1 /*
2  * Copyright 2010, 2012 Christian Costa
3  * Copyright 2012 André Hentschel
4  * Copyright 2011-2014 Henri Verbeet for CodeWeavers
5  * Copyright 2014-2015 Aaryaman Vasishta
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21 
22 #include <limits.h>
23 
24 #define COBJMACROS
25 #define _USE_MATH_DEFINES
26 #include <d3d.h>
27 #include <initguid.h>
28 #include <d3drm.h>
29 #include <d3drmwin.h>
30 #include <math.h>
31 
32 #include "wine/test.h"
33 
34 #define CHECK_REFCOUNT(obj,rc) \
35     { \
36         int rc_new = rc; \
37         int count = get_refcount( (IUnknown *)obj ); \
38         ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
39     }
40 
get_refcount(IUnknown * object)41 static ULONG get_refcount(IUnknown *object)
42 {
43     IUnknown_AddRef( object );
44     return IUnknown_Release( object );
45 }
46 
compare_float(float f,float g,unsigned int ulps)47 static BOOL compare_float(float f, float g, unsigned int ulps)
48 {
49     int x = *(int *)&f;
50     int y = *(int *)&g;
51 
52     if (x < 0)
53         x = INT_MIN - x;
54     if (y < 0)
55         y = INT_MIN - y;
56 
57     if (abs(x - y) > ulps)
58         return FALSE;
59 
60     return TRUE;
61 }
62 
63 #define expect_matrix(m, m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44, u) \
64         expect_matrix_(__LINE__, m, m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44, u)
expect_matrix_(unsigned int line,D3DRMMATRIX4D m,float m11,float m12,float m13,float m14,float m21,float m22,float m23,float m24,float m31,float m32,float m33,float m34,float m41,float m42,float m43,float m44,unsigned int ulps)65 static void expect_matrix_(unsigned int line, D3DRMMATRIX4D m,
66         float m11, float m12, float m13, float m14, float m21, float m22, float m23, float m24,
67         float m31, float m32, float m33, float m34, float m41, float m42, float m43, float m44,
68         unsigned int ulps)
69 {
70     BOOL equal = compare_float(m[0][0], m11, ulps) && compare_float(m[0][1], m12, ulps)
71             && compare_float(m[0][2], m13, ulps) && compare_float(m[0][3], m14, ulps)
72             && compare_float(m[1][0], m21, ulps) && compare_float(m[1][1], m22, ulps)
73             && compare_float(m[1][2], m23, ulps) && compare_float(m[1][3], m24, ulps)
74             && compare_float(m[2][0], m31, ulps) && compare_float(m[2][1], m32, ulps)
75             && compare_float(m[2][2], m33, ulps) && compare_float(m[2][3], m34, ulps)
76             && compare_float(m[3][0], m41, ulps) && compare_float(m[3][1], m42, ulps)
77             && compare_float(m[3][2], m43, ulps) && compare_float(m[3][3], m44, ulps);
78 
79     ok_(__FILE__, line)(equal,
80             "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e, %.8e, %.8e, "
81             "%.8e, %.8e, %.8e, %.8e, %.8e, %.8e, %.8e, %.8e}, "
82             "expected {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e, %.8e, %.8e, "
83             "%.8e, %.8e, %.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
84             m[0][0], m[0][1], m[0][2], m[0][3], m[1][0], m[1][1], m[1][2], m[1][3],
85             m[2][0], m[2][1], m[2][2], m[2][3], m[3][0], m[3][1], m[3][2], m[3][3],
86             m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44);
87 }
88 
89 #define expect_vector(v, x, y, z, u) expect_vector_(__LINE__, v, x, y, z, u)
expect_vector_(unsigned int line,const D3DVECTOR * v,float x,float y,float z,unsigned int ulps)90 static void expect_vector_(unsigned int line, const D3DVECTOR *v, float x, float y, float z, unsigned int ulps)
91 {
92     BOOL equal = compare_float(U1(*v).x, x, ulps)
93             && compare_float(U2(*v).y, y, ulps)
94             && compare_float(U3(*v).z, z, ulps);
95 
96     ok_(__FILE__, line)(equal, "Got unexpected vector {%.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e}.\n",
97             U1(*v).x, U2(*v).y, U3(*v).z, x, y, z);
98 }
99 
100 #define vector_eq(a, b) vector_eq_(__LINE__, a, b)
vector_eq_(unsigned int line,const D3DVECTOR * left,const D3DVECTOR * right)101 static void vector_eq_(unsigned int line, const D3DVECTOR *left, const D3DVECTOR *right)
102 {
103     expect_vector_(line, left, U1(*right).x, U2(*right).y, U3(*right).z, 0);
104 }
105 
106 static D3DRMMATRIX4D identity = {
107     { 1.0f, 0.0f, 0.0f, 0.0f },
108     { 0.0f, 1.0f, 0.0f, 0.0f },
109     { 0.0f, 0.0f, 1.0f, 0.0f },
110     { 0.0f, 0.0f, 0.0f, 1.0f }
111 };
112 
frame_set_transform(IDirect3DRMFrame * frame,float m11,float m12,float m13,float m14,float m21,float m22,float m23,float m24,float m31,float m32,float m33,float m34,float m41,float m42,float m43,float m44)113 static void frame_set_transform(IDirect3DRMFrame *frame,
114         float m11, float m12, float m13, float m14, float m21, float m22, float m23, float m24,
115         float m31, float m32, float m33, float m34, float m41, float m42, float m43, float m44)
116 {
117     D3DRMMATRIX4D matrix =
118     {
119         {m11, m12, m13, m14},
120         {m21, m22, m23, m24},
121         {m31, m32, m33, m34},
122         {m41, m42, m43, m44},
123     };
124 
125     IDirect3DRMFrame_AddTransform(frame, D3DRMCOMBINE_REPLACE, matrix);
126 }
127 
set_vector(D3DVECTOR * v,float x,float y,float z)128 static void set_vector(D3DVECTOR *v, float x, float y, float z)
129 {
130     U1(*v).x = x;
131     U2(*v).y = y;
132     U3(*v).z = z;
133 }
134 
matrix_sanitise(D3DRMMATRIX4D m)135 static void matrix_sanitise(D3DRMMATRIX4D m)
136 {
137     unsigned int i, j;
138 
139     for (i = 0; i < 4; ++i)
140     {
141         for (j = 0; j < 4; ++j)
142         {
143             if (m[i][j] > -1e-7f && m[i][j] < 1e-7f)
144                 m[i][j] = 0.0f;
145         }
146     }
147 }
148 
create_window(void)149 static HWND create_window(void)
150 {
151     RECT r = {0, 0, 640, 480};
152 
153     AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE);
154 
155     return CreateWindowA("static", "d3drm_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
156             CW_USEDEFAULT, CW_USEDEFAULT, r.right - r.left, r.bottom - r.top, NULL, NULL, NULL, NULL);
157 }
158 
159 #define test_class_name(a, b) test_class_name_(__LINE__, a, b)
test_class_name_(unsigned int line,IDirect3DRMObject * object,const char * name)160 static void test_class_name_(unsigned int line, IDirect3DRMObject *object, const char *name)
161 {
162     char cname[64] = {0};
163     DWORD size, size2;
164     HRESULT hr;
165 
166     hr = IDirect3DRMObject_GetClassName(object, NULL, cname);
167     ok_(__FILE__, line)(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
168     hr = IDirect3DRMViewport_GetClassName(object, NULL, NULL);
169     ok_(__FILE__, line)(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
170 
171     size = 0;
172     hr = IDirect3DRMObject_GetClassName(object, &size, NULL);
173     ok_(__FILE__, line)(hr == D3DRM_OK, "Failed to get classname size, hr %#x.\n", hr);
174     ok_(__FILE__, line)(size == strlen(name) + 1, "wrong size: %u\n", size);
175 
176     size = size2 = !!*name;
177     hr = IDirect3DRMObject_GetClassName(object, &size, cname);
178     ok_(__FILE__, line)(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
179     ok_(__FILE__, line)(size == size2, "Got size %u.\n", size);
180 
181     size = sizeof(cname);
182     hr = IDirect3DRMObject_GetClassName(object, &size, cname);
183     ok_(__FILE__, line)(hr == D3DRM_OK, "Failed to get classname, hr %#x.\n", hr);
184     ok_(__FILE__, line)(size == strlen(name) + 1, "wrong size: %u\n", size);
185     ok_(__FILE__, line)(!strcmp(cname, name), "Expected cname to be \"%s\", but got \"%s\".\n", name, cname);
186 
187     size = strlen(name) + 1;
188     hr = IDirect3DRMObject_GetClassName(object, &size, cname);
189     ok_(__FILE__, line)(hr == D3DRM_OK, "Failed to get classname, hr %#x.\n", hr);
190     ok_(__FILE__, line)(size == strlen(name) + 1, "wrong size: %u\n", size);
191     ok_(__FILE__, line)(!strcmp(cname, name), "Expected cname to be \"%s\", but got \"%s\".\n", name, cname);
192 
193     size = strlen(name);
194     strcpy(cname, "XXX");
195     hr = IDirect3DRMObject_GetClassName(object, &size, cname);
196     ok_(__FILE__, line)(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
197     ok_(__FILE__, line)(size == strlen(name), "Wrong classname size: %u.\n", size);
198     ok_(__FILE__, line)(!strcmp(cname, "XXX"), "Expected unchanged buffer, but got \"%s\".\n", cname);
199 }
200 
201 #define test_object_name(a) test_object_name_(__LINE__, a)
test_object_name_(unsigned int line,IDirect3DRMObject * object)202 static void test_object_name_(unsigned int line, IDirect3DRMObject *object)
203 {
204     char name[64] = {0};
205     HRESULT hr;
206     DWORD size;
207 
208     hr = IDirect3DRMObject_GetName(object, NULL, NULL);
209     ok_(__FILE__, line)(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
210 
211     name[0] = 0x1f;
212     hr = IDirect3DRMObject_GetName(object, NULL, name);
213     ok_(__FILE__, line)(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
214     ok_(__FILE__, line)(name[0] == 0x1f, "Unexpected buffer contents, %#x.\n", name[0]);
215 
216     /* Name is not set yet. */
217     size = 100;
218     hr = IDirect3DRMObject_GetName(object, &size, NULL);
219     ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to get name size, hr %#x.\n", hr);
220     ok_(__FILE__, line)(size == 0, "Unexpected size %u.\n", size);
221 
222     size = sizeof(name);
223     name[0] = 0x1f;
224     hr = IDirect3DRMObject_GetName(object, &size, name);
225     ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to get name size, hr %#x.\n", hr);
226     ok_(__FILE__, line)(size == 0, "Unexpected size %u.\n", size);
227     ok_(__FILE__, line)(name[0] == 0, "Unexpected name \"%s\".\n", name);
228 
229     size = 0;
230     name[0] = 0x1f;
231     hr = IDirect3DRMObject_GetName(object, &size, name);
232     ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to get name size, hr %#x.\n", hr);
233     ok_(__FILE__, line)(size == 0, "Unexpected size %u.\n", size);
234     ok_(__FILE__, line)(name[0] == 0x1f, "Unexpected name \"%s\".\n", name);
235 
236     hr = IDirect3DRMObject_SetName(object, NULL);
237     ok_(__FILE__, line)(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
238 
239     hr = IDirect3DRMObject_SetName(object, "name");
240     ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to set a name, hr %#x.\n", hr);
241 
242     size = 0;
243     hr = IDirect3DRMObject_GetName(object, &size, NULL);
244     ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to get name size, hr %#x.\n", hr);
245     ok_(__FILE__, line)(size == strlen("name") + 1, "Unexpected size %u.\n", size);
246 
247     size = strlen("name") + 1;
248     hr = IDirect3DRMObject_GetName(object, &size, name);
249     ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to get name size, hr %#x.\n", hr);
250     ok_(__FILE__, line)(size == strlen("name") + 1, "Unexpected size %u.\n", size);
251     ok_(__FILE__, line)(!strcmp(name, "name"), "Unexpected name \"%s\".\n", name);
252 
253     size = 2;
254     name[0] = 0x1f;
255     hr = IDirect3DRMObject_GetName(object, &size, name);
256     ok_(__FILE__, line)(hr == E_INVALIDARG, "Failed to get object name, hr %#x.\n", hr);
257     ok_(__FILE__, line)(size == 2, "Unexpected size %u.\n", size);
258     ok_(__FILE__, line)(name[0] == 0x1f, "Got unexpected name \"%s\".\n", name);
259 
260     hr = IDirect3DRMObject_SetName(object, NULL);
261     ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to set object name, hr %#x.\n", hr);
262 
263     size = 1;
264     hr = IDirect3DRMObject_GetName(object, &size, NULL);
265     ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to get name size, hr %#x.\n", hr);
266     ok_(__FILE__, line)(size == 0, "Unexpected size %u.\n", size);
267 
268     size = 1;
269     name[0] = 0x1f;
270     hr = IDirect3DRMObject_GetName(object, &size, name);
271     ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to get name size, hr %#x.\n", hr);
272     ok_(__FILE__, line)(size == 0, "Unexpected size %u.\n", size);
273     ok_(__FILE__, line)(name[0] == 0, "Got unexpected name \"%s\".\n", name);
274 }
275 
276 static char data_bad_version[] =
277 "xof 0302txt 0064\n"
278 "Header Object\n"
279 "{\n"
280 "1; 2; 3;\n"
281 "}\n";
282 
283 static char data_no_mesh[] =
284 "xof 0302txt 0064\n"
285 "Header Object\n"
286 "{\n"
287 "1; 0; 1;\n"
288 "}\n";
289 
290 static char data_ok[] =
291 "xof 0302txt 0064\n"
292 "Header Object\n"
293 "{\n"
294 "1; 0; 1;\n"
295 "}\n"
296 "Mesh Object\n"
297 "{\n"
298 "4;\n"
299 "1.0; 0.0; 0.0;,\n"
300 "0.0; 1.0; 0.0;,\n"
301 "0.0; 0.0; 1.0;,\n"
302 "1.0; 1.0; 1.0;;\n"
303 "3;\n"
304 "3; 0, 1, 2;,\n"
305 "3; 1, 2, 3;,\n"
306 "3; 3, 1, 2;;\n"
307 "}\n";
308 
309 static char data_full[] =
310 "xof 0302txt 0064\n"
311 "Header { 1; 0; 1; }\n"
312 "Mesh {\n"
313 " 3;\n"
314 " 0.1; 0.2; 0.3;,\n"
315 " 0.4; 0.5; 0.6;,\n"
316 " 0.7; 0.8; 0.9;;\n"
317 " 1;\n"
318 " 3; 0, 1, 2;;\n"
319 " MeshMaterialList {\n"
320 "  1; 1; 0;\n"
321 "  Material {\n"
322 "   0.0; 1.0; 0.0; 1.0;;\n"
323 "   30.0;\n"
324 "   1.0; 0.0; 0.0;;\n"
325 "   0.5; 0.5; 0.5;;\n"
326 "   TextureFileName {\n"
327 "    \"Texture.bmp\";\n"
328 "   }\n"
329 "  }\n"
330 " }\n"
331 " MeshNormals {\n"
332 "  3;\n"
333 "  1.1; 1.2; 1.3;,\n"
334 "  1.4; 1.5; 1.6;,\n"
335 "  1.7; 1.8; 1.9;;\n"
336 "  1;"
337 "  3; 0, 1, 2;;\n"
338 " }\n"
339 " MeshTextureCoords {\n"
340 "  3;\n"
341 "  0.13; 0.17;,\n"
342 "  0.23; 0.27;,\n"
343 "  0.33; 0.37;;\n"
344 " }\n"
345 "}\n";
346 
347 static char data_d3drm_load[] =
348 "xof 0302txt 0064\n"
349 "Header Object\n"
350 "{\n"
351 "1; 0; 1;\n"
352 "}\n"
353 "Mesh Object1\n"
354 "{\n"
355 " 1;\n"
356 " 0.1; 0.2; 0.3;,\n"
357 " 1;\n"
358 " 3; 0, 1, 2;;\n"
359 "}\n"
360 "Mesh Object2\n"
361 "{\n"
362 " 1;\n"
363 " 0.1; 0.2; 0.3;,\n"
364 " 1;\n"
365 " 3; 0, 1, 2;;\n"
366 "}\n"
367 "Frame Scene\n"
368 "{\n"
369 " {Object1}\n"
370 " {Object2}\n"
371 "}\n"
372 "Material\n"
373 "{\n"
374 " 0.1, 0.2, 0.3, 0.4;;\n"
375 " 0.5;\n"
376 " 0.6, 0.7, 0.8;;\n"
377 " 0.9, 1.0, 1.1;;\n"
378 "}\n";
379 
380 static char data_frame_mesh_materials[] =
381 "xof 0302txt 0064\n"
382 "Header { 1; 0; 1; }\n"
383 "Frame {\n"
384 " Mesh mesh1 {\n"
385 "  5;\n"
386 "  0.1; 0.2; 0.3;,\n"
387 "  0.4; 0.5; 0.6;,\n"
388 "  0.7; 0.8; 0.9;,\n"
389 "  1.1; 1.2; 1.3;,\n"
390 "  1.4; 1.5; 1.6;;\n"
391 "  6;\n"
392 "  3; 0, 1, 2;,\n"
393 "  3; 0, 2, 1;,\n"
394 "  3; 1, 2, 3;,\n"
395 "  3; 1, 3, 2;,\n"
396 "  3; 2, 3, 4;,\n"
397 "  3; 2, 4, 3;;\n"
398 "  MeshMaterialList {\n"
399 "   3; 6; 0, 1, 1, 2, 2, 2;\n"
400 "   Material mat1 {\n"
401 "    1.0; 0.0; 0.0; 0.1;;\n"
402 "    10.0;\n"
403 "    0.11; 0.12; 0.13;;\n"
404 "    0.14; 0.15; 0.16;;\n"
405 "   }\n"
406 "   Material mat2 {\n"
407 "    0.0; 1.0; 0.0; 0.2;;\n"
408 "    20.0;\n"
409 "    0.21; 0.22; 0.23;;\n"
410 "    0.24; 0.25; 0.26;;\n"
411 "   }\n"
412 "   Material mat3 {\n"
413 "    0.0; 0.0; 1.0; 0.3;;\n"
414 "    30.0;\n"
415 "    0.31; 0.32; 0.33;;\n"
416 "    0.34; 0.35; 0.36;;\n"
417 "   }\n"
418 "  }\n"
419 " }\n"
420 "}\n";
421 
test_MeshBuilder(void)422 static void test_MeshBuilder(void)
423 {
424     HRESULT hr;
425     IDirect3DRM *d3drm;
426     IDirect3DRMMeshBuilder *pMeshBuilder;
427     IDirect3DRMMeshBuilder3 *meshbuilder3;
428     IDirect3DRMMesh *mesh;
429     D3DRMLOADMEMORY info;
430     int val;
431     DWORD val1, val2, val3;
432     D3DVALUE valu, valv;
433     D3DVECTOR v[3];
434     D3DVECTOR n[4];
435     DWORD f[8];
436     char name[10];
437     DWORD size;
438     D3DCOLOR color;
439     IUnknown *unk;
440 
441     hr = Direct3DRMCreate(&d3drm);
442     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x)\n", hr);
443 
444     hr = IDirect3DRM_CreateMeshBuilder(d3drm, &pMeshBuilder);
445     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMMeshBuilder interface (hr = %x)\n", hr);
446 
447     hr = IDirect3DRMMeshBuilder_QueryInterface(pMeshBuilder, &IID_IDirect3DRMObject, (void **)&unk);
448     ok(SUCCEEDED(hr), "Failed to get IDirect3DRMObject, %#x.\n", hr);
449     ok(unk == (IUnknown *)pMeshBuilder, "Unexpected interface pointer.\n");
450     IUnknown_Release(unk);
451 
452     hr = IDirect3DRMMeshBuilder_QueryInterface(pMeshBuilder, &IID_IDirect3DRMVisual, (void **)&unk);
453     ok(SUCCEEDED(hr), "Failed to get IDirect3DRMVisual, %#x.\n", hr);
454     ok(unk == (IUnknown *)pMeshBuilder, "Unexpected interface pointer.\n");
455     IUnknown_Release(unk);
456 
457     hr = IDirect3DRMMeshBuilder_QueryInterface(pMeshBuilder, &IID_IDirect3DRMMeshBuilder3, (void **)&meshbuilder3);
458     ok(SUCCEEDED(hr), "Failed to get IDirect3DRMMeshBuilder3, %#x.\n", hr);
459 
460     hr = IDirect3DRMMeshBuilder3_QueryInterface(meshbuilder3, &IID_IDirect3DRMObject, (void **)&unk);
461     ok(SUCCEEDED(hr), "Failed to get IDirect3DRMObject, %#x.\n", hr);
462     ok(unk == (IUnknown *)pMeshBuilder, "Unexpected interface pointer.\n");
463     IUnknown_Release(unk);
464 
465     hr = IDirect3DRMMeshBuilder3_QueryInterface(meshbuilder3, &IID_IDirect3DRMVisual, (void **)&unk);
466     ok(SUCCEEDED(hr), "Failed to get IDirect3DRMVisual, %#x.\n", hr);
467     ok(unk == (IUnknown *)pMeshBuilder, "Unexpected interface pointer.\n");
468     IUnknown_Release(unk);
469 
470     IDirect3DRMMeshBuilder3_Release(meshbuilder3);
471 
472     test_class_name((IDirect3DRMObject *)pMeshBuilder, "Builder");
473     test_object_name((IDirect3DRMObject *)pMeshBuilder);
474 
475     info.lpMemory = data_bad_version;
476     info.dSize = strlen(data_bad_version);
477     hr = IDirect3DRMMeshBuilder_Load(pMeshBuilder, &info, NULL, D3DRMLOAD_FROMMEMORY, NULL, NULL);
478     ok(hr == D3DRMERR_BADFILE, "Should have returned D3DRMERR_BADFILE (hr = %x)\n", hr);
479 
480     info.lpMemory = data_no_mesh;
481     info.dSize = strlen(data_no_mesh);
482     hr = IDirect3DRMMeshBuilder_Load(pMeshBuilder, &info, NULL, D3DRMLOAD_FROMMEMORY, NULL, NULL);
483     ok(hr == D3DRMERR_NOTFOUND, "Should have returned D3DRMERR_NOTFOUND (hr = %x)\n", hr);
484 
485     info.lpMemory = data_ok;
486     info.dSize = strlen(data_ok);
487     hr = IDirect3DRMMeshBuilder_Load(pMeshBuilder, &info, NULL, D3DRMLOAD_FROMMEMORY, NULL, NULL);
488     ok(hr == D3DRM_OK, "Cannot load mesh data (hr = %x)\n", hr);
489 
490     size = sizeof(name);
491     hr = IDirect3DRMMeshBuilder_GetName(pMeshBuilder, &size, name);
492     ok(hr == D3DRM_OK, "IDirect3DRMMeshBuilder_GetName returned hr = %x\n", hr);
493     ok(!strcmp(name, "Object"), "Retrieved name '%s' instead of 'Object'\n", name);
494     size = strlen("Object"); /* No space for null character */
495     hr = IDirect3DRMMeshBuilder_GetName(pMeshBuilder, &size, name);
496     ok(hr == E_INVALIDARG, "IDirect3DRMMeshBuilder_GetName returned hr = %x\n", hr);
497     hr = IDirect3DRMMeshBuilder_SetName(pMeshBuilder, NULL);
498     ok(hr == D3DRM_OK, "IDirect3DRMMeshBuilder_SetName returned hr = %x\n", hr);
499     size = sizeof(name);
500     hr = IDirect3DRMMeshBuilder_GetName(pMeshBuilder, &size, name);
501     ok(hr == D3DRM_OK, "IDirect3DRMMeshBuilder_GetName returned hr = %x\n", hr);
502     ok(size == 0, "Size should be 0 instead of %u\n", size);
503     hr = IDirect3DRMMeshBuilder_SetName(pMeshBuilder, "");
504     ok(hr == D3DRM_OK, "IDirect3DRMMeshBuilder_SetName returned hr = %x\n", hr);
505     size = sizeof(name);
506     hr = IDirect3DRMMeshBuilder_GetName(pMeshBuilder, &size, name);
507     ok(hr == D3DRM_OK, "IDirect3DRMMeshBuilder_GetName returned hr = %x\n", hr);
508     ok(!strcmp(name, ""), "Retrieved name '%s' instead of ''\n", name);
509 
510     val = IDirect3DRMMeshBuilder_GetVertexCount(pMeshBuilder);
511     ok(val == 4, "Wrong number of vertices %d (must be 4)\n", val);
512 
513     val = IDirect3DRMMeshBuilder_GetFaceCount(pMeshBuilder);
514     ok(val == 3, "Wrong number of faces %d (must be 3)\n", val);
515 
516     hr = IDirect3DRMMeshBuilder_GetVertices(pMeshBuilder, &val1, NULL, &val2, NULL, &val3, NULL);
517     ok(hr == D3DRM_OK, "Cannot get vertices information (hr = %x)\n", hr);
518     ok(val1 == 4, "Wrong number of vertices %d (must be 4)\n", val1);
519     ok(val2 == 4, "Wrong number of normals %d (must be 4)\n", val2);
520     ok(val3 == 22, "Wrong number of face data bytes %d (must be 22)\n", val3);
521 
522     /* Check that Load method generated default normals */
523     hr = IDirect3DRMMeshBuilder_GetVertices(pMeshBuilder, NULL, NULL, &val2, n, NULL, NULL);
524     ok(hr == D3DRM_OK, "Cannot get vertices information (hr = %x)\n", hr);
525     expect_vector(&n[0],  0.577350f, 0.577350f, 0.577350f, 32);
526     expect_vector(&n[1], -0.229416f, 0.688247f, 0.688247f, 32);
527     expect_vector(&n[2], -0.229416f, 0.688247f, 0.688247f, 32);
528     expect_vector(&n[3], -0.577350f, 0.577350f, 0.577350f, 32);
529 
530     /* Check that Load method generated default texture coordinates (0.0f, 0.0f) for each vertex */
531     valu = 1.23f;
532     valv = 3.21f;
533     hr = IDirect3DRMMeshBuilder_GetTextureCoordinates(pMeshBuilder, 0, &valu, &valv);
534     ok(hr == D3DRM_OK, "Cannot get texture coordinates (hr = %x)\n", hr);
535     ok(valu == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valu);
536     ok(valv == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valv);
537     valu = 1.23f;
538     valv = 3.21f;
539     hr = IDirect3DRMMeshBuilder_GetTextureCoordinates(pMeshBuilder, 1, &valu, &valv);
540     ok(hr == D3DRM_OK, "Cannot get texture coordinates (hr = %x)\n", hr);
541     ok(valu == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valu);
542     ok(valv == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valv);
543     valu = 1.23f;
544     valv = 3.21f;
545     hr = IDirect3DRMMeshBuilder_GetTextureCoordinates(pMeshBuilder, 2, &valu, &valv);
546     ok(hr == D3DRM_OK, "Cannot get texture coordinates (hr = %x)\n", hr);
547     ok(valu == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valu);
548     ok(valv == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valv);
549     valu = 1.23f;
550     valv = 3.21f;
551     hr = IDirect3DRMMeshBuilder_GetTextureCoordinates(pMeshBuilder, 3, &valu, &valv);
552     ok(hr == D3DRM_OK, "Cannot get texture coordinates (hr = %x)\n", hr);
553     ok(valu == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valu);
554     ok(valv == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valv);
555     hr = IDirect3DRMMeshBuilder_GetTextureCoordinates(pMeshBuilder, 4, &valu, &valv);
556     ok(hr == D3DRMERR_BADVALUE, "Should fail and return D3DRM_BADVALUE (hr = %x)\n", hr);
557 
558     valu = 1.23f;
559     valv = 3.21f;
560     hr = IDirect3DRMMeshBuilder_SetTextureCoordinates(pMeshBuilder, 0, valu, valv);
561     ok(hr == D3DRM_OK, "Cannot set texture coordinates (hr = %x)\n", hr);
562     hr = IDirect3DRMMeshBuilder_SetTextureCoordinates(pMeshBuilder, 4, valu, valv);
563     ok(hr == D3DRMERR_BADVALUE, "Should fail and return D3DRM_BADVALUE (hr = %x)\n", hr);
564 
565     valu = 0.0f;
566     valv = 0.0f;
567     hr = IDirect3DRMMeshBuilder_GetTextureCoordinates(pMeshBuilder, 0, &valu, &valv);
568     ok(hr == D3DRM_OK, "Cannot get texture coordinates (hr = %x)\n", hr);
569     ok(valu == 1.23f, "Wrong coordinate %f (must be 1.23)\n", valu);
570     ok(valv == 3.21f, "Wrong coordinate %f (must be 3.21)\n", valv);
571 
572     IDirect3DRMMeshBuilder_Release(pMeshBuilder);
573 
574     hr = IDirect3DRM_CreateMeshBuilder(d3drm, &pMeshBuilder);
575     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMMeshBuilder interface (hr = %x)\n", hr);
576 
577     /* No group in mesh when mesh builder is not loaded */
578     hr = IDirect3DRMMeshBuilder_CreateMesh(pMeshBuilder, &mesh);
579     ok(hr == D3DRM_OK, "CreateMesh failed returning hr = %x\n", hr);
580     if (hr == D3DRM_OK)
581     {
582         DWORD nb_groups;
583 
584         nb_groups = IDirect3DRMMesh_GetGroupCount(mesh);
585         ok(nb_groups == 0, "GetCroupCount returned %u\n", nb_groups);
586 
587         IDirect3DRMMesh_Release(mesh);
588     }
589 
590     info.lpMemory = data_full;
591     info.dSize = strlen(data_full);
592     hr = IDirect3DRMMeshBuilder_Load(pMeshBuilder, &info, NULL, D3DRMLOAD_FROMMEMORY, NULL, NULL);
593     ok(hr == D3DRM_OK, "Cannot load mesh data (hr = %x)\n", hr);
594 
595     val = IDirect3DRMMeshBuilder_GetVertexCount(pMeshBuilder);
596     ok(val == 3, "Wrong number of vertices %d (must be 3)\n", val);
597 
598     val = IDirect3DRMMeshBuilder_GetFaceCount(pMeshBuilder);
599     ok(val == 1, "Wrong number of faces %d (must be 1)\n", val);
600 
601     /* Check no buffer size and too small buffer size errors */
602     val1 = 1; val2 = 3; val3 = 8;
603     hr = IDirect3DRMMeshBuilder_GetVertices(pMeshBuilder, &val1, v, &val2, n, &val3, f);
604     ok(hr == D3DRMERR_BADVALUE, "IDirect3DRMMeshBuilder_GetVertices returned %#x\n", hr);
605     hr = IDirect3DRMMeshBuilder_GetVertices(pMeshBuilder, NULL, v, &val2, n, &val3, f);
606     ok(hr == D3DRMERR_BADVALUE, "IDirect3DRMMeshBuilder_GetVertices returned %#x\n", hr);
607     val1 = 3; val2 = 1; val3 = 8;
608     hr = IDirect3DRMMeshBuilder_GetVertices(pMeshBuilder, &val1, v, &val2, n, &val3, f);
609     ok(hr == D3DRMERR_BADVALUE, "IDirect3DRMMeshBuilder_GetVertices returned %#x\n", hr);
610     hr = IDirect3DRMMeshBuilder_GetVertices(pMeshBuilder, &val1, v, NULL, n, &val3, f);
611     ok(hr == D3DRMERR_BADVALUE, "IDirect3DRMMeshBuilder_GetVertices returned %#x\n", hr);
612     val1 = 3; val2 = 3; val3 = 1;
613     hr = IDirect3DRMMeshBuilder_GetVertices(pMeshBuilder, &val1, v, &val2, n, &val3, f);
614     ok(hr == D3DRMERR_BADVALUE, "IDirect3DRMMeshBuilder_GetVertices returned %#x\n", hr);
615     hr = IDirect3DRMMeshBuilder_GetVertices(pMeshBuilder, &val1, v, &val2, n, NULL, f);
616     ok(hr == D3DRMERR_BADVALUE, "IDirect3DRMMeshBuilder_GetVertices returned %#x\n", hr);
617 
618     val1 = 3; val2 = 3; val3 = 8;
619     hr = IDirect3DRMMeshBuilder_GetVertices(pMeshBuilder, &val1, v, &val2, n, &val3, f);
620     ok(hr == D3DRM_OK, "Cannot get vertices information (hr = %x)\n", hr);
621     ok(val1 == 3, "Wrong number of vertices %d (must be 3)\n", val1);
622     ok(val2 == 3, "Wrong number of normals %d (must be 3)\n", val2);
623     ok(val3 == 8, "Wrong number of face data bytes %d (must be 8)\n", val3);
624     expect_vector(&v[0], 0.1f, 0.2f, 0.3f, 32);
625     expect_vector(&v[1], 0.4f, 0.5f, 0.6f, 32);
626     expect_vector(&v[2], 0.7f, 0.8f, 0.9f, 32);
627     expect_vector(&n[0], 1.1f, 1.2f, 1.3f, 32);
628     expect_vector(&n[1], 1.4f, 1.5f, 1.6f, 32);
629     expect_vector(&n[2], 1.7f, 1.8f, 1.9f, 32);
630     ok(f[0] == 3 , "Wrong component f[0] = %d (expected 3)\n", f[0]);
631     ok(f[1] == 0 , "Wrong component f[1] = %d (expected 0)\n", f[1]);
632     ok(f[2] == 0 , "Wrong component f[2] = %d (expected 0)\n", f[2]);
633     ok(f[3] == 1 , "Wrong component f[3] = %d (expected 1)\n", f[3]);
634     ok(f[4] == 1 , "Wrong component f[4] = %d (expected 1)\n", f[4]);
635     ok(f[5] == 2 , "Wrong component f[5] = %d (expected 2)\n", f[5]);
636     ok(f[6] == 2 , "Wrong component f[6] = %d (expected 2)\n", f[6]);
637     ok(f[7] == 0 , "Wrong component f[7] = %d (expected 0)\n", f[7]);
638 
639     hr = IDirect3DRMMeshBuilder_CreateMesh(pMeshBuilder, &mesh);
640     ok(hr == D3DRM_OK, "CreateMesh failed returning hr = %x\n", hr);
641     if (hr == D3DRM_OK)
642     {
643         DWORD nb_groups;
644         unsigned nb_vertices, nb_faces, nb_face_vertices;
645         DWORD data_size;
646         IDirect3DRMMaterial *material = (IDirect3DRMMaterial *)0xdeadbeef;
647         IDirect3DRMTexture *texture = (IDirect3DRMTexture *)0xdeadbeef;
648         D3DVALUE values[3];
649 
650         nb_groups = IDirect3DRMMesh_GetGroupCount(mesh);
651         ok(nb_groups == 1, "GetCroupCount returned %u\n", nb_groups);
652         hr = IDirect3DRMMesh_GetGroup(mesh, 1, &nb_vertices, &nb_faces, &nb_face_vertices, &data_size, NULL);
653         ok(hr == D3DRMERR_BADVALUE, "GetCroup returned hr = %x\n", hr);
654         hr = IDirect3DRMMesh_GetGroup(mesh, 0, &nb_vertices, &nb_faces, &nb_face_vertices, &data_size, NULL);
655         ok(hr == D3DRM_OK, "GetCroup failed returning hr = %x\n", hr);
656         ok(nb_vertices == 3, "Wrong number of vertices %u (must be 3)\n", nb_vertices);
657         ok(nb_faces == 1, "Wrong number of faces %u (must be 1)\n", nb_faces);
658         ok(nb_face_vertices == 3, "Wrong number of vertices per face %u (must be 3)\n", nb_face_vertices);
659         ok(data_size == 3, "Wrong number of face data bytes %u (must be 3)\n", data_size);
660         color = IDirect3DRMMesh_GetGroupColor(mesh, 0);
661         ok(color == 0xff00ff00, "Wrong color returned %#x instead of %#x\n", color, 0xff00ff00);
662         hr = IDirect3DRMMesh_GetGroupTexture(mesh, 0, &texture);
663         ok(hr == D3DRM_OK, "GetCroupTexture failed returning hr = %x\n", hr);
664         ok(texture == NULL, "No texture should be present\n");
665         hr = IDirect3DRMMesh_GetGroupMaterial(mesh, 0, &material);
666         ok(hr == D3DRM_OK, "GetCroupMaterial failed returning hr = %x\n", hr);
667         ok(material != NULL, "No material present\n");
668         hr = IDirect3DRMMaterial_GetEmissive(material, &values[0], &values[1], &values[2]);
669         ok(hr == D3DRM_OK, "Failed to get emissive color, hr %#x.\n", hr);
670         ok(values[0] == 0.5f, "Got unexpected red component %.8e.\n", values[0]);
671         ok(values[1] == 0.5f, "Got unexpected green component %.8e.\n", values[1]);
672         ok(values[2] == 0.5f, "Got unexpected blue component %.8e.\n", values[2]);
673         hr = IDirect3DRMMaterial_GetSpecular(material, &values[0], &values[1], &values[2]);
674         ok(hr == D3DRM_OK, "Failed to get specular color, hr %#x.\n", hr);
675         ok(values[0] == 1.0f, "Got unexpected red component %.8e.\n", values[0]);
676         ok(values[1] == 0.0f, "Got unexpected green component %.8e.\n", values[1]);
677         ok(values[2] == 0.0f, "Got unexpected blue component %.8e.\n", values[2]);
678         values[0] = IDirect3DRMMaterial_GetPower(material);
679         ok(values[0] == 30.0f, "Got unexpected power value %.8e.\n", values[0]);
680         IDirect3DRMMaterial_Release(material);
681 
682         IDirect3DRMMesh_Release(mesh);
683     }
684 
685     hr = IDirect3DRMMeshBuilder_Scale(pMeshBuilder, 2, 3 ,4);
686     ok(hr == D3DRM_OK, "Scale failed returning hr = %x\n", hr);
687 
688     hr = IDirect3DRMMeshBuilder_GetVertices(pMeshBuilder, &val1, v, &val2, n, &val3, f);
689     ok(hr == D3DRM_OK, "Cannot get vertices information (hr = %x)\n", hr);
690     ok(val2 == 3, "Wrong number of normals %d (must be 3)\n", val2);
691     ok(val1 == 3, "Wrong number of vertices %d (must be 3)\n", val1);
692 
693     expect_vector(&v[0], 0.1f * 2, 0.2f * 3, 0.3f * 4, 32);
694     expect_vector(&v[1], 0.4f * 2, 0.5f * 3, 0.6f * 4, 32);
695     expect_vector(&v[2], 0.7f * 2, 0.8f * 3, 0.9f * 4, 32);
696     /* Normals are not affected by Scale */
697     expect_vector(&n[0], 1.1f, 1.2f, 1.3f, 32);
698     expect_vector(&n[1], 1.4f, 1.5f, 1.6f, 32);
699     expect_vector(&n[2], 1.7f, 1.8f, 1.9f, 32);
700 
701     IDirect3DRMMeshBuilder_Release(pMeshBuilder);
702 
703     IDirect3DRM_Release(d3drm);
704 }
705 
test_MeshBuilder3(void)706 static void test_MeshBuilder3(void)
707 {
708     HRESULT hr;
709     IDirect3DRM *d3drm;
710     IDirect3DRM3 *d3drm3;
711     IDirect3DRMMeshBuilder3 *pMeshBuilder3;
712     D3DRMLOADMEMORY info;
713     int val;
714     DWORD val1;
715     D3DVALUE valu, valv;
716 
717     hr = Direct3DRMCreate(&d3drm);
718     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x)\n", hr);
719 
720     if (FAILED(hr = IDirect3DRM_QueryInterface(d3drm, &IID_IDirect3DRM3, (void **)&d3drm3)))
721     {
722         win_skip("Cannot get IDirect3DRM3 interface (hr = %x), skipping tests\n", hr);
723         IDirect3DRM_Release(d3drm);
724         return;
725     }
726 
727     hr = IDirect3DRM3_CreateMeshBuilder(d3drm3, &pMeshBuilder3);
728     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMMeshBuilder3 interface (hr = %x)\n", hr);
729 
730     test_class_name((IDirect3DRMObject *)pMeshBuilder3, "Builder");
731     test_object_name((IDirect3DRMObject *)pMeshBuilder3);
732 
733     info.lpMemory = data_bad_version;
734     info.dSize = strlen(data_bad_version);
735     hr = IDirect3DRMMeshBuilder3_Load(pMeshBuilder3, &info, NULL, D3DRMLOAD_FROMMEMORY, NULL, NULL);
736     ok(hr == D3DRMERR_BADFILE, "Should have returned D3DRMERR_BADFILE (hr = %x)\n", hr);
737 
738     info.lpMemory = data_no_mesh;
739     info.dSize = strlen(data_no_mesh);
740     hr = IDirect3DRMMeshBuilder3_Load(pMeshBuilder3, &info, NULL, D3DRMLOAD_FROMMEMORY, NULL, NULL);
741     ok(hr == D3DRMERR_NOTFOUND, "Should have returned D3DRMERR_NOTFOUND (hr = %x)\n", hr);
742 
743     info.lpMemory = data_ok;
744     info.dSize = strlen(data_ok);
745     hr = IDirect3DRMMeshBuilder3_Load(pMeshBuilder3, &info, NULL, D3DRMLOAD_FROMMEMORY, NULL, NULL);
746     ok(hr == D3DRM_OK, "Cannot load mesh data (hr = %x)\n", hr);
747 
748     val = IDirect3DRMMeshBuilder3_GetVertexCount(pMeshBuilder3);
749     ok(val == 4, "Wrong number of vertices %d (must be 4)\n", val);
750 
751     val = IDirect3DRMMeshBuilder3_GetFaceCount(pMeshBuilder3);
752     ok(val == 3, "Wrong number of faces %d (must be 3)\n", val);
753 
754     hr = IDirect3DRMMeshBuilder3_GetVertices(pMeshBuilder3, 0, &val1, NULL);
755     ok(hr == D3DRM_OK, "Cannot get vertices information (hr = %x)\n", hr);
756     ok(val1 == 4, "Wrong number of vertices %d (must be 4)\n", val1);
757 
758     /* Check that Load method generated default texture coordinates (0.0f, 0.0f) for each vertex */
759     valu = 1.23f;
760     valv = 3.21f;
761     hr = IDirect3DRMMeshBuilder3_GetTextureCoordinates(pMeshBuilder3, 0, &valu, &valv);
762     ok(hr == D3DRM_OK, "Cannot get texture coordinates (hr = %x)\n", hr);
763     ok(valu == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valu);
764     ok(valv == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valv);
765     valu = 1.23f;
766     valv = 3.21f;
767     hr = IDirect3DRMMeshBuilder3_GetTextureCoordinates(pMeshBuilder3, 1, &valu, &valv);
768     ok(hr == D3DRM_OK, "Cannot get texture coordinates (hr = %x)\n", hr);
769     ok(valu == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valu);
770     ok(valv == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valv);
771     valu = 1.23f;
772     valv = 3.21f;
773     hr = IDirect3DRMMeshBuilder3_GetTextureCoordinates(pMeshBuilder3, 2, &valu, &valv);
774     ok(hr == D3DRM_OK, "Cannot get texture coordinates (hr = %x)\n", hr);
775     ok(valu == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valu);
776     ok(valv == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valv);
777     valu = 1.23f;
778     valv = 3.21f;
779     hr = IDirect3DRMMeshBuilder3_GetTextureCoordinates(pMeshBuilder3, 3, &valu, &valv);
780     ok(hr == D3DRM_OK, "Cannot get texture coordinates (hr = %x)\n", hr);
781     ok(valu == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valu);
782     ok(valv == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valv);
783     hr = IDirect3DRMMeshBuilder3_GetTextureCoordinates(pMeshBuilder3, 4, &valu, &valv);
784     ok(hr == D3DRMERR_BADVALUE, "Should fail and return D3DRM_BADVALUE (hr = %x)\n", hr);
785 
786     valu = 1.23f;
787     valv = 3.21f;
788     hr = IDirect3DRMMeshBuilder3_SetTextureCoordinates(pMeshBuilder3, 0, valu, valv);
789     ok(hr == D3DRM_OK, "Cannot set texture coordinates (hr = %x)\n", hr);
790     hr = IDirect3DRMMeshBuilder3_SetTextureCoordinates(pMeshBuilder3, 4, valu, valv);
791     ok(hr == D3DRMERR_BADVALUE, "Should fail and return D3DRM_BADVALUE (hr = %x)\n", hr);
792 
793     valu = 0.0f;
794     valv = 0.0f;
795     hr = IDirect3DRMMeshBuilder3_GetTextureCoordinates(pMeshBuilder3, 0, &valu, &valv);
796     ok(hr == D3DRM_OK, "Cannot get texture coordinates (hr = %x)\n", hr);
797     ok(valu == 1.23f, "Wrong coordinate %f (must be 1.23)\n", valu);
798     ok(valv == 3.21f, "Wrong coordinate %f (must be 3.21)\n", valv);
799 
800     IDirect3DRMMeshBuilder3_Release(pMeshBuilder3);
801     IDirect3DRM3_Release(d3drm3);
802     IDirect3DRM_Release(d3drm);
803 }
804 
test_Mesh(void)805 static void test_Mesh(void)
806 {
807     HRESULT hr;
808     IDirect3DRM *d3drm;
809     IDirect3DRMMesh *mesh;
810     IUnknown *unk;
811 
812     hr = Direct3DRMCreate(&d3drm);
813     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x)\n", hr);
814 
815     hr = IDirect3DRM_CreateMesh(d3drm, &mesh);
816     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMMesh interface (hr = %x)\n", hr);
817 
818     test_class_name((IDirect3DRMObject *)mesh, "Mesh");
819     test_object_name((IDirect3DRMObject *)mesh);
820 
821     hr = IDirect3DRMMesh_QueryInterface(mesh, &IID_IDirect3DRMObject, (void **)&unk);
822     ok(SUCCEEDED(hr), "Failed to get IDirect3DRMObject, %#x.\n", hr);
823     IUnknown_Release(unk);
824 
825     hr = IDirect3DRMMesh_QueryInterface(mesh, &IID_IDirect3DRMVisual, (void **)&unk);
826     ok(SUCCEEDED(hr), "Failed to get IDirect3DRMVisual, %#x.\n", hr);
827     IUnknown_Release(unk);
828 
829     IDirect3DRMMesh_Release(mesh);
830 
831     IDirect3DRM_Release(d3drm);
832 }
833 
test_Face(void)834 static void test_Face(void)
835 {
836     HRESULT hr;
837     IDirect3DRM *d3drm;
838     IDirect3DRM2 *d3drm2;
839     IDirect3DRM3 *d3drm3;
840     IDirect3DRMMeshBuilder2 *MeshBuilder2;
841     IDirect3DRMMeshBuilder3 *MeshBuilder3;
842     IDirect3DRMFace *face1;
843     IDirect3DRMObject *obj;
844     IDirect3DRMFace2 *face2;
845     IDirect3DRMFaceArray *array1;
846     D3DRMLOADMEMORY info;
847     D3DVECTOR v1[4], n1[4], v2[4], n2[4];
848     D3DCOLOR color;
849     DWORD count;
850     int icount;
851 
852     hr = Direct3DRMCreate(&d3drm);
853     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x)\n", hr);
854 
855     hr = IDirect3DRM_CreateFace(d3drm, &face1);
856     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMFace interface (hr = %x)\n", hr);
857     if (FAILED(hr))
858     {
859         skip("Cannot get IDirect3DRMFace interface (hr = %x), skipping tests\n", hr);
860         IDirect3DRM_Release(d3drm);
861         return;
862     }
863 
864     hr = IDirect3DRMFace_QueryInterface(face1, &IID_IDirect3DRMObject, (void **)&obj);
865     ok(SUCCEEDED(hr), "Failed to get IDirect3DRMObject, %#x.\n", hr);
866     ok(obj == (IDirect3DRMObject *)face1, "Unexpected interface pointer.\n");
867     IDirect3DRMObject_Release(obj);
868 
869     test_class_name((IDirect3DRMObject *)face1, "Face");
870     test_object_name((IDirect3DRMObject *)face1);
871 
872     icount = IDirect3DRMFace_GetVertexCount(face1);
873     ok(!icount, "wrong VertexCount: %i\n", icount);
874 
875     IDirect3DRMFace_Release(face1);
876 
877     if (FAILED(hr = IDirect3DRM_QueryInterface(d3drm, &IID_IDirect3DRM2, (void **)&d3drm2)))
878     {
879         win_skip("Cannot get IDirect3DRM2 interface (hr = %x), skipping tests\n", hr);
880         IDirect3DRM_Release(d3drm);
881         return;
882     }
883 
884     hr = IDirect3DRM2_CreateMeshBuilder(d3drm2, &MeshBuilder2);
885     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMMeshBuilder2 interface (hr = %x)\n", hr);
886 
887     icount = IDirect3DRMMeshBuilder2_GetFaceCount(MeshBuilder2);
888     ok(!icount, "wrong FaceCount: %i\n", icount);
889 
890     array1 = NULL;
891     hr = IDirect3DRMMeshBuilder2_GetFaces(MeshBuilder2, &array1);
892     todo_wine
893     ok(hr == D3DRM_OK, "Cannot get FaceArray (hr = %x)\n", hr);
894 
895     hr = IDirect3DRMMeshBuilder2_CreateFace(MeshBuilder2, &face1);
896     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMFace interface (hr = %x)\n", hr);
897 
898     icount = IDirect3DRMMeshBuilder2_GetFaceCount(MeshBuilder2);
899     todo_wine
900     ok(icount == 1, "wrong FaceCount: %i\n", icount);
901 
902     array1 = NULL;
903     hr = IDirect3DRMMeshBuilder2_GetFaces(MeshBuilder2, &array1);
904     todo_wine
905     ok(hr == D3DRM_OK, "Cannot get FaceArray (hr = %x)\n", hr);
906     todo_wine
907     ok(array1 != NULL, "pArray = %p\n", array1);
908     if (array1)
909     {
910         IDirect3DRMFace *face;
911         count = IDirect3DRMFaceArray_GetSize(array1);
912         ok(count == 1, "count = %u\n", count);
913         hr = IDirect3DRMFaceArray_GetElement(array1, 0, &face);
914         ok(hr == D3DRM_OK, "Cannot get face (hr = %x)\n", hr);
915         IDirect3DRMFace_Release(face);
916         IDirect3DRMFaceArray_Release(array1);
917     }
918 
919     icount = IDirect3DRMFace_GetVertexCount(face1);
920     ok(!icount, "wrong VertexCount: %i\n", icount);
921 
922     IDirect3DRMFace_Release(face1);
923     IDirect3DRMMeshBuilder2_Release(MeshBuilder2);
924 
925     if (FAILED(hr = IDirect3DRM_QueryInterface(d3drm, &IID_IDirect3DRM3, (void **)&d3drm3)))
926     {
927         win_skip("Cannot get IDirect3DRM3 interface (hr = %x), skipping tests\n", hr);
928         IDirect3DRM_Release(d3drm);
929         return;
930     }
931 
932     hr = IDirect3DRM3_CreateMeshBuilder(d3drm3, &MeshBuilder3);
933     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMMeshBuilder3 interface (hr = %x)\n", hr);
934 
935     icount = IDirect3DRMMeshBuilder3_GetFaceCount(MeshBuilder3);
936     ok(!icount, "wrong FaceCount: %i\n", icount);
937 
938     hr = IDirect3DRMMeshBuilder3_CreateFace(MeshBuilder3, &face2);
939     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMFace2 interface (hr = %x)\n", hr);
940 
941     hr = IDirect3DRMFace2_QueryInterface(face2, &IID_IDirect3DRMObject, (void **)&obj);
942     ok(SUCCEEDED(hr), "Failed to get IDirect3DRMObject, %#x.\n", hr);
943 
944     hr = IDirect3DRMFace2_QueryInterface(face2, &IID_IDirect3DRMFace, (void **)&face1);
945     ok(SUCCEEDED(hr), "Failed to get IDirect3DRMObject, %#x.\n", hr);
946     ok(obj == (IDirect3DRMObject *)face1, "Unexpected interface pointer.\n");
947 
948     IDirect3DRMFace_Release(face1);
949     IDirect3DRMObject_Release(obj);
950 
951     test_class_name((IDirect3DRMObject *)face2, "Face");
952     test_object_name((IDirect3DRMObject *)face2);
953 
954     icount = IDirect3DRMMeshBuilder3_GetFaceCount(MeshBuilder3);
955     todo_wine
956     ok(icount == 1, "wrong FaceCount: %i\n", icount);
957 
958     array1 = NULL;
959     hr = IDirect3DRMMeshBuilder3_GetFaces(MeshBuilder3, &array1);
960     todo_wine
961     ok(hr == D3DRM_OK, "Cannot get FaceArray (hr = %x)\n", hr);
962     todo_wine
963     ok(array1 != NULL, "pArray = %p\n", array1);
964     if (array1)
965     {
966         IDirect3DRMFace *face;
967         count = IDirect3DRMFaceArray_GetSize(array1);
968         ok(count == 1, "count = %u\n", count);
969         hr = IDirect3DRMFaceArray_GetElement(array1, 0, &face);
970         ok(hr == D3DRM_OK, "Cannot get face (hr = %x)\n", hr);
971         IDirect3DRMFace_Release(face);
972         IDirect3DRMFaceArray_Release(array1);
973     }
974 
975     icount = IDirect3DRMFace2_GetVertexCount(face2);
976     ok(!icount, "wrong VertexCount: %i\n", icount);
977 
978     info.lpMemory = data_ok;
979     info.dSize = strlen(data_ok);
980     hr = IDirect3DRMMeshBuilder3_Load(MeshBuilder3, &info, NULL, D3DRMLOAD_FROMMEMORY, NULL, NULL);
981     ok(hr == D3DRM_OK, "Cannot load mesh data (hr = %x)\n", hr);
982 
983     icount = IDirect3DRMMeshBuilder3_GetVertexCount(MeshBuilder3);
984     ok(icount == 4, "Wrong number of vertices %d (must be 4)\n", icount);
985 
986     icount = IDirect3DRMMeshBuilder3_GetNormalCount(MeshBuilder3);
987     ok(icount == 4, "Wrong number of normals %d (must be 4)\n", icount);
988 
989     icount = IDirect3DRMMeshBuilder3_GetFaceCount(MeshBuilder3);
990     todo_wine
991     ok(icount == 4, "Wrong number of faces %d (must be 4)\n", icount);
992 
993     count = 4;
994     hr = IDirect3DRMMeshBuilder3_GetVertices(MeshBuilder3, 0, &count, v1);
995     ok(hr == D3DRM_OK, "Cannot get vertices information (hr = %x)\n", hr);
996     ok(count == 4, "Wrong number of vertices %d (must be 4)\n", count);
997 
998     hr = IDirect3DRMMeshBuilder3_GetNormals(MeshBuilder3, 0, &count, n1);
999     ok(hr == D3DRM_OK, "Cannot get normals information (hr = %x)\n", hr);
1000     ok(count == 4, "Wrong number of normals %d (must be 4)\n", count);
1001 
1002     array1 = NULL;
1003     hr = IDirect3DRMMeshBuilder3_GetFaces(MeshBuilder3, &array1);
1004     todo_wine
1005     ok(hr == D3DRM_OK, "Cannot get FaceArray (hr = %x)\n", hr);
1006     todo_wine
1007     ok(array1 != NULL, "pArray = %p\n", array1);
1008     if (array1)
1009     {
1010         IDirect3DRMFace *face;
1011         count = IDirect3DRMFaceArray_GetSize(array1);
1012         ok(count == 4, "count = %u\n", count);
1013         hr = IDirect3DRMFaceArray_GetElement(array1, 1, &face);
1014         ok(hr == D3DRM_OK, "Cannot get face (hr = %x)\n", hr);
1015         hr = IDirect3DRMFace_GetVertices(face, &count, v2, n2);
1016         ok(hr == D3DRM_OK, "Cannot get vertices information (hr = %x)\n", hr);
1017         ok(count == 3, "Wrong number of vertices %d (must be 3)\n", count);
1018 
1019         vector_eq(&v1[0], &v2[0]);
1020         vector_eq(&v1[1], &v2[1]);
1021         vector_eq(&v1[2], &v2[2]);
1022 
1023         vector_eq(&n1[0], &n2[0]);
1024         vector_eq(&n1[1], &n2[1]);
1025         vector_eq(&n1[2], &n2[2]);
1026 
1027         IDirect3DRMFace_Release(face);
1028         IDirect3DRMFaceArray_Release(array1);
1029     }
1030 
1031     /* Setting face color. */
1032     hr = IDirect3DRMFace2_SetColor(face2, 0x1f180587);
1033     ok(SUCCEEDED(hr), "Failed to set face color, hr %#x.\n", hr);
1034     color = IDirect3DRMFace2_GetColor(face2);
1035     ok(color == 0x1f180587, "Unexpected color %8x.\n", color);
1036 
1037     hr = IDirect3DRMFace2_SetColorRGB(face2, 0.5f, 0.5f, 0.5f);
1038     ok(SUCCEEDED(hr), "Failed to set color, hr %#x.\n", hr);
1039     color = IDirect3DRMFace2_GetColor(face2);
1040     ok(color == 0xff7f7f7f, "Unexpected color %8x.\n", color);
1041 
1042     IDirect3DRMFace2_Release(face2);
1043     IDirect3DRMMeshBuilder3_Release(MeshBuilder3);
1044     IDirect3DRM3_Release(d3drm3);
1045     IDirect3DRM2_Release(d3drm2);
1046     IDirect3DRM_Release(d3drm);
1047 }
1048 
test_Frame(void)1049 static void test_Frame(void)
1050 {
1051     HRESULT hr;
1052     IDirect3DRM *d3drm;
1053     IDirect3DRMFrame *pFrameC;
1054     IDirect3DRMFrame *pFrameP1;
1055     IDirect3DRMFrame *pFrameP2;
1056     IDirect3DRMFrame *pFrameTmp;
1057     IDirect3DRMFrame *scene_frame;
1058     IDirect3DRMFrameArray *frame_array;
1059     IDirect3DRMMeshBuilder *mesh_builder;
1060     IDirect3DRMVisual *visual1;
1061     IDirect3DRMVisual *visual_tmp;
1062     IDirect3DRMVisualArray *visual_array;
1063     IDirect3DRMLight *light1;
1064     IDirect3DRMLight *light_tmp;
1065     IDirect3DRMLightArray *light_array;
1066     IDirect3DRMFrame3 *frame3;
1067     DWORD count, options;
1068     ULONG ref, ref2;
1069     D3DCOLOR color;
1070 
1071     hr = Direct3DRMCreate(&d3drm);
1072     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x)\n", hr);
1073 
1074     ref = get_refcount((IUnknown *)d3drm);
1075     hr = IDirect3DRM_CreateFrame(d3drm, NULL, &pFrameC);
1076     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMFrame interface (hr = %x)\n", hr);
1077     CHECK_REFCOUNT(pFrameC, 1);
1078     ref2 = get_refcount((IUnknown *)d3drm);
1079     ok(ref2 > ref, "Expected d3drm object to be referenced.\n");
1080 
1081     test_class_name((IDirect3DRMObject *)pFrameC, "Frame");
1082     test_object_name((IDirect3DRMObject *)pFrameC);
1083 
1084     hr = IDirect3DRMFrame_GetParent(pFrameC, NULL);
1085     ok(hr == D3DRMERR_BADVALUE, "Should fail and return D3DRM_BADVALUE (hr = %x)\n", hr);
1086     pFrameTmp = (void*)0xdeadbeef;
1087     hr = IDirect3DRMFrame_GetParent(pFrameC, &pFrameTmp);
1088     ok(hr == D3DRM_OK, "Cannot get parent frame (hr = %x)\n", hr);
1089     ok(pFrameTmp == NULL, "pFrameTmp = %p\n", pFrameTmp);
1090     CHECK_REFCOUNT(pFrameC, 1);
1091 
1092     frame_array = NULL;
1093     hr = IDirect3DRMFrame_GetChildren(pFrameC, &frame_array);
1094     ok(hr == D3DRM_OK, "Cannot get children (hr = %x)\n", hr);
1095     ok(!!frame_array, "frame_array = %p\n", frame_array);
1096     if (frame_array)
1097     {
1098         count = IDirect3DRMFrameArray_GetSize(frame_array);
1099         ok(count == 0, "count = %u\n", count);
1100         hr = IDirect3DRMFrameArray_GetElement(frame_array, 0, &pFrameTmp);
1101         ok(hr == D3DRMERR_BADVALUE, "Should have returned D3DRMERR_BADVALUE (hr = %x)\n", hr);
1102         ok(pFrameTmp == NULL, "pFrameTmp = %p\n", pFrameTmp);
1103         IDirect3DRMFrameArray_Release(frame_array);
1104     }
1105 
1106     hr = IDirect3DRM_CreateFrame(d3drm, NULL, &pFrameP1);
1107     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMFrame interface (hr = %x)\n", hr);
1108 
1109     /* GetParent with NULL pointer */
1110     hr = IDirect3DRMFrame_GetParent(pFrameP1, NULL);
1111     ok(hr == D3DRMERR_BADVALUE, "Should have returned D3DRMERR_BADVALUE (hr = %x)\n", hr);
1112     CHECK_REFCOUNT(pFrameP1, 1);
1113 
1114     /* [Add/Delete]Child with NULL pointer */
1115     hr = IDirect3DRMFrame_AddChild(pFrameP1, NULL);
1116     ok(hr == D3DRMERR_BADOBJECT, "Should have returned D3DRMERR_BADOBJECT (hr = %x)\n", hr);
1117     CHECK_REFCOUNT(pFrameP1, 1);
1118 
1119     hr = IDirect3DRMFrame_DeleteChild(pFrameP1, NULL);
1120     ok(hr == D3DRMERR_BADOBJECT, "Should have returned D3DRMERR_BADOBJECT (hr = %x)\n", hr);
1121     CHECK_REFCOUNT(pFrameP1, 1);
1122 
1123     /* Add child to first parent */
1124     pFrameTmp = (void*)0xdeadbeef;
1125     hr = IDirect3DRMFrame_GetParent(pFrameP1, &pFrameTmp);
1126     ok(hr == D3DRM_OK, "Cannot get parent frame (hr = %x)\n", hr);
1127     ok(pFrameTmp == NULL, "pFrameTmp = %p\n", pFrameTmp);
1128 
1129     hr = IDirect3DRMFrame_AddChild(pFrameP1, pFrameC);
1130     ok(hr == D3DRM_OK, "Cannot add child frame (hr = %x)\n", hr);
1131     CHECK_REFCOUNT(pFrameP1, 1);
1132     CHECK_REFCOUNT(pFrameC, 2);
1133 
1134     hr = IDirect3DRMFrame_GetScene(pFrameC, NULL);
1135     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
1136     hr = IDirect3DRMFrame_GetScene(pFrameC, &scene_frame);
1137     ok(SUCCEEDED(hr), "Cannot get scene (hr == %#x).\n", hr);
1138     ok(scene_frame == pFrameP1, "Expected scene frame == %p, got %p.\n", pFrameP1, scene_frame);
1139     CHECK_REFCOUNT(pFrameP1, 2);
1140     IDirect3DRMFrame_Release(scene_frame);
1141     hr = IDirect3DRMFrame_GetScene(pFrameP1, &scene_frame);
1142     ok(SUCCEEDED(hr), "Cannot get scene (hr == %#x).\n", hr);
1143     ok(scene_frame == pFrameP1, "Expected scene frame == %p, got %p.\n", pFrameP1, scene_frame);
1144     CHECK_REFCOUNT(pFrameP1, 2);
1145     IDirect3DRMFrame_Release(scene_frame);
1146 
1147     frame_array = NULL;
1148     hr = IDirect3DRMFrame_GetChildren(pFrameP1, &frame_array);
1149     ok(hr == D3DRM_OK, "Cannot get children (hr = %x)\n", hr);
1150     /* In some older version of d3drm, creating IDirect3DRMFrameArray object with GetChildren does not increment refcount of children frames */
1151     ok((get_refcount((IUnknown*)pFrameC) == 3) || broken(get_refcount((IUnknown*)pFrameC) == 2),
1152             "Invalid refcount. Expected 3 (or 2) got %d\n", get_refcount((IUnknown*)pFrameC));
1153     if (frame_array)
1154     {
1155         count = IDirect3DRMFrameArray_GetSize(frame_array);
1156         ok(count == 1, "count = %u\n", count);
1157         hr = IDirect3DRMFrameArray_GetElement(frame_array, 0, &pFrameTmp);
1158         ok(hr == D3DRM_OK, "Cannot get element (hr = %x)\n", hr);
1159         ok(pFrameTmp == pFrameC, "pFrameTmp = %p\n", pFrameTmp);
1160         ok((get_refcount((IUnknown*)pFrameC) == 4) || broken(get_refcount((IUnknown*)pFrameC) == 3),
1161                 "Invalid refcount. Expected 4 (or 3) got %d\n", get_refcount((IUnknown*)pFrameC));
1162         IDirect3DRMFrame_Release(pFrameTmp);
1163         ok((get_refcount((IUnknown*)pFrameC) == 3) || broken(get_refcount((IUnknown*)pFrameC) == 2),
1164                 "Invalid refcount. Expected 3 (or 2) got %d\n", get_refcount((IUnknown*)pFrameC));
1165         IDirect3DRMFrameArray_Release(frame_array);
1166         CHECK_REFCOUNT(pFrameC, 2);
1167     }
1168 
1169     pFrameTmp = (void*)0xdeadbeef;
1170     hr = IDirect3DRMFrame_GetParent(pFrameC, &pFrameTmp);
1171     ok(hr == D3DRM_OK, "Cannot get parent frame (hr = %x)\n", hr);
1172     ok(pFrameTmp == pFrameP1, "pFrameTmp = %p\n", pFrameTmp);
1173     CHECK_REFCOUNT(pFrameP1, 2);
1174     IDirect3DRMFrame_Release(pFrameTmp);
1175     CHECK_REFCOUNT(pFrameP1, 1);
1176 
1177     /* Add child to second parent */
1178     hr = IDirect3DRM_CreateFrame(d3drm, NULL, &pFrameP2);
1179     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMFrame interface (hr = %x)\n", hr);
1180 
1181     hr = IDirect3DRMFrame_AddChild(pFrameP2, pFrameC);
1182     ok(hr == D3DRM_OK, "Cannot add child frame (hr = %x)\n", hr);
1183     CHECK_REFCOUNT(pFrameC, 2);
1184 
1185     frame_array = NULL;
1186     hr = IDirect3DRMFrame_GetChildren(pFrameP2, &frame_array);
1187     ok(hr == D3DRM_OK, "Cannot get children (hr = %x)\n", hr);
1188     if (frame_array)
1189     {
1190         count = IDirect3DRMFrameArray_GetSize(frame_array);
1191         ok(count == 1, "count = %u\n", count);
1192         hr = IDirect3DRMFrameArray_GetElement(frame_array, 0, &pFrameTmp);
1193         ok(hr == D3DRM_OK, "Cannot get element (hr = %x)\n", hr);
1194         ok(pFrameTmp == pFrameC, "pFrameTmp = %p\n", pFrameTmp);
1195         IDirect3DRMFrame_Release(pFrameTmp);
1196         IDirect3DRMFrameArray_Release(frame_array);
1197     }
1198 
1199     frame_array = NULL;
1200     hr = IDirect3DRMFrame_GetChildren(pFrameP1, &frame_array);
1201     ok(hr == D3DRM_OK, "Cannot get children (hr = %x)\n", hr);
1202     if (frame_array)
1203     {
1204         count = IDirect3DRMFrameArray_GetSize(frame_array);
1205         ok(count == 0, "count = %u\n", count);
1206         pFrameTmp = (void*)0xdeadbeef;
1207         hr = IDirect3DRMFrameArray_GetElement(frame_array, 0, &pFrameTmp);
1208         ok(hr == D3DRMERR_BADVALUE, "Should have returned D3DRMERR_BADVALUE (hr = %x)\n", hr);
1209         ok(pFrameTmp == NULL, "pFrameTmp = %p\n", pFrameTmp);
1210         IDirect3DRMFrameArray_Release(frame_array);
1211     }
1212     hr = IDirect3DRMFrame_GetScene(pFrameC, &scene_frame);
1213     ok(SUCCEEDED(hr), "Cannot get scene (hr == %#x).\n", hr);
1214     ok(scene_frame == pFrameP2, "Expected scene frame == %p, got %p.\n", pFrameP2, scene_frame);
1215     CHECK_REFCOUNT(pFrameP2, 2);
1216     IDirect3DRMFrame_Release(scene_frame);
1217     hr = IDirect3DRMFrame_GetScene(pFrameP2, &scene_frame);
1218     ok(SUCCEEDED(hr), "Cannot get scene (hr == %#x).\n", hr);
1219     ok(scene_frame == pFrameP2, "Expected scene frame == %p, got %p.\n", pFrameP2, scene_frame);
1220     CHECK_REFCOUNT(pFrameP2, 2);
1221     IDirect3DRMFrame_Release(scene_frame);
1222 
1223     pFrameTmp = (void*)0xdeadbeef;
1224     hr = IDirect3DRMFrame_GetParent(pFrameC, &pFrameTmp);
1225     ok(hr == D3DRM_OK, "Cannot get parent frame (hr = %x)\n", hr);
1226     ok(pFrameTmp == pFrameP2, "pFrameTmp = %p\n", pFrameTmp);
1227     CHECK_REFCOUNT(pFrameP2, 2);
1228     CHECK_REFCOUNT(pFrameC, 2);
1229     IDirect3DRMFrame_Release(pFrameTmp);
1230     CHECK_REFCOUNT(pFrameP2, 1);
1231 
1232     /* Add child again */
1233     hr = IDirect3DRMFrame_AddChild(pFrameP2, pFrameC);
1234     ok(hr == D3DRM_OK, "Cannot add child frame (hr = %x)\n", hr);
1235     CHECK_REFCOUNT(pFrameC, 2);
1236 
1237     frame_array = NULL;
1238     hr = IDirect3DRMFrame_GetChildren(pFrameP2, &frame_array);
1239     ok(hr == D3DRM_OK, "Cannot get children (hr = %x)\n", hr);
1240     if (frame_array)
1241     {
1242         count = IDirect3DRMFrameArray_GetSize(frame_array);
1243         ok(count == 1, "count = %u\n", count);
1244         hr = IDirect3DRMFrameArray_GetElement(frame_array, 0, &pFrameTmp);
1245         ok(hr == D3DRM_OK, "Cannot get element (hr = %x)\n", hr);
1246         ok(pFrameTmp == pFrameC, "pFrameTmp = %p\n", pFrameTmp);
1247         IDirect3DRMFrame_Release(pFrameTmp);
1248         IDirect3DRMFrameArray_Release(frame_array);
1249     }
1250 
1251     /* Delete child */
1252     hr = IDirect3DRMFrame_DeleteChild(pFrameP2, pFrameC);
1253     ok(hr == D3DRM_OK, "Cannot delete child frame (hr = %x)\n", hr);
1254     CHECK_REFCOUNT(pFrameC, 1);
1255 
1256     frame_array = NULL;
1257     hr = IDirect3DRMFrame_GetChildren(pFrameP2, &frame_array);
1258     ok(hr == D3DRM_OK, "Cannot get children (hr = %x)\n", hr);
1259     if (frame_array)
1260     {
1261         count = IDirect3DRMFrameArray_GetSize(frame_array);
1262         ok(count == 0, "count = %u\n", count);
1263         pFrameTmp = (void*)0xdeadbeef;
1264         hr = IDirect3DRMFrameArray_GetElement(frame_array, 0, &pFrameTmp);
1265         ok(hr == D3DRMERR_BADVALUE, "Should have returned D3DRMERR_BADVALUE (hr = %x)\n", hr);
1266         ok(pFrameTmp == NULL, "pFrameTmp = %p\n", pFrameTmp);
1267         IDirect3DRMFrameArray_Release(frame_array);
1268     }
1269 
1270     pFrameTmp = (void*)0xdeadbeef;
1271     hr = IDirect3DRMFrame_GetParent(pFrameC, &pFrameTmp);
1272     ok(hr == D3DRM_OK, "Cannot get parent frame (hr = %x)\n", hr);
1273     ok(pFrameTmp == NULL, "pFrameTmp = %p\n", pFrameTmp);
1274 
1275     /* Add two children */
1276     hr = IDirect3DRMFrame_AddChild(pFrameP2, pFrameC);
1277     ok(hr == D3DRM_OK, "Cannot add child frame (hr = %x)\n", hr);
1278     CHECK_REFCOUNT(pFrameC, 2);
1279 
1280     hr = IDirect3DRMFrame_AddChild(pFrameP2, pFrameP1);
1281     ok(hr == D3DRM_OK, "Cannot add child frame (hr = %x)\n", hr);
1282     CHECK_REFCOUNT(pFrameP1, 2);
1283 
1284     frame_array = NULL;
1285     hr = IDirect3DRMFrame_GetChildren(pFrameP2, &frame_array);
1286     ok(hr == D3DRM_OK, "Cannot get children (hr = %x)\n", hr);
1287     if (frame_array)
1288     {
1289         count = IDirect3DRMFrameArray_GetSize(frame_array);
1290         ok(count == 2, "count = %u\n", count);
1291         hr = IDirect3DRMFrameArray_GetElement(frame_array, 0, &pFrameTmp);
1292         ok(hr == D3DRM_OK, "Cannot get element (hr = %x)\n", hr);
1293         ok(pFrameTmp == pFrameC, "pFrameTmp = %p\n", pFrameTmp);
1294         IDirect3DRMFrame_Release(pFrameTmp);
1295         hr = IDirect3DRMFrameArray_GetElement(frame_array, 1, &pFrameTmp);
1296         ok(hr == D3DRM_OK, "Cannot get element (hr = %x)\n", hr);
1297         ok(pFrameTmp == pFrameP1, "pFrameTmp = %p\n", pFrameTmp);
1298         IDirect3DRMFrame_Release(pFrameTmp);
1299         IDirect3DRMFrameArray_Release(frame_array);
1300     }
1301 
1302     /* [Add/Delete]Visual with NULL pointer */
1303     hr = IDirect3DRMFrame_AddVisual(pFrameP1, NULL);
1304     ok(hr == D3DRMERR_BADOBJECT, "Should have returned D3DRMERR_BADOBJECT (hr = %x)\n", hr);
1305     CHECK_REFCOUNT(pFrameP1, 2);
1306 
1307     hr = IDirect3DRMFrame_DeleteVisual(pFrameP1, NULL);
1308     ok(hr == D3DRMERR_BADOBJECT, "Should have returned D3DRMERR_BADOBJECT (hr = %x)\n", hr);
1309     CHECK_REFCOUNT(pFrameP1, 2);
1310 
1311     /* Create Visual */
1312     hr = IDirect3DRM_CreateMeshBuilder(d3drm, &mesh_builder);
1313     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMMeshBuilder interface (hr = %x)\n", hr);
1314     visual1 = (IDirect3DRMVisual *)mesh_builder;
1315 
1316     /* Add Visual to first parent */
1317     hr = IDirect3DRMFrame_AddVisual(pFrameP1, visual1);
1318     ok(hr == D3DRM_OK, "Cannot add visual (hr = %x)\n", hr);
1319     CHECK_REFCOUNT(pFrameP1, 2);
1320     CHECK_REFCOUNT(visual1, 2);
1321 
1322     visual_array = NULL;
1323     hr = IDirect3DRMFrame_GetVisuals(pFrameP1, &visual_array);
1324     ok(hr == D3DRM_OK, "Cannot get visuals (hr = %x)\n", hr);
1325     if (visual_array)
1326     {
1327         count = IDirect3DRMVisualArray_GetSize(visual_array);
1328         ok(count == 1, "count = %u\n", count);
1329         hr = IDirect3DRMVisualArray_GetElement(visual_array, 0, &visual_tmp);
1330         ok(hr == D3DRM_OK, "Cannot get element (hr = %x)\n", hr);
1331         ok(visual_tmp == visual1, "visual_tmp = %p\n", visual_tmp);
1332         IDirect3DRMVisual_Release(visual_tmp);
1333         IDirect3DRMVisualArray_Release(visual_array);
1334     }
1335 
1336     /* Delete Visual */
1337     hr = IDirect3DRMFrame_DeleteVisual(pFrameP1, visual1);
1338     ok(hr == D3DRM_OK, "Cannot delete visual (hr = %x)\n", hr);
1339     CHECK_REFCOUNT(pFrameP1, 2);
1340     IDirect3DRMMeshBuilder_Release(mesh_builder);
1341 
1342     /* [Add/Delete]Light with NULL pointer */
1343     hr = IDirect3DRMFrame_AddLight(pFrameP1, NULL);
1344     ok(hr == D3DRMERR_BADOBJECT, "Should have returned D3DRMERR_BADOBJECT (hr = %x)\n", hr);
1345     CHECK_REFCOUNT(pFrameP1, 2);
1346 
1347     hr = IDirect3DRMFrame_DeleteLight(pFrameP1, NULL);
1348     ok(hr == D3DRMERR_BADOBJECT, "Should have returned D3DRMERR_BADOBJECT (hr = %x)\n", hr);
1349     CHECK_REFCOUNT(pFrameP1, 2);
1350 
1351     /* Create Light */
1352     hr = IDirect3DRM_CreateLightRGB(d3drm, D3DRMLIGHT_SPOT, 0.1, 0.2, 0.3, &light1);
1353     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMLight interface (hr = %x)\n", hr);
1354 
1355     /* Add Light to first parent */
1356     hr = IDirect3DRMFrame_AddLight(pFrameP1, light1);
1357     ok(hr == D3DRM_OK, "Cannot add light (hr = %x)\n", hr);
1358     CHECK_REFCOUNT(pFrameP1, 2);
1359     CHECK_REFCOUNT(light1, 2);
1360 
1361     light_array = NULL;
1362     hr = IDirect3DRMFrame_GetLights(pFrameP1, &light_array);
1363     ok(hr == D3DRM_OK, "Cannot get lights (hr = %x)\n", hr);
1364     if (light_array)
1365     {
1366         count = IDirect3DRMLightArray_GetSize(light_array);
1367         ok(count == 1, "count = %u\n", count);
1368         hr = IDirect3DRMLightArray_GetElement(light_array, 0, &light_tmp);
1369         ok(hr == D3DRM_OK, "Cannot get element (hr = %x)\n", hr);
1370         ok(light_tmp == light1, "light_tmp = %p\n", light_tmp);
1371         IDirect3DRMLight_Release(light_tmp);
1372         IDirect3DRMLightArray_Release(light_array);
1373     }
1374 
1375     /* Delete Light */
1376     hr = IDirect3DRMFrame_DeleteLight(pFrameP1, light1);
1377     ok(hr == D3DRM_OK, "Cannot delete light (hr = %x)\n", hr);
1378     CHECK_REFCOUNT(pFrameP1, 2);
1379     IDirect3DRMLight_Release(light1);
1380 
1381     /* Test SceneBackground on first parent */
1382     color = IDirect3DRMFrame_GetSceneBackground(pFrameP1);
1383     ok(color == 0xff000000, "wrong color (%x)\n", color);
1384 
1385     hr = IDirect3DRMFrame_SetSceneBackground(pFrameP1, 0xff180587);
1386     ok(hr == D3DRM_OK, "Cannot set color (hr = %x)\n", hr);
1387     color = IDirect3DRMFrame_GetSceneBackground(pFrameP1);
1388     ok(color == 0xff180587, "wrong color (%x)\n", color);
1389 
1390     hr = IDirect3DRMFrame_SetSceneBackgroundRGB(pFrameP1, 0.5, 0.5, 0.5);
1391     ok(hr == D3DRM_OK, "Cannot set color (hr = %x)\n", hr);
1392     color = IDirect3DRMFrame_GetSceneBackground(pFrameP1);
1393     ok(color == 0xff7f7f7f, "wrong color (%x)\n", color);
1394 
1395     /* Traversal options. */
1396     hr = IDirect3DRMFrame_QueryInterface(pFrameP2, &IID_IDirect3DRMFrame3, (void **)&frame3);
1397     ok(SUCCEEDED(hr), "Failed to get IDirect3DRMFrame3 interface, hr %#x.\n", hr);
1398 
1399     hr = IDirect3DRMFrame3_GetTraversalOptions(frame3, NULL);
1400     ok(hr == D3DRMERR_BADVALUE, "Unexpected hr %#x.\n", hr);
1401 
1402     options = 0;
1403     hr = IDirect3DRMFrame3_GetTraversalOptions(frame3, &options);
1404     ok(SUCCEEDED(hr), "Failed to get traversal options, hr %#x.\n", hr);
1405     ok(options == (D3DRMFRAME_RENDERENABLE | D3DRMFRAME_PICKENABLE), "Unexpected default options %#x.\n", options);
1406 
1407     hr = IDirect3DRMFrame3_SetTraversalOptions(frame3, 0);
1408     ok(SUCCEEDED(hr), "Unexpected hr %#x.\n", hr);
1409 
1410     hr = IDirect3DRMFrame3_SetTraversalOptions(frame3, 0xf0000000);
1411     ok(hr == D3DRMERR_BADVALUE, "Unexpected hr %#x.\n", hr);
1412 
1413     hr = IDirect3DRMFrame3_SetTraversalOptions(frame3, 0xf0000000 | D3DRMFRAME_PICKENABLE);
1414     ok(hr == D3DRMERR_BADVALUE, "Unexpected hr %#x.\n", hr);
1415 
1416     options = 0xf;
1417     hr = IDirect3DRMFrame3_GetTraversalOptions(frame3, &options);
1418     ok(SUCCEEDED(hr), "Failed to get traversal options, hr %#x.\n", hr);
1419     ok(options == 0, "Unexpected traversal options %#x.\n", options);
1420 
1421     hr = IDirect3DRMFrame3_SetTraversalOptions(frame3, D3DRMFRAME_PICKENABLE);
1422     ok(SUCCEEDED(hr), "Failed to set traversal options, hr %#x.\n", hr);
1423 
1424     options = 0;
1425     hr = IDirect3DRMFrame3_GetTraversalOptions(frame3, &options);
1426     ok(SUCCEEDED(hr), "Failed to get traversal options, hr %#x.\n", hr);
1427     ok(options == D3DRMFRAME_PICKENABLE, "Unexpected traversal options %#x.\n", options);
1428 
1429     IDirect3DRMFrame3_Release(frame3);
1430 
1431     /* Cleanup */
1432     IDirect3DRMFrame_Release(pFrameP2);
1433     CHECK_REFCOUNT(pFrameC, 1);
1434     CHECK_REFCOUNT(pFrameP1, 1);
1435 
1436     IDirect3DRMFrame_Release(pFrameC);
1437     IDirect3DRMFrame_Release(pFrameP1);
1438 
1439     IDirect3DRM_Release(d3drm);
1440 }
1441 
1442 struct destroy_context
1443 {
1444     IDirect3DRMObject *obj;
1445     unsigned int test_idx;
1446     int called;
1447 };
1448 
1449 struct callback_order
1450 {
1451     void *callback;
1452     void *context;
1453 } corder[3], d3drm_corder[3];
1454 
destroy_callback(IDirect3DRMObject * obj,void * arg)1455 static void CDECL destroy_callback(IDirect3DRMObject *obj, void *arg)
1456 {
1457     struct destroy_context *ctxt = arg;
1458     ok(ctxt->called == 1 || ctxt->called == 2, "got called counter %d\n", ctxt->called);
1459     ok(obj == ctxt->obj, "called with %p, expected %p\n", obj, ctxt->obj);
1460     d3drm_corder[ctxt->called].callback = &destroy_callback;
1461     d3drm_corder[ctxt->called++].context = ctxt;
1462 }
1463 
destroy_callback1(IDirect3DRMObject * obj,void * arg)1464 static void CDECL destroy_callback1(IDirect3DRMObject *obj, void *arg)
1465 {
1466     struct destroy_context *ctxt = (struct destroy_context*)arg;
1467     ok(ctxt->called == 0, "got called counter %d\n", ctxt->called);
1468     ok(obj == ctxt->obj, "called with %p, expected %p\n", obj, ctxt->obj);
1469     d3drm_corder[ctxt->called].callback = &destroy_callback1;
1470     d3drm_corder[ctxt->called++].context = ctxt;
1471 }
1472 
test_destroy_callback(unsigned int test_idx,REFCLSID clsid,REFIID iid)1473 static void test_destroy_callback(unsigned int test_idx, REFCLSID clsid, REFIID iid)
1474 {
1475     struct destroy_context context;
1476     IDirect3DRMObject *obj;
1477     IUnknown *unknown;
1478     IDirect3DRM *d3drm;
1479     HRESULT hr;
1480     int i;
1481 
1482     hr = Direct3DRMCreate(&d3drm);
1483     ok(SUCCEEDED(hr), "Test %u: Cannot get IDirect3DRM interface (hr = %x).\n", test_idx, hr);
1484 
1485     hr = IDirect3DRM_CreateObject(d3drm, clsid, NULL, iid, (void **)&unknown);
1486     ok(hr == D3DRM_OK, "Test %u: Cannot get IDirect3DRMObject interface (hr = %x).\n", test_idx, hr);
1487     hr = IUnknown_QueryInterface(unknown, &IID_IDirect3DRMObject, (void**)&obj);
1488     ok(hr == D3DRM_OK, "Test %u: expected D3DRM_OK (hr = %x).\n", test_idx, hr);
1489     IUnknown_Release(unknown);
1490 
1491     context.called = 0;
1492     context.test_idx = test_idx;
1493     context.obj = obj;
1494 
1495     hr = IDirect3DRMObject_AddDestroyCallback(obj, NULL, &context);
1496     ok(hr == D3DRMERR_BADVALUE, "Test %u: expected D3DRMERR_BADVALUE (hr = %x).\n", test_idx, hr);
1497 
1498     hr = IDirect3DRMObject_AddDestroyCallback(obj, destroy_callback, &context);
1499     ok(hr == D3DRM_OK, "Test %u: expected D3DRM_OK (hr = %x).\n", test_idx, hr);
1500     corder[2].callback = &destroy_callback;
1501     corder[2].context = &context;
1502 
1503     /* same callback added twice */
1504     hr = IDirect3DRMObject_AddDestroyCallback(obj, destroy_callback, &context);
1505     ok(hr == D3DRM_OK, "Test %u: expected D3DRM_OK (hr = %x).\n", test_idx, hr);
1506     corder[1].callback = &destroy_callback;
1507     corder[1].context = &context;
1508 
1509     hr = IDirect3DRMObject_DeleteDestroyCallback(obj, destroy_callback1, NULL);
1510     ok(hr == D3DRM_OK, "Test %u: expected D3DRM_OK (hr = %x).\n", test_idx, hr);
1511 
1512     hr = IDirect3DRMObject_DeleteDestroyCallback(obj, destroy_callback1, &context);
1513     ok(hr == D3DRM_OK, "Test %u: expected D3DRM_OK (hr = %x).\n", test_idx, hr);
1514 
1515     /* add one more */
1516     hr = IDirect3DRMObject_AddDestroyCallback(obj, destroy_callback1, &context);
1517     ok(hr == D3DRM_OK, "Test %u: expected D3DRM_OK (hr = %x).\n", test_idx, hr);
1518     corder[0].callback = &destroy_callback1;
1519     corder[0].context = &context;
1520 
1521     hr = IDirect3DRMObject_DeleteDestroyCallback(obj, NULL, NULL);
1522     ok(hr == D3DRMERR_BADVALUE, "Test %u: expected D3DRM_BADVALUE (hr = %x).\n", test_idx, hr);
1523 
1524     context.called = 0;
1525     IDirect3DRMObject_Release(obj);
1526     ok(context.called == 3, "Test %u: got %d, expected 3.\n", test_idx, context.called);
1527     for (i = 0; i < context.called; i++)
1528     {
1529         ok(corder[i].callback == d3drm_corder[i].callback
1530                 && corder[i].context == d3drm_corder[i].context,
1531                 "Expected callback = %p, context = %p. Got callback = %p, context = %p.\n", d3drm_corder[i].callback,
1532                 d3drm_corder[i].context, corder[i].callback, corder[i].context);
1533     }
1534 
1535     /* test this pattern - add cb1, add cb2, add cb1, delete cb1 */
1536     hr = IDirect3DRM_CreateObject(d3drm, clsid, NULL, iid, (void **)&unknown);
1537     ok(hr == D3DRM_OK, "Test %u: Cannot get IDirect3DRMObject interface (hr = %x).\n", test_idx, hr);
1538     hr = IUnknown_QueryInterface(unknown, &IID_IDirect3DRMObject, (void**)&obj);
1539     ok(hr == D3DRM_OK, "Test %u: expected D3DRM_OK (hr = %x).\n", test_idx, hr);
1540     IUnknown_Release(unknown);
1541 
1542     hr = IDirect3DRMObject_AddDestroyCallback(obj, destroy_callback, &context);
1543     ok(hr == D3DRM_OK, "Test %u: expected D3DRM_OK (hr = %x).\n", test_idx, hr);
1544     corder[1].callback = &destroy_callback;
1545     corder[1].context = &context;
1546 
1547     hr = IDirect3DRMObject_AddDestroyCallback(obj, destroy_callback1, &context);
1548     ok(hr == D3DRM_OK, "Test %u: expected D3DRM_OK (hr = %x).\n", test_idx, hr);
1549     corder[0].callback = &destroy_callback1;
1550     corder[0].context = &context;
1551 
1552     hr = IDirect3DRMObject_AddDestroyCallback(obj, destroy_callback, &context);
1553     ok(hr == D3DRM_OK, "Test %u: expected D3DRM_OK (hr = %x).\n", test_idx, hr);
1554 
1555     hr = IDirect3DRMObject_DeleteDestroyCallback(obj, destroy_callback, &context);
1556     ok(hr == D3DRM_OK, "Test %u: expected D3DRM_OK (hr = %x).\n", test_idx, hr);
1557 
1558     context.called = 0;
1559     hr = IDirect3DRMObject_QueryInterface(obj, &IID_IDirect3DRMObject, (void**)&context.obj);
1560     ok(hr == D3DRM_OK, "Test %u: expected D3DRM_OK (hr = %x).\n", test_idx, hr);
1561     IDirect3DRMObject_Release(context.obj);
1562     IUnknown_Release(unknown);
1563     ok(context.called == 2, "Test %u: got %d, expected 2.\n", test_idx, context.called);
1564     for (i = 0; i < context.called; i++)
1565     {
1566         ok(corder[i].callback == d3drm_corder[i].callback
1567                 && corder[i].context == d3drm_corder[i].context,
1568                 "Expected callback = %p, context = %p. Got callback = %p, context = %p.\n", d3drm_corder[i].callback,
1569                 d3drm_corder[i].context, corder[i].callback, corder[i].context);
1570     }
1571 
1572     IDirect3DRM_Release(d3drm);
1573 }
1574 
test_object(void)1575 static void test_object(void)
1576 {
1577     static const struct
1578     {
1579         REFCLSID clsid;
1580         REFIID iid;
1581         BOOL takes_d3drm_ref;
1582     }
1583     tests[] =
1584     {
1585         { &CLSID_CDirect3DRMDevice,      &IID_IDirect3DRMDevice },
1586         { &CLSID_CDirect3DRMDevice,      &IID_IDirect3DRMDevice2 },
1587         { &CLSID_CDirect3DRMDevice,      &IID_IDirect3DRMDevice3 },
1588         { &CLSID_CDirect3DRMDevice,      &IID_IDirect3DRMWinDevice },
1589         { &CLSID_CDirect3DRMTexture,     &IID_IDirect3DRMTexture },
1590         { &CLSID_CDirect3DRMTexture,     &IID_IDirect3DRMTexture2 },
1591         { &CLSID_CDirect3DRMTexture,     &IID_IDirect3DRMTexture3 },
1592         { &CLSID_CDirect3DRMViewport,    &IID_IDirect3DRMViewport },
1593         { &CLSID_CDirect3DRMViewport,    &IID_IDirect3DRMViewport2 },
1594         { &CLSID_CDirect3DRMFace,        &IID_IDirect3DRMFace },
1595         { &CLSID_CDirect3DRMFace,        &IID_IDirect3DRMFace2 },
1596         { &CLSID_CDirect3DRMMeshBuilder, &IID_IDirect3DRMMeshBuilder,  TRUE },
1597         { &CLSID_CDirect3DRMMeshBuilder, &IID_IDirect3DRMMeshBuilder2, TRUE },
1598         { &CLSID_CDirect3DRMMeshBuilder, &IID_IDirect3DRMMeshBuilder3, TRUE },
1599         { &CLSID_CDirect3DRMFrame,       &IID_IDirect3DRMFrame,        TRUE },
1600         { &CLSID_CDirect3DRMFrame,       &IID_IDirect3DRMFrame2,       TRUE },
1601         { &CLSID_CDirect3DRMFrame,       &IID_IDirect3DRMFrame3,       TRUE },
1602         { &CLSID_CDirect3DRMLight,       &IID_IDirect3DRMLight,        TRUE },
1603         { &CLSID_CDirect3DRMMaterial,    &IID_IDirect3DRMMaterial,     TRUE },
1604         { &CLSID_CDirect3DRMMaterial,    &IID_IDirect3DRMMaterial2,    TRUE },
1605         { &CLSID_CDirect3DRMMesh,        &IID_IDirect3DRMMesh,         TRUE },
1606         { &CLSID_CDirect3DRMAnimation,   &IID_IDirect3DRMAnimation,    TRUE },
1607         { &CLSID_CDirect3DRMAnimation,   &IID_IDirect3DRMAnimation2,   TRUE },
1608         { &CLSID_CDirect3DRMWrap,        &IID_IDirect3DRMWrap },
1609     };
1610     IDirect3DRM *d3drm1;
1611     IDirect3DRM2 *d3drm2;
1612     IDirect3DRM3 *d3drm3;
1613     IUnknown *unknown = (IUnknown *)0xdeadbeef;
1614     HRESULT hr;
1615     ULONG ref1, ref2, ref3, ref4;
1616     int i;
1617 
1618     hr = Direct3DRMCreate(&d3drm1);
1619     ok(SUCCEEDED(hr), "Cannot get IDirect3DRM interface (hr = %#x).\n", hr);
1620     ref1 = get_refcount((IUnknown *)d3drm1);
1621     hr = IDirect3DRM_QueryInterface(d3drm1, &IID_IDirect3DRM2, (void **)&d3drm2);
1622     ok(SUCCEEDED(hr), "Cannot get IDirect3DRM2 interface (hr = %#x).\n", hr);
1623     hr = IDirect3DRM_QueryInterface(d3drm1, &IID_IDirect3DRM3, (void **)&d3drm3);
1624     ok(SUCCEEDED(hr), "Cannot get IDirect3DRM3 interface (hr = %#x).\n", hr);
1625 
1626     hr = IDirect3DRM_CreateObject(d3drm1, &CLSID_DirectDraw, NULL, &IID_IDirectDraw, (void **)&unknown);
1627     ok(hr == CLASSFACTORY_E_FIRST, "Expected hr == CLASSFACTORY_E_FIRST, got %#x.\n", hr);
1628     ok(!unknown, "Expected object returned == NULL, got %p.\n", unknown);
1629 
1630     for (i = 0; i < ARRAY_SIZE(tests); ++i)
1631     {
1632         unknown = (IUnknown *)0xdeadbeef;
1633         hr = IDirect3DRM_CreateObject(d3drm1, NULL, NULL, tests[i].iid, (void **)&unknown);
1634         ok(hr == D3DRMERR_BADVALUE, "Test %u: expected hr == D3DRMERR_BADVALUE, got %#x.\n", i, hr);
1635         ok(!unknown, "Expected object returned == NULL, got %p.\n", unknown);
1636         unknown = (IUnknown *)0xdeadbeef;
1637         hr = IDirect3DRM_CreateObject(d3drm1, tests[i].clsid, NULL, NULL, (void **)&unknown);
1638         ok(hr == D3DRMERR_BADVALUE, "Test %u: expected hr == D3DRMERR_BADVALUE, got %#x.\n", i, hr);
1639         ok(!unknown, "Expected object returned == NULL, got %p.\n", unknown);
1640         hr = IDirect3DRM_CreateObject(d3drm1, tests[i].clsid, NULL, NULL, NULL);
1641         ok(hr == D3DRMERR_BADVALUE, "Test %u: expected hr == D3DRMERR_BADVALUE, got %#x.\n", i, hr);
1642 
1643         hr = IDirect3DRM_CreateObject(d3drm1, tests[i].clsid, NULL, tests[i].iid, (void **)&unknown);
1644         ok(SUCCEEDED(hr), "Test %u: expected hr == D3DRM_OK, got %#x.\n", i, hr);
1645         if (SUCCEEDED(hr))
1646         {
1647             ref2 = get_refcount((IUnknown *)d3drm1);
1648             if (tests[i].takes_d3drm_ref)
1649                 ok(ref2 > ref1, "Test %u: expected ref2 > ref1, got ref1 = %u, ref2 = %u.\n", i, ref1, ref2);
1650             else
1651                 ok(ref2 == ref1, "Test %u: expected ref2 == ref1, got ref1 = %u, ref2 = %u.\n", i, ref1, ref2);
1652 
1653             ref3 = get_refcount((IUnknown *)d3drm2);
1654             ok(ref3 == ref1, "Test %u: expected ref3 == ref1, got ref1 = %u, ref3 = %u.\n", i, ref1, ref3);
1655             ref4 = get_refcount((IUnknown *)d3drm3);
1656             ok(ref4 == ref1, "Test %u: expected ref4 == ref1, got ref1 = %u, ref4 = %u.\n", i, ref1, ref4);
1657             IUnknown_Release(unknown);
1658             ref2 = get_refcount((IUnknown *)d3drm1);
1659             ok(ref2 == ref1, "Test %u: expected ref2 == ref1, got ref1 = %u, ref2 = %u.\n", i, ref1, ref2);
1660             ref3 = get_refcount((IUnknown *)d3drm2);
1661             ok(ref3 == ref1, "Test %u: expected ref3 == ref1, got ref1 = %u, ref3 = %u.\n", i, ref1, ref3);
1662             ref4 = get_refcount((IUnknown *)d3drm3);
1663             ok(ref4 == ref1, "Test %u: expected ref4 == ref1, got ref1 = %u, ref4 = %u.\n", i, ref1, ref4);
1664 
1665             /* test Add/Destroy callbacks */
1666             test_destroy_callback(i, tests[i].clsid, tests[i].iid);
1667 
1668             hr = IDirect3DRM2_CreateObject(d3drm2, tests[i].clsid, NULL, tests[i].iid, (void **)&unknown);
1669             ok(SUCCEEDED(hr), "Test %u: expected hr == D3DRM_OK, got %#x.\n", i, hr);
1670             ref2 = get_refcount((IUnknown *)d3drm1);
1671             if (tests[i].takes_d3drm_ref)
1672                 ok(ref2 > ref1, "Test %u: expected ref2 > ref1, got ref1 = %u, ref2 = %u.\n", i, ref1, ref2);
1673             else
1674                 ok(ref2 == ref1, "Test %u: expected ref2 == ref1, got ref1 = %u, ref2 = %u.\n", i, ref1, ref2);
1675             ref3 = get_refcount((IUnknown *)d3drm2);
1676             ok(ref3 == ref1, "Test %u: expected ref3 == ref1, got ref1 = %u, ref3 = %u.\n", i, ref1, ref3);
1677             ref4 = get_refcount((IUnknown *)d3drm3);
1678             ok(ref4 == ref1, "Test %u: expected ref4 == ref1, got ref1 = %u, ref4 = %u.\n", i, ref1, ref4);
1679             IUnknown_Release(unknown);
1680             ref2 = get_refcount((IUnknown *)d3drm1);
1681             ok(ref2 == ref1, "Test %u: expected ref2 == ref1, got ref1 = %u, ref2 = %u.\n", i, ref1, ref2);
1682             ref3 = get_refcount((IUnknown *)d3drm2);
1683             ok(ref3 == ref1, "Test %u: expected ref3 == ref1, got ref1 = %u, ref3 = %u.\n", i, ref1, ref3);
1684             ref4 = get_refcount((IUnknown *)d3drm3);
1685             ok(ref4 == ref1, "Test %u: expected ref4 == ref1, got ref1 = %u, ref4 = %u.\n", i, ref1, ref4);
1686 
1687             hr = IDirect3DRM3_CreateObject(d3drm3, tests[i].clsid, NULL, tests[i].iid, (void **)&unknown);
1688             ok(SUCCEEDED(hr), "Test %u: expected hr == D3DRM_OK, got %#x.\n", i, hr);
1689             ref2 = get_refcount((IUnknown *)d3drm1);
1690             if (tests[i].takes_d3drm_ref)
1691                 ok(ref2 > ref1, "Test %u: expected ref2 > ref1, got ref1 = %u, ref2 = %u.\n", i, ref1, ref2);
1692             else
1693                 ok(ref2 == ref1, "Test %u: expected ref2 == ref1, got ref1 = %u, ref2 = %u.\n", i, ref1, ref2);
1694             ref3 = get_refcount((IUnknown *)d3drm2);
1695             ok(ref3 == ref1, "Test %u: expected ref3 == ref1, got ref1 = %u, ref3 = %u.\n", i, ref1, ref3);
1696             ref4 = get_refcount((IUnknown *)d3drm3);
1697             ok(ref4 == ref1, "Test %u: expected ref4 == ref1, got ref1 = %u, ref4 = %u.\n", i, ref1, ref4);
1698             IUnknown_Release(unknown);
1699             ref2 = get_refcount((IUnknown *)d3drm1);
1700             ok(ref2 == ref1, "Test %u: expected ref2 == ref1, got ref1 = %u, ref2 = %u.\n", i, ref1, ref2);
1701             ref3 = get_refcount((IUnknown *)d3drm2);
1702             ok(ref3 == ref1, "Test %u: expected ref3 == ref1, got ref1 = %u, ref3 = %u.\n", i, ref1, ref3);
1703             ref4 = get_refcount((IUnknown *)d3drm3);
1704             ok(ref4 == ref1, "Test %u: expected ref4 == ref1, got ref1 = %u, ref4 = %u.\n", i, ref1, ref4);
1705         }
1706     }
1707 
1708     IDirect3DRM_Release(d3drm1);
1709     IDirect3DRM2_Release(d3drm2);
1710     IDirect3DRM3_Release(d3drm3);
1711 }
1712 
test_Viewport(void)1713 static void test_Viewport(void)
1714 {
1715     IDirect3DRMFrame3 *frame3, *d3drm_frame3, *tmp_frame3;
1716     IDirect3DRMFrame *frame, *d3drm_frame, *tmp_frame1;
1717     float field, left, top, right, bottom, front, back;
1718     IDirectDrawClipper *clipper;
1719     HRESULT hr;
1720     IDirect3DRM *d3drm1;
1721     IDirect3DRM2 *d3drm2;
1722     IDirect3DRM3 *d3drm3;
1723     IDirect3DRMDevice *device1, *d3drm_device1;
1724     IDirect3DRMDevice3 *device3, *d3drm_device3;
1725     IDirect3DRMViewport *viewport;
1726     IDirect3DRMViewport2 *viewport2;
1727     IDirect3DViewport *d3d_viewport;
1728     D3DVIEWPORT vp;
1729     D3DVALUE expected_val;
1730     IDirect3DRMObject *obj, *obj2;
1731     GUID driver;
1732     HWND window;
1733     RECT rc;
1734     DWORD data, ref1, ref2, ref3, ref4;
1735     DWORD initial_ref1, initial_ref2, initial_ref3, device_ref, frame_ref, frame_ref2, viewport_ref;
1736 
1737     window = create_window();
1738     GetClientRect(window, &rc);
1739 
1740     hr = Direct3DRMCreate(&d3drm1);
1741     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x)\n", hr);
1742     hr = IDirect3DRM_QueryInterface(d3drm1, &IID_IDirect3DRM2, (void **)&d3drm2);
1743     ok(SUCCEEDED(hr), "Cannot get IDirect3DRM2 interface (hr = %#x).\n", hr);
1744     hr = IDirect3DRM_QueryInterface(d3drm1, &IID_IDirect3DRM3, (void **)&d3drm3);
1745     ok(SUCCEEDED(hr), "Cannot get IDirect3DRM3 interface (hr = %#x).\n", hr);
1746     initial_ref1 = get_refcount((IUnknown *)d3drm1);
1747     initial_ref2 = get_refcount((IUnknown *)d3drm2);
1748     initial_ref3 = get_refcount((IUnknown *)d3drm3);
1749 
1750     hr = DirectDrawCreateClipper(0, &clipper, NULL);
1751     ok(hr == DD_OK, "Cannot get IDirectDrawClipper interface (hr = %x)\n", hr);
1752 
1753     hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
1754     ok(hr == DD_OK, "Cannot set HWnd to Clipper (hr = %x)\n", hr);
1755 
1756     memcpy(&driver, &IID_IDirect3DRGBDevice, sizeof(GUID));
1757     hr = IDirect3DRM3_CreateDeviceFromClipper(d3drm3, clipper, &driver, rc.right, rc.bottom, &device3);
1758     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMDevice interface (hr = %x)\n", hr);
1759     hr = IDirect3DRMDevice3_QueryInterface(device3, &IID_IDirect3DRMDevice, (void **)&device1);
1760     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMDevice interface (hr = %#x).\n", hr);
1761 
1762     hr = IDirect3DRM_CreateFrame(d3drm1, NULL, &frame);
1763     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMFrame interface (hr = %x)\n", hr);
1764     hr = IDirect3DRM_CreateFrame(d3drm1, NULL, &tmp_frame1);
1765     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
1766     hr = IDirect3DRM3_CreateFrame(d3drm3, NULL, &frame3);
1767     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMFrame3 interface (hr = %x).\n", hr);
1768     hr = IDirect3DRM3_CreateFrame(d3drm3, NULL, &tmp_frame3);
1769     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
1770 
1771     ref1 = get_refcount((IUnknown *)d3drm1);
1772     ref2 = get_refcount((IUnknown *)d3drm2);
1773     ref3 = get_refcount((IUnknown *)d3drm3);
1774     device_ref = get_refcount((IUnknown *)device1);
1775     frame_ref = get_refcount((IUnknown *)frame);
1776 
1777     hr = IDirect3DRM_CreateViewport(d3drm1, device1, frame, 0, 0, 0, 0, &viewport);
1778     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMViewport interface (hr = %#x)\n", hr);
1779     ref4 = get_refcount((IUnknown *)d3drm1);
1780     ok(ref4 > ref1, "Expected ref4 > ref1, got ref1 = %u, ref4 = %u.\n", ref1, ref4);
1781     ref4 = get_refcount((IUnknown *)d3drm2);
1782     ok(ref4 == ref2, "Expected ref4 == ref2, got ref2 = %u, ref4 = %u.\n", ref2, ref4);
1783     ref4 = get_refcount((IUnknown *)d3drm3);
1784     ok(ref4 == ref3, "Expected ref4 == ref3, got ref3 = %u, ref4 = %u.\n", ref3, ref4);
1785     ref4 = get_refcount((IUnknown *)device1);
1786     ok(ref4 == device_ref, "Expected ref4 == device_ref, got device_ref = %u, ref4 = %u.\n", device_ref, ref4);
1787     ref4 = get_refcount((IUnknown *)frame);
1788     ok(ref4 > frame_ref, "Expected ref4 > frame_ref, got frame_ref = %u, ref4 = %u.\n", frame_ref, ref4);
1789 
1790     hr = IDirect3DRMViewport_GetDevice(viewport, &d3drm_device1);
1791     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMDevice interface (hr = %x)\n", hr);
1792     ok(device1 == d3drm_device1, "Expected device returned = %p, got %p.\n", device1, d3drm_device1);
1793     IDirect3DRMDevice_Release(d3drm_device1);
1794 
1795     hr = IDirect3DRMViewport_SetCamera(viewport, NULL);
1796     ok(hr == D3DRMERR_BADOBJECT, "Got unexpected hr %#x.\n", hr);
1797     hr = IDirect3DRMViewport_GetCamera(viewport, &d3drm_frame);
1798     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
1799     ok(frame == d3drm_frame, "Expected frame returned = %p, got %p.\n", frame, d3drm_frame);
1800     IDirect3DRMFrame_Release(d3drm_frame);
1801 
1802     hr = IDirect3DRMViewport_SetCamera(viewport, tmp_frame1);
1803     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
1804     hr = IDirect3DRMViewport_GetCamera(viewport, &d3drm_frame);
1805     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
1806     ok(d3drm_frame == tmp_frame1, "Got unexpected frame %p, expected %p.\n", d3drm_frame, tmp_frame1);
1807     IDirect3DRMFrame_Release(d3drm_frame);
1808 
1809     IDirect3DRMViewport_Release(viewport);
1810     ref4 = get_refcount((IUnknown *)d3drm1);
1811     ok(ref4 == ref1, "Expected ref4 == ref1, got ref1 = %u, ref4 = %u.\n", ref1, ref4);
1812     ref4 = get_refcount((IUnknown *)d3drm2);
1813     ok(ref4 == ref2, "Expected ref4 == ref2, got ref2 = %u, ref4 = %u.\n", ref2, ref4);
1814     ref4 = get_refcount((IUnknown *)d3drm3);
1815     ok(ref4 == ref3, "Expected ref4 == ref3, got ref3 = %u, ref4 = %u.\n", ref3, ref4);
1816     ref4 = get_refcount((IUnknown *)device1);
1817     ok(ref4 == device_ref, "Expected ref4 == device_ref, got device_ref = %u, ref4 = %u.\n", device_ref, ref4);
1818     ref4 = get_refcount((IUnknown *)frame);
1819     ok(ref4 == frame_ref, "Expected ref4 == frame_ref, got frame_ref = %u, ref4 = %u.\n", frame_ref, ref4);
1820 
1821     hr = IDirect3DRM2_CreateViewport(d3drm2, device1, frame, 0, 0, 0, 0, &viewport);
1822     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMViewport interface (hr = %#x)\n", hr);
1823     ref4 = get_refcount((IUnknown *)d3drm1);
1824     ok(ref4 > ref1, "Expected ref4 > ref1, got ref1 = %u, ref4 = %u.\n", ref1, ref4);
1825     ref4 = get_refcount((IUnknown *)d3drm2);
1826     ok(ref4 == ref2, "Expected ref4 == ref2, got ref2 = %u, ref4 = %u.\n", ref2, ref4);
1827     ref4 = get_refcount((IUnknown *)d3drm3);
1828     ok(ref4 == ref3, "Expected ref4 == ref3, got ref3 = %u, ref4 = %u.\n", ref3, ref4);
1829     ref4 = get_refcount((IUnknown *)device1);
1830     ok(ref4 == device_ref, "Expected ref4 == device_ref, got device_ref = %u, ref4 = %u.\n", device_ref, ref4);
1831     ref4 = get_refcount((IUnknown *)frame);
1832     ok(ref4 > frame_ref, "Expected ref4 > frame_ref, got frame_ref = %u, ref4 = %u.\n", frame_ref, ref4);
1833 
1834     hr = IDirect3DRMViewport_GetDevice(viewport, &d3drm_device1);
1835     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMDevice interface (hr = %x)\n", hr);
1836     ok(device1 == d3drm_device1, "Expected device returned = %p, got %p.\n", device1, d3drm_device1);
1837     IDirect3DRMDevice_Release(d3drm_device1);
1838 
1839     hr = IDirect3DRMViewport_SetCamera(viewport, NULL);
1840     ok(hr == D3DRMERR_BADOBJECT, "Got unexpected hr %#x.\n", hr);
1841     hr = IDirect3DRMViewport_GetCamera(viewport, &d3drm_frame);
1842     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
1843     ok(frame == d3drm_frame, "Expected frame returned = %p, got %p.\n", frame, d3drm_frame);
1844     IDirect3DRMFrame_Release(d3drm_frame);
1845 
1846     hr = IDirect3DRMViewport_SetCamera(viewport, tmp_frame1);
1847     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
1848     hr = IDirect3DRMViewport_GetCamera(viewport, &d3drm_frame);
1849     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
1850     ok(d3drm_frame == tmp_frame1, "Got unexpected frame %p, expected %p.\n", d3drm_frame, tmp_frame1);
1851     IDirect3DRMFrame_Release(d3drm_frame);
1852 
1853     IDirect3DRMViewport_Release(viewport);
1854     ref4 = get_refcount((IUnknown *)d3drm1);
1855     ok(ref4 == ref1, "Expected ref4 == ref1, got ref1 = %u, ref4 = %u.\n", ref1, ref4);
1856     ref4 = get_refcount((IUnknown *)d3drm2);
1857     ok(ref4 == ref2, "Expected ref4 == ref2, got ref2 = %u, ref4 = %u.\n", ref2, ref4);
1858     ref4 = get_refcount((IUnknown *)d3drm3);
1859     ok(ref4 == ref3, "Expected ref4 == ref3, got ref3 = %u, ref4 = %u.\n", ref3, ref4);
1860     ref4 = get_refcount((IUnknown *)device1);
1861     ok(ref4 == device_ref, "Expected ref4 == device_ref, got device_ref = %u, ref4 = %u.\n", device_ref, ref4);
1862     ref4 = get_refcount((IUnknown *)frame);
1863     ok(ref4 == frame_ref, "Expected ref4 == frame_ref, got frame_ref = %u, ref4 = %u.\n", frame_ref, ref4);
1864 
1865     device_ref = get_refcount((IUnknown *)device3);
1866     frame_ref2 = get_refcount((IUnknown *)frame3);
1867 
1868     hr = IDirect3DRM3_CreateViewport(d3drm3, device3, frame3, 0, 0, 0, 0, &viewport2);
1869     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMViewport2 interface (hr = %#x)\n", hr);
1870     ref4 = get_refcount((IUnknown *)d3drm1);
1871     ok(ref4 > ref1, "Expected ref4 > ref1, got ref1 = %u, ref4 = %u.\n", ref1, ref4);
1872     ref4 = get_refcount((IUnknown *)d3drm2);
1873     ok(ref4 == ref2, "Expected ref4 == ref2, got ref2 = %u, ref4 = %u.\n", ref2, ref4);
1874     ref4 = get_refcount((IUnknown *)d3drm3);
1875     ok(ref4 == ref3, "Expected ref4 == ref3, got ref3 = %u, ref4 = %u.\n", ref3, ref4);
1876     ref4 = get_refcount((IUnknown *)device3);
1877     ok(ref4 == device_ref, "Expected ref4 == device_ref, got device_ref = %u, ref4 = %u.\n", device_ref, ref4);
1878     ref4 = get_refcount((IUnknown *)frame3);
1879     ok(ref4 > frame_ref2, "Expected ref4 > frame_ref2, got frame_ref2 = %u, ref4 = %u.\n", frame_ref2, ref4);
1880 
1881     hr = IDirect3DRMViewport2_GetDevice(viewport2, &d3drm_device3);
1882     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMDevice3 interface (hr = %x)\n", hr);
1883     ok(device3 == d3drm_device3, "Expected device returned = %p, got %p.\n", device3, d3drm_device3);
1884     IDirect3DRMDevice3_Release(d3drm_device3);
1885 
1886     hr = IDirect3DRMViewport2_SetCamera(viewport2, NULL);
1887     ok(hr == D3DRMERR_BADOBJECT, "Got unexpected hr %#x.\n", hr);
1888     hr = IDirect3DRMViewport2_GetCamera(viewport2, &d3drm_frame3);
1889     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
1890     ok(frame3 == d3drm_frame3, "Expected frame returned = %p, got %p.\n", frame3, d3drm_frame3);
1891     IDirect3DRMFrame3_Release(d3drm_frame3);
1892 
1893     hr = IDirect3DRMViewport2_SetCamera(viewport2, tmp_frame3);
1894     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
1895     hr = IDirect3DRMViewport2_GetCamera(viewport2, &d3drm_frame3);
1896     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
1897     ok(d3drm_frame3 == tmp_frame3, "Got unexpected frame %p, expected %p.\n", d3drm_frame3, tmp_frame3);
1898     IDirect3DRMFrame3_Release(d3drm_frame3);
1899 
1900     IDirect3DRMViewport2_Release(viewport2);
1901     ref4 = get_refcount((IUnknown *)d3drm1);
1902     ok(ref4 == ref1, "Expected ref4 == ref1, got ref1 = %u, ref4 = %u.\n", ref1, ref4);
1903     ref4 = get_refcount((IUnknown *)d3drm2);
1904     ok(ref4 == ref2, "Expected ref4 == ref2, got ref2 = %u, ref4 = %u.\n", ref2, ref4);
1905     ref4 = get_refcount((IUnknown *)d3drm3);
1906     ok(ref4 == ref3, "Expected ref4 == ref3, got ref3 = %u, ref4 = %u.\n", ref3, ref4);
1907     ref4 = get_refcount((IUnknown *)device3);
1908     ok(ref4 == device_ref, "Expected ref4 == device_ref, got device_ref = %u, ref4 = %u.\n", device_ref, ref4);
1909     ref4 = get_refcount((IUnknown *)frame3);
1910     ok(ref4 == frame_ref2, "Expected ref4 == frame_ref2, got frame_ref2 = %u, ref4 = %u.\n", frame_ref2, ref4);
1911 
1912     /* Test all failures together */
1913     viewport = (IDirect3DRMViewport *)0xdeadbeef;
1914     hr = IDirect3DRM_CreateViewport(d3drm1, NULL, frame, rc.left, rc.top, rc.right, rc.bottom, &viewport);
1915     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
1916     ok(!viewport, "Expected viewport returned == NULL, got %p.\n", viewport);
1917     viewport = (IDirect3DRMViewport *)0xdeadbeef;
1918     hr = IDirect3DRM_CreateViewport(d3drm1, device1, NULL, rc.left, rc.top, rc.right, rc.bottom, &viewport);
1919     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
1920     ok(!viewport, "Expected viewport returned == NULL, got %p.\n", viewport);
1921     viewport = (IDirect3DRMViewport *)0xdeadbeef;
1922     hr = IDirect3DRM_CreateViewport(d3drm1, device1, frame, rc.left, rc.top, rc.right + 1, rc.bottom + 1, &viewport);
1923     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
1924     ok(!viewport, "Expected viewport returned == NULL, got %p.\n", viewport);
1925     viewport = (IDirect3DRMViewport *)0xdeadbeef;
1926     hr = IDirect3DRM_CreateViewport(d3drm1, device1, frame, rc.left, rc.top, rc.right + 1, rc.bottom, &viewport);
1927     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
1928     ok(!viewport, "Expected viewport returned == NULL, got %p.\n", viewport);
1929     viewport = (IDirect3DRMViewport *)0xdeadbeef;
1930     hr = IDirect3DRM_CreateViewport(d3drm1, device1, frame, rc.left, rc.top, rc.right, rc.bottom + 1, &viewport);
1931     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
1932     ok(!viewport, "Expected viewport returned == NULL, got %p.\n", viewport);
1933     hr = IDirect3DRM_CreateViewport(d3drm1, device1, frame, rc.left, rc.top, rc.right, rc.bottom, NULL);
1934     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
1935 
1936     viewport = (IDirect3DRMViewport *)0xdeadbeef;
1937     hr = IDirect3DRM2_CreateViewport(d3drm2, NULL, frame, rc.left, rc.top, rc.right, rc.bottom, &viewport);
1938     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
1939     ok(!viewport, "Expected viewport returned == NULL, got %p.\n", viewport);
1940     viewport = (IDirect3DRMViewport *)0xdeadbeef;
1941     hr = IDirect3DRM2_CreateViewport(d3drm2, device1, NULL, rc.left, rc.top, rc.right, rc.bottom, &viewport);
1942     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
1943     ok(!viewport, "Expected viewport returned == NULL, got %p.\n", viewport);
1944     viewport = (IDirect3DRMViewport *)0xdeadbeef;
1945     hr = IDirect3DRM2_CreateViewport(d3drm2, device1, frame, rc.left, rc.top, rc.right + 1, rc.bottom + 1, &viewport);
1946     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
1947     ok(!viewport, "Expected viewport returned == NULL, got %p.\n", viewport);
1948     viewport = (IDirect3DRMViewport *)0xdeadbeef;
1949     hr = IDirect3DRM2_CreateViewport(d3drm2, device1, frame, rc.left, rc.top, rc.right + 1, rc.bottom, &viewport);
1950     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
1951     ok(!viewport, "Expected viewport returned == NULL, got %p.\n", viewport);
1952     viewport = (IDirect3DRMViewport *)0xdeadbeef;
1953     hr = IDirect3DRM2_CreateViewport(d3drm2, device1, frame, rc.left, rc.top, rc.right, rc.bottom + 1, &viewport);
1954     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
1955     ok(!viewport, "Expected viewport returned == NULL, got %p.\n", viewport);
1956     hr = IDirect3DRM2_CreateViewport(d3drm2, device1, frame, rc.left, rc.top, rc.right, rc.bottom, NULL);
1957     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
1958 
1959     viewport2 = (IDirect3DRMViewport2 *)0xdeadbeef;
1960     hr = IDirect3DRM3_CreateViewport(d3drm3, NULL, frame3, rc.left, rc.top, rc.right, rc.bottom, &viewport2);
1961     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
1962     ok(!viewport2, "Expected viewport returned == NULL, got %p.\n", viewport2);
1963     viewport2 = (IDirect3DRMViewport2 *)0xdeadbeef;
1964     hr = IDirect3DRM3_CreateViewport(d3drm3, device3, NULL, rc.left, rc.top, rc.right, rc.bottom, &viewport2);
1965     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
1966     ok(!viewport2, "Expected viewport returned == NULL, got %p.\n", viewport2);
1967     viewport2 = (IDirect3DRMViewport2 *)0xdeadbeef;
1968     hr = IDirect3DRM3_CreateViewport(d3drm3, device3, frame3, rc.left, rc.top, rc.right + 1, rc.bottom + 1, &viewport2);
1969     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
1970     ok(!viewport2, "Expected viewport returned == NULL, got %p.\n", viewport2);
1971     viewport2 = (IDirect3DRMViewport2 *)0xdeadbeef;
1972     hr = IDirect3DRM3_CreateViewport(d3drm3, device3, frame3, rc.left, rc.top, rc.right + 1, rc.bottom, &viewport2);
1973     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
1974     ok(!viewport2, "Expected viewport returned == NULL, got %p.\n", viewport2);
1975     viewport2 = (IDirect3DRMViewport2 *)0xdeadbeef;
1976     hr = IDirect3DRM3_CreateViewport(d3drm3, device3, frame3, rc.left, rc.top, rc.right, rc.bottom + 1, &viewport2);
1977     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
1978     ok(!viewport2, "Expected viewport returned == NULL, got %p.\n", viewport2);
1979     hr = IDirect3DRM3_CreateViewport(d3drm3, device3, frame3, rc.left, rc.top, rc.right, rc.bottom, NULL);
1980     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
1981 
1982     hr = IDirect3DRM2_CreateViewport(d3drm2, device1, frame, rc.left, rc.top, rc.right, rc.bottom, &viewport);
1983     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMViewport interface (hr = %#x)\n", hr);
1984     hr = IDirect3DRMViewport_GetDirect3DViewport(viewport, &d3d_viewport);
1985     ok(SUCCEEDED(hr), "Cannot get IDirect3DViewport interface (hr = %#x).\n", hr);
1986     viewport_ref = get_refcount((IUnknown *)d3d_viewport);
1987     hr = IDirect3DRMViewport_GetDirect3DViewport(viewport, &d3d_viewport);
1988     ok(SUCCEEDED(hr), "Cannot get IDirect3DViewport interface (hr = %#x).\n", hr);
1989     ref4 = get_refcount((IUnknown *)d3d_viewport);
1990     ok(ref4 > viewport_ref, "Expected ref4 > viewport_ref, got ref4 = %u, viewport_ref = %u.\n", ref4, viewport_ref);
1991     IDirect3DViewport_Release(d3d_viewport);
1992     ref4 = get_refcount((IUnknown *)d3d_viewport);
1993     ok(ref4 == viewport_ref, "Expected ref4 == viewport_ref, got ref4 = %u, viewport_ref = %u.\n", ref4, viewport_ref);
1994     IDirect3DViewport_Release(d3d_viewport);
1995 
1996     hr = IDirect3DRMViewport_GetDirect3DViewport(viewport, &d3d_viewport);
1997     ok(SUCCEEDED(hr), "Cannot get IDirect3DViewport interface (hr = %#x).\n", hr);
1998     vp.dwSize = sizeof(vp);
1999     hr = IDirect3DViewport_GetViewport(d3d_viewport, &vp);
2000     ok(SUCCEEDED(hr), "Cannot get D3DVIEWPORT struct (hr = %#x).\n", hr);
2001     ok(vp.dwWidth == rc.right, "Expected viewport width = %u, got %u.\n", rc.right, vp.dwWidth);
2002     ok(vp.dwHeight == rc.bottom, "Expected viewport height = %u, got %u.\n", rc.bottom, vp.dwHeight);
2003     ok(vp.dwX == rc.left, "Expected viewport X position = %u, got %u.\n", rc.left, vp.dwX);
2004     ok(vp.dwY == rc.top, "Expected viewport Y position = %u, got %u.\n", rc.top, vp.dwY);
2005     expected_val = (rc.right > rc.bottom) ? (rc.right / 2.0f) : (rc.bottom / 2.0f);
2006     ok(vp.dvScaleX == expected_val, "Expected dvScaleX = %f, got %f.\n", expected_val, vp.dvScaleX);
2007     ok(vp.dvScaleY == expected_val, "Expected dvScaleY = %f, got %f.\n", expected_val, vp.dvScaleY);
2008     expected_val = vp.dwWidth / (2.0f * vp.dvScaleX);
2009     ok(vp.dvMaxX == expected_val, "Expected dvMaxX = %f, got %f.\n", expected_val, vp.dvMaxX);
2010     expected_val = vp.dwHeight / (2.0f * vp.dvScaleY);
2011     ok(vp.dvMaxY == expected_val, "Expected dvMaxY = %f, got %f.\n", expected_val, vp.dvMaxY);
2012     IDirect3DViewport_Release(d3d_viewport);
2013     IDirect3DRMViewport_Release(viewport);
2014 
2015     hr = IDirect3DRM3_CreateViewport(d3drm3, device3, frame3, rc.left, rc.top, rc.right, rc.bottom, &viewport2);
2016     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMViewport2 interface (hr = %#x)\n", hr);
2017     hr = IDirect3DRMViewport2_GetDirect3DViewport(viewport2, &d3d_viewport);
2018     ok(SUCCEEDED(hr), "Cannot get IDirect3DViewport interface (hr = %#x).\n", hr);
2019     viewport_ref = get_refcount((IUnknown *)d3d_viewport);
2020     hr = IDirect3DRMViewport2_GetDirect3DViewport(viewport2, &d3d_viewport);
2021     ok(SUCCEEDED(hr), "Cannot get IDirect3DViewport interface (hr = %#x).\n", hr);
2022     ref4 = get_refcount((IUnknown *)d3d_viewport);
2023     ok(ref4 > viewport_ref, "Expected ref4 > viewport_ref, got ref4 = %u, viewport_ref = %u.\n", ref4, viewport_ref);
2024     IDirect3DViewport_Release(d3d_viewport);
2025     ref4 = get_refcount((IUnknown *)d3d_viewport);
2026     ok(ref4 == viewport_ref, "Expected ref4 == viewport_ref, got ref4 = %u, viewport_ref = %u.\n", ref4, viewport_ref);
2027     IDirect3DViewport_Release(d3d_viewport);
2028 
2029     hr = IDirect3DRMViewport2_GetDirect3DViewport(viewport2, &d3d_viewport);
2030     ok(SUCCEEDED(hr), "Cannot get IDirect3DViewport interface (hr = %#x).\n", hr);
2031     vp.dwSize = sizeof(vp);
2032     hr = IDirect3DViewport_GetViewport(d3d_viewport, &vp);
2033     ok(SUCCEEDED(hr), "Cannot get D3DVIEWPORT struct (hr = %#x).\n", hr);
2034     ok(vp.dwWidth == rc.right, "Expected viewport width = %u, got %u.\n", rc.right, vp.dwWidth);
2035     ok(vp.dwHeight == rc.bottom, "Expected viewport height = %u, got %u.\n", rc.bottom, vp.dwHeight);
2036     ok(vp.dwX == rc.left, "Expected viewport X position = %u, got %u.\n", rc.left, vp.dwX);
2037     ok(vp.dwY == rc.top, "Expected viewport Y position = %u, got %u.\n", rc.top, vp.dwY);
2038     expected_val = (rc.right > rc.bottom) ? (rc.right / 2.0f) : (rc.bottom / 2.0f);
2039     ok(vp.dvScaleX == expected_val, "Expected dvScaleX = %f, got %f.\n", expected_val, vp.dvScaleX);
2040     ok(vp.dvScaleY == expected_val, "Expected dvScaleY = %f, got %f.\n", expected_val, vp.dvScaleY);
2041     expected_val = vp.dwWidth / (2.0f * vp.dvScaleX);
2042     ok(vp.dvMaxX == expected_val, "Expected dvMaxX = %f, got %f.\n", expected_val, vp.dvMaxX);
2043     expected_val = vp.dwHeight / (2.0f * vp.dvScaleY);
2044     ok(vp.dvMaxY == expected_val, "Expected dvMaxY = %f, got %f.\n", expected_val, vp.dvMaxY);
2045     IDirect3DViewport_Release(d3d_viewport);
2046     IDirect3DRMViewport2_Release(viewport2);
2047 
2048     hr = IDirect3DRM_CreateViewport(d3drm1, device1, frame, rc.left, rc.top, rc.right, rc.bottom, &viewport);
2049     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMViewport interface (hr = %x)\n", hr);
2050     hr = IDirect3DRMViewport_GetDirect3DViewport(viewport, &d3d_viewport);
2051     ok(SUCCEEDED(hr), "Cannot get IDirect3DViewport interface (hr = %#x).\n", hr);
2052     viewport_ref = get_refcount((IUnknown *)d3d_viewport);
2053     hr = IDirect3DRMViewport_GetDirect3DViewport(viewport, &d3d_viewport);
2054     ok(SUCCEEDED(hr), "Cannot get IDirect3DViewport interface (hr = %#x).\n", hr);
2055     ref4 = get_refcount((IUnknown *)d3d_viewport);
2056     ok(ref4 > viewport_ref, "Expected ref4 > viewport_ref, got ref4 = %u, viewport_ref = %u.\n", ref4, viewport_ref);
2057     IDirect3DViewport_Release(d3d_viewport);
2058     ref4 = get_refcount((IUnknown *)d3d_viewport);
2059     ok(ref4 == viewport_ref, "Expected ref4 == viewport_ref, got ref4 = %u, viewport_ref = %u.\n", ref4, viewport_ref);
2060     IDirect3DViewport_Release(d3d_viewport);
2061 
2062     hr = IDirect3DRMViewport_GetDirect3DViewport(viewport, &d3d_viewport);
2063     ok(SUCCEEDED(hr), "Cannot get IDirect3DViewport interface (hr = %#x).\n", hr);
2064     vp.dwSize = sizeof(vp);
2065     hr = IDirect3DViewport_GetViewport(d3d_viewport, &vp);
2066     ok(SUCCEEDED(hr), "Cannot get D3DVIEWPORT struct (hr = %#x).\n", hr);
2067     ok(vp.dwWidth == rc.right, "Expected viewport width = %u, got %u.\n", rc.right, vp.dwWidth);
2068     ok(vp.dwHeight == rc.bottom, "Expected viewport height = %u, got %u.\n", rc.bottom, vp.dwHeight);
2069     ok(vp.dwX == rc.left, "Expected viewport X position = %u, got %u.\n", rc.left, vp.dwX);
2070     ok(vp.dwY == rc.top, "Expected viewport Y position = %u, got %u.\n", rc.top, vp.dwY);
2071     expected_val = (rc.right > rc.bottom) ? (rc.right / 2.0f) : (rc.bottom / 2.0f);
2072     ok(vp.dvScaleX == expected_val, "Expected dvScaleX = %f, got %f.\n", expected_val, vp.dvScaleX);
2073     ok(vp.dvScaleY == expected_val, "Expected dvScaleY = %f, got %f.\n", expected_val, vp.dvScaleY);
2074     expected_val = vp.dwWidth / (2.0f * vp.dvScaleX);
2075     ok(vp.dvMaxX == expected_val, "Expected dvMaxX = %f, got %f.\n", expected_val, vp.dvMaxX);
2076     expected_val = vp.dwHeight / (2.0f * vp.dvScaleY);
2077     ok(vp.dvMaxY == expected_val, "Expected dvMaxY = %f, got %f.\n", expected_val, vp.dvMaxY);
2078     IDirect3DViewport_Release(d3d_viewport);
2079 
2080     hr = IDirect3DRMViewport_QueryInterface(viewport, &IID_IDirect3DRMObject, (void**)&obj);
2081     ok(hr == D3DRM_OK, "expected D3DRM_OK (hr = %x)\n", hr);
2082     ok((IDirect3DRMObject*)viewport == obj, "got object pointer %p, expected %p\n", obj, viewport);
2083 
2084     hr = IDirect3DRMViewport_QueryInterface(viewport, &IID_IDirect3DRMViewport2, (void**)&viewport2);
2085     ok(hr == D3DRM_OK, "expected D3DRM_OK (hr = %x)\n", hr);
2086 
2087     hr = IDirect3DRMViewport2_QueryInterface(viewport2, &IID_IDirect3DRMObject, (void**)&obj2);
2088     ok(hr == D3DRM_OK, "expected D3DRM_OK (hr = %x)\n", hr);
2089     ok(obj == obj2, "got object pointer %p, expected %p\n", obj2, obj);
2090     ok((IUnknown*)viewport != (IUnknown*)viewport2, "got viewport1 %p, viewport2 %p\n", viewport, viewport2);
2091 
2092     IDirect3DRMViewport2_Release(viewport2);
2093     IDirect3DRMObject_Release(obj);
2094     IDirect3DRMObject_Release(obj2);
2095 
2096     test_class_name((IDirect3DRMObject *)viewport, "Viewport");
2097     test_object_name((IDirect3DRMObject *)viewport);
2098 
2099     /* AppData */
2100     hr = IDirect3DRMViewport_SetAppData(viewport, 0);
2101     ok(hr == D3DRM_OK, "expected D3DRM_OK (hr = %x)\n", hr);
2102 
2103     hr = IDirect3DRMViewport_SetAppData(viewport, 0);
2104     ok(hr == D3DRM_OK, "expected D3DRM_OK (hr = %x)\n", hr);
2105 
2106     hr = IDirect3DRMViewport_SetAppData(viewport, 1);
2107     ok(hr == D3DRM_OK, "expected D3DRM_OK (hr = %x)\n", hr);
2108 
2109     hr = IDirect3DRMViewport_SetAppData(viewport, 1);
2110     ok(hr == D3DRM_OK, "expected D3DRM_OK (hr = %x)\n", hr);
2111 
2112     hr = IDirect3DRMViewport_QueryInterface(viewport, &IID_IDirect3DRMViewport2, (void**)&viewport2);
2113     ok(hr == D3DRM_OK, "expected D3DRM_OK (hr = %x)\n", hr);
2114 
2115     data = IDirect3DRMViewport2_GetAppData(viewport2);
2116     ok(data == 1, "got %x\n", data);
2117     IDirect3DRMViewport2_Release(viewport2);
2118     IDirect3DRMViewport_Release(viewport);
2119 
2120     /* IDirect3DRMViewport*::Init tests */
2121     ref1 = get_refcount((IUnknown *)d3drm1);
2122     ref2 = get_refcount((IUnknown *)d3drm2);
2123     ref3 = get_refcount((IUnknown *)d3drm3);
2124     hr = IDirect3DRM_CreateObject(d3drm1, &CLSID_CDirect3DRMViewport, NULL, &IID_IDirect3DRMViewport,
2125             (void **)&viewport);
2126     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMViewport interface (hr = %#x).\n", hr);
2127     ref4 = get_refcount((IUnknown *)d3drm1);
2128     ok(ref4 == ref1, "Expected ref4 == ref1, got ref1 = %u, ref4 = %u.\n", ref1, ref4);
2129     ref4 = get_refcount((IUnknown *)d3drm2);
2130     ok(ref4 == ref2, "Expected ref4 == ref2, got ref2 = %u, ref4 = %u.\n", ref2, ref4);
2131     ref4 = get_refcount((IUnknown *)d3drm3);
2132     ok(ref4 == ref3, "Expected ref4 == ref3, got ref3 = %u, ref4 = %u.\n", ref3, ref4);
2133 
2134     hr = IDirect3DRMViewport_GetDirect3DViewport(viewport, &d3d_viewport);
2135     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
2136     hr = IDirect3DRMViewport_GetDevice(viewport, &d3drm_device1);
2137     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
2138     hr = IDirect3DRMViewport_GetCamera(viewport, &d3drm_frame);
2139     ok(hr == D3DRMERR_BADOBJECT, "Got unexpected hr %#x.\n", hr);
2140     field = IDirect3DRMViewport_GetField(viewport);
2141     ok(field == -1.0f, "Got unexpected field %.8e.\n", field);
2142     left = right = bottom = top = 10.0f;
2143     hr = IDirect3DRMViewport_GetPlane(viewport, &left, &right, &bottom, &top);
2144     ok(hr == D3DRMERR_BADOBJECT, "Got unexpected hr %#x.\n", hr);
2145     ok(left == 10.0f, "Got unexpected left %.8e.\n", left);
2146     ok(right == 10.0f, "Got unexpected right %.8e.\n", right);
2147     ok(bottom == 10.0f, "Got unexpected bottom %.8e.\n", bottom);
2148     ok(top == 10.0f, "Got unexpected top %.8e.\n", top);
2149     front = IDirect3DRMViewport_GetFront(viewport);
2150     ok(front == -1.0f, "Got unexpected front %.8e\n", front);
2151     back = IDirect3DRMViewport_GetBack(viewport);
2152     ok(back == -1.0f, "Got unexpected back %.8e\n", back);
2153 
2154     hr = IDirect3DRMViewport_SetCamera(viewport, frame);
2155     ok(hr == D3DRMERR_BADOBJECT, "Got unexpected hr %#x.\n", hr);
2156     hr = IDirect3DRMViewport_SetField(viewport, 0.5f);
2157     ok(hr == D3DRMERR_BADOBJECT, "Got unexpected hr %#x.\n", hr);
2158     hr = IDirect3DRMViewport_SetPlane(viewport, -0.5f, 0.5f, -0.5f, 0.5f);
2159     ok(hr == D3DRMERR_BADOBJECT, "Got unexpected hr %#x.\n", hr);
2160     hr = IDirect3DRMViewport_SetFront(viewport, 1.0f);
2161     ok(hr == D3DRMERR_BADOBJECT, "Got unexpected hr %#x.\n", hr);
2162     hr = IDirect3DRMViewport_SetBack(viewport, 100.0f);
2163     ok(hr == D3DRMERR_BADOBJECT, "Got unexpected hr %#x.\n", hr);
2164 
2165     /* Test all failures together */
2166     hr = IDirect3DRMViewport_Init(viewport, NULL, frame, rc.left, rc.top, rc.right, rc.bottom);
2167     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
2168     hr = IDirect3DRMViewport_Init(viewport, device1, NULL, rc.left, rc.top, rc.right, rc.bottom);
2169     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
2170     hr = IDirect3DRMViewport_Init(viewport, device1, frame, rc.left, rc.top, rc.right + 1, rc.bottom + 1);
2171     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
2172     hr = IDirect3DRMViewport_Init(viewport, device1, frame, rc.left, rc.top, rc.right + 1, rc.bottom);
2173     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
2174     hr = IDirect3DRMViewport_Init(viewport, device1, frame, rc.left, rc.top, rc.right, rc.bottom + 1);
2175     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
2176 
2177     device_ref = get_refcount((IUnknown *)device1);
2178     frame_ref = get_refcount((IUnknown *)frame);
2179     hr = IDirect3DRMViewport_Init(viewport, device1, frame, rc.left, rc.top, rc.right, rc.bottom);
2180     ok(SUCCEEDED(hr), "Cannot initialize IDirect3DRMViewport interface (hr = %#x).\n", hr);
2181     ref4 = get_refcount((IUnknown *)d3drm1);
2182     ok(ref4 > ref1, "Expected ref4 > ref1, got ref1 = %u, ref4 = %u.\n", ref1, ref4);
2183     ref4 = get_refcount((IUnknown *)d3drm2);
2184     ok(ref4 == ref2, "Expected ref4 == ref2, got ref2 = %u, ref4 = %u.\n", ref2, ref4);
2185     ref4 = get_refcount((IUnknown *)d3drm3);
2186     ok(ref4 == ref3, "Expected ref4 == ref3, got ref3 = %u, ref4 = %u.\n", ref3, ref4);
2187     ref4 = get_refcount((IUnknown *)device1);
2188     ok(ref4 == device_ref, "Expected ref4 == device_ref, got device_ref = %u, ref4 = %u.\n", device_ref, ref4);
2189     ref4 = get_refcount((IUnknown *)frame);
2190     ok(ref4 > frame_ref, "Expected ref4 > frame_ref, got frame_ref = %u, ref4 = %u.\n", frame_ref, ref4);
2191 
2192     hr = IDirect3DRMViewport_GetDevice(viewport, &d3drm_device1);
2193     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMDevice3 interface (hr = %x)\n", hr);
2194     ok(device1 == d3drm_device1, "Expected device returned = %p, got %p.\n", device3, d3drm_device3);
2195     IDirect3DRMDevice_Release(d3drm_device1);
2196 
2197     hr = IDirect3DRMViewport_GetDirect3DViewport(viewport, &d3d_viewport);
2198     ok(SUCCEEDED(hr), "Cannot get IDirect3DViewport interface (hr = %#x).\n", hr);
2199     viewport_ref = get_refcount((IUnknown *)d3d_viewport);
2200     hr = IDirect3DRMViewport_GetDirect3DViewport(viewport, &d3d_viewport);
2201     ok(SUCCEEDED(hr), "Cannot get IDirect3DViewport interface (hr = %#x).\n", hr);
2202     ref4 = get_refcount((IUnknown *)d3d_viewport);
2203     ok(ref4 > viewport_ref, "Expected ref4 > viewport_ref, got ref4 = %u, viewport_ref = %u.\n", ref4, viewport_ref);
2204     IDirect3DViewport_Release(d3d_viewport);
2205     ref4 = get_refcount((IUnknown *)d3d_viewport);
2206     ok(ref4 == viewport_ref, "Expected ref4 == viewport_ref, got ref4 = %u, viewport_ref = %u.\n", ref4, viewport_ref);
2207     IDirect3DViewport_Release(d3d_viewport);
2208 
2209     hr = IDirect3DRMViewport_GetDirect3DViewport(viewport, &d3d_viewport);
2210     ok(SUCCEEDED(hr), "Cannot get IDirect3DViewport interface (hr = %#x).\n", hr);
2211     vp.dwSize = sizeof(vp);
2212     hr = IDirect3DViewport_GetViewport(d3d_viewport, &vp);
2213     ok(SUCCEEDED(hr), "Cannot get D3DVIEWPORT struct (hr = %#x).\n", hr);
2214     ok(vp.dwWidth == rc.right, "Expected viewport width = %u, got %u.\n", rc.right, vp.dwWidth);
2215     ok(vp.dwHeight == rc.bottom, "Expected viewport height = %u, got %u.\n", rc.bottom, vp.dwHeight);
2216     ok(vp.dwX == rc.left, "Expected viewport X position = %u, got %u.\n", rc.left, vp.dwX);
2217     ok(vp.dwY == rc.top, "Expected viewport Y position = %u, got %u.\n", rc.top, vp.dwY);
2218     expected_val = (rc.right > rc.bottom) ? (rc.right / 2.0f) : (rc.bottom / 2.0f);
2219     ok(vp.dvScaleX == expected_val, "Expected dvScaleX = %f, got %f.\n", expected_val, vp.dvScaleX);
2220     ok(vp.dvScaleY == expected_val, "Expected dvScaleY = %f, got %f.\n", expected_val, vp.dvScaleY);
2221     expected_val = vp.dwWidth / (2.0f * vp.dvScaleX);
2222     ok(vp.dvMaxX == expected_val, "Expected dvMaxX = %f, got %f.\n", expected_val, vp.dvMaxX);
2223     expected_val = vp.dwHeight / (2.0f * vp.dvScaleY);
2224     ok(vp.dvMaxY == expected_val, "Expected dvMaxY = %f, got %f.\n", expected_val, vp.dvMaxY);
2225     IDirect3DViewport_Release(d3d_viewport);
2226 
2227     field = IDirect3DRMViewport_GetField(viewport);
2228     ok(field == 0.5f, "Got unexpected field %.8e.\n", field);
2229     hr = IDirect3DRMViewport_GetPlane(viewport, &left, &right, &bottom, &top);
2230     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
2231     ok(left == -0.5f, "Got unexpected left %.8e.\n", left);
2232     ok(right == 0.5f, "Got unexpected right %.8e.\n", right);
2233     ok(bottom == -0.5f, "Got unexpected bottom %.8e.\n", bottom);
2234     ok(top == 0.5f, "Got unexpected top %.8e.\n", top);
2235     front = IDirect3DRMViewport_GetFront(viewport);
2236     ok(front == 1.0f, "Got unexpected front %.8e.\n", front);
2237     back = IDirect3DRMViewport_GetBack(viewport);
2238     ok(back == 100.0f, "Got unexpected back %.8e.\n", back);
2239 
2240     hr = IDirect3DRMViewport_SetField(viewport, 1.0f);
2241     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
2242     field = IDirect3DRMViewport_GetField(viewport);
2243     ok(field == 1.0f, "Got unexpected field %.8e.\n", field);
2244     hr = IDirect3DRMViewport_GetPlane(viewport, &left, &right, &bottom, &top);
2245     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
2246     ok(left == -1.0f, "Got unexpected left %.8e.\n", left);
2247     ok(right == 1.0f, "Got unexpected right %.8e.\n", right);
2248     ok(bottom == -1.0f, "Got unexpected bottom %.8e.\n", bottom);
2249     ok(top == 1.0f, "Got unexpected top %.8e.\n", top);
2250 
2251     hr = IDirect3DRMViewport_SetPlane(viewport, 5.0f, 3.0f, 2.0f, 0.0f);
2252     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
2253     field = IDirect3DRMViewport_GetField(viewport);
2254     ok(field == -1.0f, "Got unexpected field %.8e.\n", field);
2255     hr = IDirect3DRMViewport_GetPlane(viewport, &left, &right, &bottom, &top);
2256     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
2257     ok(left == 5.0f, "Got unexpected left %.8e.\n", left);
2258     ok(right == 3.0f, "Got unexpected right %.8e.\n", right);
2259     ok(bottom == 2.0f, "Got unexpected bottom %.8e.\n", bottom);
2260     ok(top == 0.0f, "Got unexpected top %.8e.\n", top);
2261     hr = IDirect3DRMViewport_SetFront(viewport, 2.0f);
2262     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
2263     front = IDirect3DRMViewport_GetFront(viewport);
2264     ok(front == 2.0f, "Got unexpected front %.8e.\n", front);
2265     hr = IDirect3DRMViewport_SetBack(viewport, 200.0f);
2266     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
2267     back = IDirect3DRMViewport_GetBack(viewport);
2268     ok(back == 200.0f, "Got unexpected back %.8e.\n", back);
2269 
2270     hr = IDirect3DRMViewport_Init(viewport, device1, frame, rc.left, rc.top, rc.right, rc.bottom);
2271     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
2272     hr = IDirect3DRMViewport_GetDevice(viewport, NULL);
2273     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
2274     hr = IDirect3DRMViewport_GetDirect3DViewport(viewport, NULL);
2275     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
2276     hr = IDirect3DRMViewport_GetCamera(viewport, NULL);
2277     ok(hr == D3DRMERR_BADVALUE, "Got unexpected hr %#x.\n", hr);
2278     hr = IDirect3DRMViewport_SetField(viewport, 0.0f);
2279     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
2280     hr = IDirect3DRMViewport_SetField(viewport, -1.0f);
2281     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
2282     hr = IDirect3DRMViewport_SetFront(viewport, 0.0f);
2283     ok(hr == D3DRMERR_BADVALUE, "Got unexpected hr %#x.\n", hr);
2284     hr = IDirect3DRMViewport_SetFront(viewport, -1.0f);
2285     ok(hr == D3DRMERR_BADVALUE, "Got unexpected hr %#x.\n", hr);
2286     front = IDirect3DRMViewport_GetFront(viewport);
2287     hr = IDirect3DRMViewport_SetBack(viewport, front);
2288     ok(hr == D3DRMERR_BADVALUE, "Got unexpected hr %#x.\n", hr);
2289     hr = IDirect3DRMViewport_SetBack(viewport, front / 2.0f);
2290     ok(hr == D3DRMERR_BADVALUE, "Got unexpected hr %#x.\n", hr);
2291 
2292     IDirect3DRMViewport_Release(viewport);
2293     ref4 = get_refcount((IUnknown *)d3drm1);
2294     todo_wine ok(ref4 > ref1, "Expected ref4 > ref1, got ref1 = %u, ref4 = %u.\n", ref1, ref4);
2295     ref4 = get_refcount((IUnknown *)d3drm2);
2296     ok(ref4 == ref2, "Expected ref4 == ref2, got ref2 = %u, ref4 = %u.\n", ref2, ref4);
2297     ref4 = get_refcount((IUnknown *)d3drm3);
2298     ok(ref4 == ref3, "Expected ref4 == ref3, got ref3 = %u, ref4 = %u.\n", ref3, ref4);
2299     ref4 = get_refcount((IUnknown *)device1);
2300     ok(ref4 == device_ref, "Expected ref4 == device_ref, got device_ref = %u, ref4 = %u.\n", device_ref, ref4);
2301     ref4 = get_refcount((IUnknown *)frame);
2302     todo_wine ok(ref4 > frame_ref, "Expected ref4 > frame_ref, got frame_ref = %u, ref4 = %u.\n", frame_ref, ref4);
2303 
2304     ref1 = get_refcount((IUnknown *)d3drm1);
2305     ref2 = get_refcount((IUnknown *)d3drm2);
2306     ref3 = get_refcount((IUnknown *)d3drm3);
2307     hr = IDirect3DRM3_CreateObject(d3drm2, &CLSID_CDirect3DRMViewport, NULL, &IID_IDirect3DRMViewport2,
2308             (void **)&viewport2);
2309     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMViewport2 interface (hr = %#x).\n", hr);
2310     ref4 = get_refcount((IUnknown *)d3drm1);
2311     ok(ref4 == ref1, "Expected ref4 == ref1, got ref1 = %u, ref4 = %u.\n", ref1, ref4);
2312     ref4 = get_refcount((IUnknown *)d3drm2);
2313     ok(ref4 == ref2, "Expected ref4 == ref2, got ref2 = %u, ref4 = %u.\n", ref2, ref4);
2314     ref4 = get_refcount((IUnknown *)d3drm3);
2315     ok(ref4 == ref3, "Expected ref4 == ref3, got ref3 = %u, ref4 = %u.\n", ref3, ref4);
2316 
2317     hr = IDirect3DRMViewport2_GetDirect3DViewport(viewport2, &d3d_viewport);
2318     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
2319     hr = IDirect3DRMViewport2_GetDevice(viewport2, &d3drm_device3);
2320     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
2321     hr = IDirect3DRMViewport2_GetCamera(viewport2, &d3drm_frame3);
2322     ok(hr == D3DRMERR_BADOBJECT, "Got unexpected hr %#x.\n", hr);
2323     field = IDirect3DRMViewport2_GetField(viewport2);
2324     ok(field == -1.0f, "Got unexpected field %.8e.\n", field);
2325     left = right = bottom = top = 10.0f;
2326     hr = IDirect3DRMViewport2_GetPlane(viewport2, &left, &right, &bottom, &top);
2327     ok(hr == D3DRMERR_BADOBJECT, "Got unexpected hr %#x.\n", hr);
2328     ok(left == 10.0f, "Got unexpected left %.8e.\n", left);
2329     ok(right == 10.0f, "Got unexpected right %.8e.\n", right);
2330     ok(bottom == 10.0f, "Got unexpected bottom %.8e.\n", bottom);
2331     ok(top == 10.0f, "Got unexpected top %.8e.\n", top);
2332     front = IDirect3DRMViewport2_GetFront(viewport2);
2333     ok(front == -1.0f, "Got unexpected front %.8e\n", front);
2334     back = IDirect3DRMViewport2_GetBack(viewport2);
2335     ok(back == -1.0f, "Got unexpected back %.8e\n", back);
2336 
2337     hr = IDirect3DRMViewport2_SetCamera(viewport2, frame3);
2338     ok(hr == D3DRMERR_BADOBJECT, "Got unexpected hr %#x.\n", hr);
2339     hr = IDirect3DRMViewport2_SetField(viewport2, 0.5f);
2340     ok(hr == D3DRMERR_BADOBJECT, "Got unexpected hr %#x.\n", hr);
2341     hr = IDirect3DRMViewport2_SetPlane(viewport2, -0.5f, 0.5f, -0.5f, 0.5f);
2342     ok(hr == D3DRMERR_BADOBJECT, "Got unexpected hr %#x.\n", hr);
2343     hr = IDirect3DRMViewport2_SetFront(viewport2, 1.0f);
2344     ok(hr == D3DRMERR_BADOBJECT, "Got unexpected hr %#x.\n", hr);
2345     hr = IDirect3DRMViewport2_SetBack(viewport2, 100.0f);
2346     ok(hr == D3DRMERR_BADOBJECT, "Got unexpected hr %#x.\n", hr);
2347 
2348     hr = IDirect3DRMViewport2_Init(viewport2, NULL, frame3, rc.left, rc.top, rc.right, rc.bottom);
2349     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
2350     hr = IDirect3DRMViewport2_Init(viewport2, device3, NULL, rc.left, rc.top, rc.right, rc.bottom);
2351     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
2352     hr = IDirect3DRMViewport2_Init(viewport2, device3, frame3, rc.left, rc.top, rc.right + 1, rc.bottom + 1);
2353     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
2354     hr = IDirect3DRMViewport2_Init(viewport2, device3, frame3, rc.left, rc.top, rc.right + 1, rc.bottom);
2355     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
2356     hr = IDirect3DRMViewport2_Init(viewport2, device3, frame3, rc.left, rc.top, rc.right, rc.bottom + 1);
2357     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
2358 
2359     device_ref = get_refcount((IUnknown *)device3);
2360     frame_ref2 = get_refcount((IUnknown *)frame3);
2361     hr = IDirect3DRMViewport2_Init(viewport2, device3, frame3, rc.left, rc.top, rc.right, rc.bottom);
2362     ok(SUCCEEDED(hr), "Cannot initialize IDirect3DRMViewport2 interface (hr = %#x).\n", hr);
2363     ref4 = get_refcount((IUnknown *)device3);
2364     ok(ref4 == device_ref, "Expected ref4 == device_ref, got device_ref = %u, ref4 = %u.\n", device_ref, ref4);
2365     ref4 = get_refcount((IUnknown *)frame3);
2366     ok(ref4 > frame_ref2, "Expected ref4 > frame_ref2, got frame_ref2 = %u, ref4 = %u.\n", frame_ref2, ref4);
2367 
2368     hr = IDirect3DRMViewport2_GetDevice(viewport2, &d3drm_device3);
2369     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMDevice3 interface (hr = %x)\n", hr);
2370     ok(device3 == d3drm_device3, "Expected device returned = %p, got %p.\n", device3, d3drm_device3);
2371     IDirect3DRMDevice3_Release(d3drm_device3);
2372 
2373     hr = IDirect3DRMViewport2_GetDirect3DViewport(viewport2, &d3d_viewport);
2374     ok(SUCCEEDED(hr), "Cannot get IDirect3DViewport interface (hr = %#x).\n", hr);
2375     viewport_ref = get_refcount((IUnknown *)d3d_viewport);
2376     hr = IDirect3DRMViewport2_GetDirect3DViewport(viewport2, &d3d_viewport);
2377     ok(SUCCEEDED(hr), "Cannot get IDirect3DViewport interface (hr = %#x).\n", hr);
2378     ref4 = get_refcount((IUnknown *)d3d_viewport);
2379     ok(ref4 > viewport_ref, "Expected ref4 > viewport_ref, got ref4 = %u, viewport_ref = %u.\n", ref4, viewport_ref);
2380     IDirect3DViewport_Release(d3d_viewport);
2381     ref4 = get_refcount((IUnknown *)d3d_viewport);
2382     ok(ref4 == viewport_ref, "Expected ref4 == viewport_ref, got ref4 = %u, viewport_ref = %u.\n", ref4, viewport_ref);
2383     IDirect3DViewport_Release(d3d_viewport);
2384 
2385     hr = IDirect3DRMViewport2_GetDirect3DViewport(viewport2, &d3d_viewport);
2386     ok(SUCCEEDED(hr), "Cannot get IDirect3DViewport interface (hr = %#x).\n", hr);
2387     vp.dwSize = sizeof(vp);
2388     hr = IDirect3DViewport_GetViewport(d3d_viewport, &vp);
2389     ok(SUCCEEDED(hr), "Cannot get D3DVIEWPORT struct (hr = %#x).\n", hr);
2390     ok(vp.dwWidth == rc.right, "Expected viewport width = %u, got %u.\n", rc.right, vp.dwWidth);
2391     ok(vp.dwHeight == rc.bottom, "Expected viewport height = %u, got %u.\n", rc.bottom, vp.dwHeight);
2392     ok(vp.dwX == rc.left, "Expected viewport X position = %u, got %u.\n", rc.left, vp.dwX);
2393     ok(vp.dwY == rc.top, "Expected viewport Y position = %u, got %u.\n", rc.top, vp.dwY);
2394     expected_val = (rc.right > rc.bottom) ? (rc.right / 2.0f) : (rc.bottom / 2.0f);
2395     ok(vp.dvScaleX == expected_val, "Expected dvScaleX = %f, got %f.\n", expected_val, vp.dvScaleX);
2396     ok(vp.dvScaleY == expected_val, "Expected dvScaleY = %f, got %f.\n", expected_val, vp.dvScaleY);
2397     expected_val = vp.dwWidth / (2.0f * vp.dvScaleX);
2398     ok(vp.dvMaxX == expected_val, "Expected dvMaxX = %f, got %f.\n", expected_val, vp.dvMaxX);
2399     expected_val = vp.dwHeight / (2.0f * vp.dvScaleY);
2400     ok(vp.dvMaxY == expected_val, "Expected dvMaxY = %f, got %f.\n", expected_val, vp.dvMaxY);
2401     IDirect3DViewport_Release(d3d_viewport);
2402 
2403     field = IDirect3DRMViewport2_GetField(viewport2);
2404     ok(field == 0.5f, "Got unexpected field %.8e.\n", field);
2405     hr = IDirect3DRMViewport2_GetPlane(viewport2, &left, &right, &bottom, &top);
2406     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
2407     ok(left == -0.5f, "Got unexpected left %.8e.\n", left);
2408     ok(right == 0.5f, "Got unexpected right %.8e.\n", right);
2409     ok(bottom == -0.5f, "Got unexpected bottom %.8e.\n", bottom);
2410     ok(top == 0.5f, "Got unexpected top %.8e.\n", top);
2411     front = IDirect3DRMViewport2_GetFront(viewport2);
2412     ok(front == 1.0f, "Got unexpected front %.8e.\n", front);
2413     back = IDirect3DRMViewport2_GetBack(viewport2);
2414     ok(back == 100.0f, "Got unexpected back %.8e.\n", back);
2415 
2416     hr = IDirect3DRMViewport2_SetField(viewport2, 1.0f);
2417     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
2418     field = IDirect3DRMViewport2_GetField(viewport2);
2419     ok(field == 1.0f, "Got unexpected field %.8e.\n", field);
2420     hr = IDirect3DRMViewport2_GetPlane(viewport2, &left, &right, &bottom, &top);
2421     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
2422     ok(left == -1.0f, "Got unexpected left %.8e.\n", left);
2423     ok(right == 1.0f, "Got unexpected right %.8e.\n", right);
2424     ok(bottom == -1.0f, "Got unexpected bottom %.8e.\n", bottom);
2425     ok(top == 1.0f, "Got unexpected top %.8e.\n", top);
2426 
2427     hr = IDirect3DRMViewport2_SetPlane(viewport2, 5.0f, 3.0f, 2.0f, 0.0f);
2428     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
2429     field = IDirect3DRMViewport2_GetField(viewport2);
2430     ok(field == -1.0f, "Got unexpected field %.8e.\n", field);
2431     hr = IDirect3DRMViewport2_GetPlane(viewport2, &left, &right, &bottom, &top);
2432     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
2433     ok(left == 5.0f, "Got unexpected left %.8e.\n", left);
2434     ok(right == 3.0f, "Got unexpected right %.8e.\n", right);
2435     ok(bottom == 2.0f, "Got unexpected bottom %.8e.\n", bottom);
2436     ok(top == 0.0f, "Got unexpected top %.8e.\n", top);
2437     hr = IDirect3DRMViewport2_SetFront(viewport2, 2.0f);
2438     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
2439     front = IDirect3DRMViewport2_GetFront(viewport2);
2440     ok(front == 2.0f, "Got unexpected front %.8e.\n", front);
2441     hr = IDirect3DRMViewport2_SetBack(viewport2, 200.0f);
2442     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
2443     back = IDirect3DRMViewport2_GetBack(viewport2);
2444     ok(back == 200.0f, "Got unexpected back %.8e.\n", back);
2445 
2446     hr = IDirect3DRMViewport2_Init(viewport2, device3, frame3, rc.left, rc.top, rc.right, rc.bottom);
2447     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
2448     hr = IDirect3DRMViewport2_GetDevice(viewport2, NULL);
2449     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
2450     hr = IDirect3DRMViewport2_GetDirect3DViewport(viewport2, NULL);
2451     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
2452     hr = IDirect3DRMViewport2_GetCamera(viewport2, NULL);
2453     ok(hr == D3DRMERR_BADVALUE, "Got unexpected hr %#x.\n", hr);
2454     hr = IDirect3DRMViewport2_SetField(viewport2, 0.0f);
2455     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
2456     hr = IDirect3DRMViewport2_SetField(viewport2, -1.0f);
2457     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
2458     hr = IDirect3DRMViewport2_SetFront(viewport2, 0.0f);
2459     ok(hr == D3DRMERR_BADVALUE, "Got unexpected hr %#x.\n", hr);
2460     hr = IDirect3DRMViewport2_SetFront(viewport2, -1.0f);
2461     ok(hr == D3DRMERR_BADVALUE, "Got unexpected hr %#x.\n", hr);
2462     front = IDirect3DRMViewport2_GetFront(viewport2);
2463     hr = IDirect3DRMViewport2_SetBack(viewport2, front);
2464     ok(hr == D3DRMERR_BADVALUE, "Got unexpected hr %#x.\n", hr);
2465     hr = IDirect3DRMViewport2_SetBack(viewport2, front / 2.0f);
2466     ok(hr == D3DRMERR_BADVALUE, "Got unexpected hr %#x.\n", hr);
2467 
2468     IDirect3DRMViewport2_Release(viewport2);
2469     ref4 = get_refcount((IUnknown *)d3drm1);
2470     todo_wine ok(ref4 > ref1, "Expected ref4 > ref1, got ref1 = %u, ref4 = %u.\n", ref1, ref4);
2471     ref4 = get_refcount((IUnknown *)d3drm2);
2472     ok(ref4 == ref2, "Expected ref4 == ref2, got ref2 = %u, ref4 = %u.\n", ref2, ref4);
2473     ref4 = get_refcount((IUnknown *)d3drm3);
2474     ok(ref4 == ref3, "Expected ref4 == ref3, got ref3 = %u, ref4 = %u.\n", ref3, ref4);
2475     ref4 = get_refcount((IUnknown *)device3);
2476     ok(ref4 == device_ref, "Expected ref4 == device_ref, got device_ref = %u, ref4 = %u.\n", device_ref, ref4);
2477     ref4 = get_refcount((IUnknown *)frame3);
2478     todo_wine ok(ref4 > frame_ref2, "Expected ref4 > frame_ref2, got frame_ref2 = %u, ref4 = %u.\n", frame_ref2, ref4);
2479 
2480     IDirect3DRMDevice3_Release(device3);
2481     IDirect3DRMDevice_Release(device1);
2482     ref4 = get_refcount((IUnknown *)d3drm1);
2483     ok(ref4 > initial_ref1, "Expected ref4 > initial_ref1, got initial_ref1 = %u, ref4 = %u.\n", initial_ref1, ref4);
2484     ref4 = get_refcount((IUnknown *)d3drm2);
2485     ok(ref4 == initial_ref2, "Expected ref4 == initial_ref2, got initial_ref2 = %u, ref4 = %u.\n", initial_ref2, ref4);
2486     ref4 = get_refcount((IUnknown *)d3drm3);
2487     ok(ref4 == initial_ref3, "Expected ref4 == initial_ref3, got initial_ref3 = %u, ref4 = %u.\n", initial_ref3, ref4);
2488     ref4 = get_refcount((IUnknown *)frame);
2489     ok(ref4 == frame_ref, "Expected ref4 == frame_ref, got frame_ref = %u, ref4 = %u.\n", frame_ref, ref4);
2490     ref4 = get_refcount((IUnknown *)frame3);
2491     ok(ref4 == frame_ref2, "Expected ref4 == frame_ref2, got frame_ref2 = %u, ref4 = %u.\n", frame_ref2, ref4);
2492 
2493     IDirect3DRMFrame3_Release(tmp_frame3);
2494     IDirect3DRMFrame3_Release(frame3);
2495     ref4 = get_refcount((IUnknown *)d3drm1);
2496     ok(ref4 > initial_ref1, "Expected ref4 > initial_ref1, got initial_ref1 = %u, ref4 = %u.\n", initial_ref1, ref4);
2497     ref4 = get_refcount((IUnknown *)d3drm2);
2498     ok(ref4 == initial_ref2, "Expected ref4 == initial_ref2, got initial_ref2 = %u, ref4 = %u.\n", initial_ref2, ref4);
2499     ref4 = get_refcount((IUnknown *)d3drm3);
2500     ok(ref4 == initial_ref3, "Expected ref4 == initial_ref3, got initial_ref3 = %u, ref4 = %u.\n", initial_ref3, ref4);
2501 
2502     IDirect3DRMFrame3_Release(tmp_frame1);
2503     IDirect3DRMFrame_Release(frame);
2504     ref4 = get_refcount((IUnknown *)d3drm1);
2505     ok(ref4 == initial_ref1, "Expected ref4 == initial_ref1, got initial_ref1 = %u, ref4 = %u.\n", initial_ref1, ref4);
2506     ref4 = get_refcount((IUnknown *)d3drm2);
2507     ok(ref4 == initial_ref2, "Expected ref4 == initial_ref2, got initial_ref2 = %u, ref4 = %u.\n", initial_ref2, ref4);
2508     ref4 = get_refcount((IUnknown *)d3drm3);
2509     ok(ref4 == initial_ref3, "Expected ref4 == initial_ref3, got initial_ref3 = %u, ref4 = %u.\n", initial_ref3, ref4);
2510     IDirectDrawClipper_Release(clipper);
2511 
2512     IDirect3DRM3_Release(d3drm3);
2513     IDirect3DRM2_Release(d3drm2);
2514     IDirect3DRM_Release(d3drm1);
2515     DestroyWindow(window);
2516 }
2517 
test_Light(void)2518 static void test_Light(void)
2519 {
2520     IDirect3DRMObject *object;
2521     HRESULT hr;
2522     IDirect3DRM *d3drm;
2523     IDirect3DRMLight *light;
2524     D3DRMLIGHTTYPE type;
2525     D3DCOLOR color;
2526 
2527     hr = Direct3DRMCreate(&d3drm);
2528     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x)\n", hr);
2529 
2530     hr = IDirect3DRM_CreateLightRGB(d3drm, D3DRMLIGHT_SPOT, 0.5, 0.5, 0.5, &light);
2531     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMLight interface (hr = %x)\n", hr);
2532 
2533     hr = IDirect3DRMLight_QueryInterface(light, &IID_IDirect3DRMObject, (void **)&object);
2534     ok(SUCCEEDED(hr), "Failed to get IDirect3DRMObject, hr %#x.\n", hr);
2535     IDirect3DRMObject_Release(object);
2536 
2537     test_class_name((IDirect3DRMObject *)light, "Light");
2538     test_object_name((IDirect3DRMObject *)light);
2539 
2540     type = IDirect3DRMLight_GetType(light);
2541     ok(type == D3DRMLIGHT_SPOT, "wrong type (%u)\n", type);
2542 
2543     color = IDirect3DRMLight_GetColor(light);
2544     ok(color == 0xff7f7f7f, "wrong color (%x)\n", color);
2545 
2546     hr = IDirect3DRMLight_SetType(light, D3DRMLIGHT_POINT);
2547     ok(hr == D3DRM_OK, "Cannot set type (hr = %x)\n", hr);
2548     type = IDirect3DRMLight_GetType(light);
2549     ok(type == D3DRMLIGHT_POINT, "wrong type (%u)\n", type);
2550 
2551     hr = IDirect3DRMLight_SetColor(light, 0xff180587);
2552     ok(hr == D3DRM_OK, "Cannot set color (hr = %x)\n", hr);
2553     color = IDirect3DRMLight_GetColor(light);
2554     ok(color == 0xff180587, "wrong color (%x)\n", color);
2555 
2556     hr = IDirect3DRMLight_SetColorRGB(light, 0.5, 0.5, 0.5);
2557     ok(hr == D3DRM_OK, "Cannot set color (hr = %x)\n", hr);
2558     color = IDirect3DRMLight_GetColor(light);
2559     ok(color == 0xff7f7f7f, "wrong color (%x)\n", color);
2560 
2561     IDirect3DRMLight_Release(light);
2562 
2563     IDirect3DRM_Release(d3drm);
2564 }
2565 
test_Material2(void)2566 static void test_Material2(void)
2567 {
2568     HRESULT hr;
2569     IDirect3DRM *d3drm;
2570     IDirect3DRM3 *d3drm3;
2571     IDirect3DRMMaterial2 *material2;
2572     D3DVALUE r, g, b;
2573 
2574     hr = Direct3DRMCreate(&d3drm);
2575     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x)\n", hr);
2576 
2577     if (FAILED(hr = IDirect3DRM_QueryInterface(d3drm, &IID_IDirect3DRM3, (void **)&d3drm3)))
2578     {
2579         win_skip("Cannot get IDirect3DRM3 interface (hr = %x), skipping tests\n", hr);
2580         IDirect3DRM_Release(d3drm);
2581         return;
2582     }
2583 
2584     hr = IDirect3DRM3_CreateMaterial(d3drm3, 18.5f, &material2);
2585     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMMaterial2 interface (hr = %x)\n", hr);
2586 
2587     test_class_name((IDirect3DRMObject *)material2, "Material");
2588     test_object_name((IDirect3DRMObject *)material2);
2589 
2590     r = IDirect3DRMMaterial2_GetPower(material2);
2591     ok(r == 18.5f, "wrong power (%f)\n", r);
2592 
2593     hr = IDirect3DRMMaterial2_GetEmissive(material2, &r, &g, &b);
2594     ok(hr == D3DRM_OK, "Cannot get emissive (hr = %x)\n", hr);
2595     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);
2596 
2597     hr = IDirect3DRMMaterial2_GetSpecular(material2, &r, &g, &b);
2598     ok(hr == D3DRM_OK, "Cannot get emissive (hr = %x)\n", hr);
2599     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);
2600 
2601     hr = IDirect3DRMMaterial2_GetAmbient(material2, &r, &g, &b);
2602     ok(hr == D3DRM_OK, "Cannot get emissive (hr = %x)\n", hr);
2603     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);
2604 
2605     hr = IDirect3DRMMaterial2_SetPower(material2, 5.87f);
2606     ok(hr == D3DRM_OK, "Cannot set power (hr = %x)\n", hr);
2607     r = IDirect3DRMMaterial2_GetPower(material2);
2608     ok(r == 5.87f, "wrong power (%f)\n", r);
2609 
2610     hr = IDirect3DRMMaterial2_SetEmissive(material2, 0.5f, 0.5f, 0.5f);
2611     ok(hr == D3DRM_OK, "Cannot set emissive (hr = %x)\n", hr);
2612     hr = IDirect3DRMMaterial2_GetEmissive(material2, &r, &g, &b);
2613     ok(hr == D3DRM_OK, "Cannot get emissive (hr = %x)\n", hr);
2614     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);
2615 
2616     hr = IDirect3DRMMaterial2_SetSpecular(material2, 0.6f, 0.6f, 0.6f);
2617     ok(hr == D3DRM_OK, "Cannot set specular (hr = %x)\n", hr);
2618     hr = IDirect3DRMMaterial2_GetSpecular(material2, &r, &g, &b);
2619     ok(hr == D3DRM_OK, "Cannot get specular (hr = %x)\n", hr);
2620     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);
2621 
2622     hr = IDirect3DRMMaterial2_SetAmbient(material2, 0.7f, 0.7f, 0.7f);
2623     ok(hr == D3DRM_OK, "Cannot set ambient (hr = %x)\n", hr);
2624     hr = IDirect3DRMMaterial2_GetAmbient(material2, &r, &g, &b);
2625     ok(hr == D3DRM_OK, "Cannot get ambient (hr = %x)\n", hr);
2626     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);
2627 
2628     IDirect3DRMMaterial2_Release(material2);
2629 
2630     IDirect3DRM3_Release(d3drm3);
2631     IDirect3DRM_Release(d3drm);
2632 }
2633 
test_Texture(void)2634 static void test_Texture(void)
2635 {
2636     HRESULT hr;
2637     IDirect3DRM *d3drm1;
2638     IDirect3DRM2 *d3drm2;
2639     IDirect3DRM3 *d3drm3;
2640     IDirect3DRMTexture *texture1;
2641     IDirect3DRMTexture2 *texture2;
2642     IDirect3DRMTexture3 *texture3;
2643     IDirectDrawSurface *surface;
2644 
2645     D3DRMIMAGE initimg =
2646     {
2647         2, 2, 1, 1, 32,
2648         TRUE, 2 * sizeof(DWORD), NULL, NULL,
2649         0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000, 0, NULL
2650     },
2651     testimg =
2652     {
2653         0, 0, 0, 0, 0,
2654         TRUE, 0, (void *)0xcafebabe, NULL,
2655         0x000000ff, 0x0000ff00, 0x00ff0000, 0, 0, NULL
2656     },
2657     *d3drm_img = NULL;
2658 
2659     DWORD pixel[4] = { 20000, 30000, 10000, 0 };
2660     ULONG ref1, ref2, ref3, ref4;
2661 
2662     hr = Direct3DRMCreate(&d3drm1);
2663     ok(SUCCEEDED(hr), "Cannot get IDirect3DRM interface (hr = %x)\n", hr);
2664     ref1 = get_refcount((IUnknown *)d3drm1);
2665 
2666     hr = IDirect3DRM_QueryInterface(d3drm1, &IID_IDirect3DRM2, (void **)&d3drm2);
2667     ok(SUCCEEDED(hr), "Cannot get IDirect3DRM2 interface (hr = %x).\n", hr);
2668 
2669     hr = IDirect3DRM_QueryInterface(d3drm1, &IID_IDirect3DRM3, (void **)&d3drm3);
2670     ok(SUCCEEDED(hr), "Cannot get IDirect3DRM3 interface (hr = %x).\n", hr);
2671 
2672     /* Test NULL params */
2673     texture1 = (IDirect3DRMTexture *)0xdeadbeef;
2674     hr = IDirect3DRM_CreateTexture(d3drm1, NULL, &texture1);
2675     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
2676     ok(!texture1, "Expected texture returned == NULL, got %p.\n", texture1);
2677     hr = IDirect3DRM_CreateTexture(d3drm1, NULL, NULL);
2678     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
2679 
2680     texture2 = (IDirect3DRMTexture2 *)0xdeadbeef;
2681     hr = IDirect3DRM2_CreateTexture(d3drm2, NULL, &texture2);
2682     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
2683     ok(!texture2, "Expected texture returned == NULL, got %p.\n", texture2);
2684     hr = IDirect3DRM2_CreateTexture(d3drm2, NULL, NULL);
2685     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
2686 
2687     texture3 = (IDirect3DRMTexture3 *)0xdeadbeef;
2688     hr = IDirect3DRM3_CreateTexture(d3drm3, NULL, &texture3);
2689     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
2690     ok(!texture3, "Expected texture returned == NULL, got %p.\n", texture3);
2691     hr = IDirect3DRM3_CreateTexture(d3drm3, NULL, NULL);
2692     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
2693 
2694     /* Tests for validation of D3DRMIMAGE struct */
2695     hr = IDirect3DRM_CreateTexture(d3drm1, &testimg, &texture1);
2696     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMTexture interface (hr = %#x)\n", hr);
2697     hr = IDirect3DRM2_CreateTexture(d3drm2, &testimg, &texture2);
2698     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMTexture2 interface (hr = %#x)\n", hr);
2699     hr = IDirect3DRM3_CreateTexture(d3drm3, &testimg, &texture3);
2700     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMTexture3 interface (hr = %#x)\n", hr);
2701     IDirect3DRMTexture_Release(texture1);
2702     IDirect3DRMTexture2_Release(texture2);
2703     IDirect3DRMTexture3_Release(texture3);
2704 
2705     testimg.rgb = 0;
2706     testimg.palette = (void *)0xdeadbeef;
2707     testimg.palette_size = 0x39;
2708     hr = IDirect3DRM_CreateTexture(d3drm1, &testimg, &texture1);
2709     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMTexture interface (hr = %#x)\n", hr);
2710     hr = IDirect3DRM2_CreateTexture(d3drm2, &testimg, &texture2);
2711     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMTexture2 interface (hr = %#x)\n", hr);
2712     hr = IDirect3DRM3_CreateTexture(d3drm3, &testimg, &texture3);
2713     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMTexture3 interface (hr = %#x)\n", hr);
2714     IDirect3DRMTexture_Release(texture1);
2715     IDirect3DRMTexture2_Release(texture2);
2716     IDirect3DRMTexture3_Release(texture3);
2717 
2718     initimg.rgb = 0;
2719     texture1 = (IDirect3DRMTexture *)0xdeadbeef;
2720     hr = IDirect3DRM_CreateTexture(d3drm1, &initimg, &texture1);
2721     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
2722     ok(!texture1, "Expected texture == NULL, got %p.\n", texture1);
2723     texture2 = (IDirect3DRMTexture2 *)0xdeadbeef;
2724     hr = IDirect3DRM2_CreateTexture(d3drm2, &initimg, &texture2);
2725     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
2726     ok(!texture2, "Expected texture == NULL, got %p.\n", texture2);
2727     texture3 = (IDirect3DRMTexture3 *)0xdeadbeef;
2728     hr = IDirect3DRM3_CreateTexture(d3drm3, &initimg, &texture3);
2729     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
2730     ok(!texture3, "Expected texture == NULL, got %p.\n", texture3);
2731     initimg.rgb = 1;
2732     initimg.red_mask = 0;
2733     hr = IDirect3DRM_CreateTexture(d3drm1, &initimg, &texture1);
2734     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
2735     hr = IDirect3DRM2_CreateTexture(d3drm2, &initimg, &texture2);
2736     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
2737     hr = IDirect3DRM3_CreateTexture(d3drm3, &initimg, &texture3);
2738     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
2739     initimg.red_mask = 0x000000ff;
2740     initimg.green_mask = 0;
2741     hr = IDirect3DRM_CreateTexture(d3drm1, &initimg, &texture1);
2742     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
2743     hr = IDirect3DRM2_CreateTexture(d3drm2, &initimg, &texture2);
2744     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
2745     hr = IDirect3DRM3_CreateTexture(d3drm3, &initimg, &texture3);
2746     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
2747     initimg.green_mask = 0x0000ff00;
2748     initimg.blue_mask = 0;
2749     hr = IDirect3DRM_CreateTexture(d3drm1, &initimg, &texture1);
2750     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
2751     hr = IDirect3DRM2_CreateTexture(d3drm2, &initimg, &texture2);
2752     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
2753     hr = IDirect3DRM3_CreateTexture(d3drm3, &initimg, &texture3);
2754     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
2755     initimg.blue_mask = 0x00ff0000;
2756     initimg.buffer1 = NULL;
2757     hr = IDirect3DRM_CreateTexture(d3drm1, &initimg, &texture1);
2758     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
2759     hr = IDirect3DRM2_CreateTexture(d3drm2, &initimg, &texture2);
2760     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
2761     hr = IDirect3DRM3_CreateTexture(d3drm3, &initimg, &texture3);
2762     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
2763 
2764     initimg.buffer1 = &pixel;
2765     hr = IDirect3DRM_CreateTexture(d3drm1, &initimg, &texture1);
2766     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMTexture interface (hr = %#x)\n", hr);
2767     ref2 = get_refcount((IUnknown *)d3drm1);
2768     ok(ref2 > ref1, "expected ref2 > ref1, got ref1 = %u , ref2 = %u.\n", ref1, ref2);
2769     ref3 = get_refcount((IUnknown *)d3drm2);
2770     ok(ref3 == ref1, "expected ref3 == ref1, got ref1 = %u , ref3 = %u.\n", ref1, ref3);
2771     ref4 = get_refcount((IUnknown *)d3drm3);
2772     ok(ref4 == ref1, "expected ref4 == ref1, got ref1 = %u , ref4 = %u.\n", ref1, ref4);
2773     hr = IDirect3DRM2_CreateTexture(d3drm2, &initimg, &texture2);
2774     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMTexture2 interface (hr = %#x)\n", hr);
2775     ref2 = get_refcount((IUnknown *)d3drm1);
2776     ok(ref2 > ref1 + 1, "expected ref2 > (ref1 + 1), got ref1 = %u , ref2 = %u.\n", ref1, ref2);
2777     ref3 = get_refcount((IUnknown *)d3drm2);
2778     ok(ref3 == ref1, "expected ref3 == ref1, got ref1 = %u , ref3 = %u.\n", ref1, ref3);
2779     ref4 = get_refcount((IUnknown *)d3drm3);
2780     ok(ref4 == ref1, "expected ref4 == ref1, got ref1 = %u , ref4 = %u.\n", ref1, ref4);
2781     hr = IDirect3DRM3_CreateTexture(d3drm3, &initimg, &texture3);
2782     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMTexture3 interface (hr = %#x)\n", hr);
2783     ref2 = get_refcount((IUnknown *)d3drm1);
2784     ok(ref2 > ref1 + 2, "expected ref2 > (ref1 + 2), got ref1 = %u , ref2 = %u.\n", ref1, ref2);
2785     ref3 = get_refcount((IUnknown *)d3drm2);
2786     ok(ref3 == ref1, "expected ref3 == ref1, got ref1 = %u , ref3 = %u.\n", ref1, ref3);
2787     ref4 = get_refcount((IUnknown *)d3drm3);
2788     ok(ref4 == ref1, "expected ref4 == ref1, got ref1 = %u , ref4 = %u.\n", ref1, ref4);
2789 
2790     /* Created from image, GetSurface() does not work. */
2791     hr = IDirect3DRMTexture3_GetSurface(texture3, 0, NULL);
2792     ok(hr == D3DRMERR_BADVALUE, "GetSurface() expected to fail, %#x\n", hr);
2793 
2794     hr = IDirect3DRMTexture3_GetSurface(texture3, 0, &surface);
2795     ok(hr == D3DRMERR_NOTCREATEDFROMDDS, "GetSurface() expected to fail, %#x\n", hr);
2796 
2797     /* Test all failures together */
2798     test_class_name((IDirect3DRMObject *)texture1, "Texture");
2799     test_class_name((IDirect3DRMObject *)texture2, "Texture");
2800     test_class_name((IDirect3DRMObject *)texture3, "Texture");
2801     test_object_name((IDirect3DRMObject *)texture1);
2802     test_object_name((IDirect3DRMObject *)texture2);
2803     test_object_name((IDirect3DRMObject *)texture3);
2804 
2805     d3drm_img = IDirect3DRMTexture_GetImage(texture1);
2806     ok(!!d3drm_img, "Failed to get image.\n");
2807     ok(d3drm_img == &initimg, "Expected image returned == %p, got %p.\n", &initimg, d3drm_img);
2808 
2809     IDirect3DRMTexture_Release(texture1);
2810     ref2 = get_refcount((IUnknown *)d3drm1);
2811     ok(ref2 - 2 == ref1, "expected (ref2 - 2) == ref1, got ref1 = %u, ref2 = %u.\n", ref1, ref2);
2812     ref3 = get_refcount((IUnknown *)d3drm2);
2813     ok(ref3 == ref1, "expected ref3 == ref1, got ref1 = %u, ref3 = %u.\n", ref1, ref3);
2814     ref4 = get_refcount((IUnknown *)d3drm3);
2815     ok(ref4 == ref1, "expected ref4 == ref1, got ref1 = %u, ref4 = %u.\n", ref1, ref4);
2816 
2817     d3drm_img = NULL;
2818     d3drm_img = IDirect3DRMTexture2_GetImage(texture2);
2819     ok(!!d3drm_img, "Failed to get image.\n");
2820     ok(d3drm_img == &initimg, "Expected image returned == %p, got %p.\n", &initimg, d3drm_img);
2821 
2822     IDirect3DRMTexture2_Release(texture2);
2823     ref2 = get_refcount((IUnknown *)d3drm1);
2824     ok(ref2 - 1 == ref1, "expected (ref2 - 1) == ref1, got ref1 = %u, ref2 = %u.\n", ref1, ref2);
2825     ref3 = get_refcount((IUnknown *)d3drm2);
2826     ok(ref3 == ref1, "expected ref3 == ref1, got ref1 = %u, ref3 = %u.\n", ref1, ref3);
2827     ref4 = get_refcount((IUnknown *)d3drm3);
2828     ok(ref4 == ref1, "expected ref4 == ref1, got ref1 = %u, ref4 = %u.\n", ref1, ref4);
2829 
2830     d3drm_img = NULL;
2831     d3drm_img = IDirect3DRMTexture3_GetImage(texture3);
2832     ok(!!d3drm_img, "Failed to get image.\n");
2833     ok(d3drm_img == &initimg, "Expected image returned == %p, got %p.\n", &initimg, d3drm_img);
2834 
2835     IDirect3DRMTexture3_Release(texture3);
2836     ref2 = get_refcount((IUnknown *)d3drm1);
2837     ok(ref2 == ref1, "expected ref2 == ref1, got ref1 = %u, ref2 = %u.\n", ref1, ref2);
2838     ref3 = get_refcount((IUnknown *)d3drm2);
2839     ok(ref3 == ref1, "expected ref3 == ref1, got ref1 = %u, ref3 = %u.\n", ref1, ref3);
2840     ref4 = get_refcount((IUnknown *)d3drm3);
2841     ok(ref4 == ref1, "expected ref4 == ref1, got ref1 = %u, ref4 = %u.\n", ref1, ref4);
2842 
2843     /* InitFromImage tests */
2844     /* Tests for validation of D3DRMIMAGE struct */
2845     testimg.rgb = 1;
2846     testimg.palette = NULL;
2847     testimg.palette_size = 0;
2848     hr = IDirect3DRM2_CreateObject(d3drm2, &CLSID_CDirect3DRMTexture, NULL, &IID_IDirect3DRMTexture2,
2849             (void **)&texture2);
2850     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMTexture2 interface (hr = %#x).\n", hr);
2851     hr = IDirect3DRM3_CreateObject(d3drm3, &CLSID_CDirect3DRMTexture, NULL, &IID_IDirect3DRMTexture3,
2852             (void **)&texture3);
2853     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMTexture3 interface (hr = %#x).\n", hr);
2854     hr = IDirect3DRMTexture2_InitFromImage(texture2, &testimg);
2855     ok(SUCCEEDED(hr), "Cannot initialize IDirect3DRMTexture2 interface (hr = %#x)\n", hr);
2856     hr = IDirect3DRMTexture3_InitFromImage(texture3, &testimg);
2857     ok(SUCCEEDED(hr), "Cannot initialize IDirect3DRMTexture3 interface (hr = %#x)\n", hr);
2858     IDirect3DRMTexture2_Release(texture2);
2859     IDirect3DRMTexture3_Release(texture3);
2860 
2861     testimg.rgb = 0;
2862     testimg.palette = (void *)0xdeadbeef;
2863     testimg.palette_size = 0x39;
2864     hr = IDirect3DRM2_CreateObject(d3drm2, &CLSID_CDirect3DRMTexture, NULL, &IID_IDirect3DRMTexture2,
2865             (void **)&texture2);
2866     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMTexture2 interface (hr = %#x).\n", hr);
2867     hr = IDirect3DRM3_CreateObject(d3drm3, &CLSID_CDirect3DRMTexture, NULL, &IID_IDirect3DRMTexture3,
2868             (void **)&texture3);
2869     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMTexture3 interface (hr = %#x).\n", hr);
2870     hr = IDirect3DRMTexture2_InitFromImage(texture2, &testimg);
2871     ok(SUCCEEDED(hr), "Cannot initialize IDirect3DRMTexture2 interface (hr = %#x)\n", hr);
2872     hr = IDirect3DRMTexture3_InitFromImage(texture3, &testimg);
2873     ok(SUCCEEDED(hr), "Cannot initialize IDirect3DRMTexture3 interface (hr = %#x)\n", hr);
2874     IDirect3DRMTexture2_Release(texture2);
2875     IDirect3DRMTexture3_Release(texture3);
2876 
2877     hr = IDirect3DRM2_CreateObject(d3drm2, &CLSID_CDirect3DRMTexture, NULL, &IID_IDirect3DRMTexture2,
2878             (void **)&texture2);
2879     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMTexture2 interface (hr = %#x).\n", hr);
2880     ref2 = get_refcount((IUnknown *)texture2);
2881     hr = IDirect3DRMTexture2_InitFromImage(texture2, NULL);
2882     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
2883     ref3 = get_refcount((IUnknown *)texture2);
2884     ok(ref3 == ref2, "expected ref3 == ref2, got ref2 = %u , ref3 = %u.\n", ref2, ref3);
2885 
2886     hr = IDirect3DRM3_CreateObject(d3drm3, &CLSID_CDirect3DRMTexture, NULL, &IID_IDirect3DRMTexture3,
2887             (void **)&texture3);
2888     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMTexture3 interface (hr = %#x).\n", hr);
2889     ref2 = get_refcount((IUnknown *)texture3);
2890     hr = IDirect3DRMTexture3_InitFromImage(texture3, NULL);
2891     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
2892     ref3 = get_refcount((IUnknown *)texture3);
2893     ok(ref3 == ref2, "expected ref3 == ref2, got ref2 = %u , ref3 = %u.\n", ref2, ref3);
2894 
2895     initimg.rgb = 0;
2896     hr = IDirect3DRMTexture2_InitFromImage(texture2, &initimg);
2897     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
2898     hr = IDirect3DRMTexture3_InitFromImage(texture3, &initimg);
2899     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
2900     initimg.rgb = 1;
2901     initimg.red_mask = 0;
2902     hr = IDirect3DRMTexture2_InitFromImage(texture2, &initimg);
2903     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
2904     hr = IDirect3DRMTexture3_InitFromImage(texture3, &initimg);
2905     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
2906     initimg.red_mask = 0x000000ff;
2907     initimg.green_mask = 0;
2908     hr = IDirect3DRMTexture2_InitFromImage(texture2, &initimg);
2909     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
2910     hr = IDirect3DRMTexture3_InitFromImage(texture3, &initimg);
2911     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
2912     initimg.green_mask = 0x0000ff00;
2913     initimg.blue_mask = 0;
2914     hr = IDirect3DRMTexture2_InitFromImage(texture2, &initimg);
2915     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
2916     hr = IDirect3DRMTexture3_InitFromImage(texture3, &initimg);
2917     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
2918     initimg.blue_mask = 0x00ff0000;
2919     initimg.buffer1 = NULL;
2920     hr = IDirect3DRMTexture2_InitFromImage(texture2, &initimg);
2921     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
2922     hr = IDirect3DRMTexture3_InitFromImage(texture3, &initimg);
2923     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
2924     initimg.buffer1 = &pixel;
2925 
2926     d3drm_img = NULL;
2927     hr = IDirect3DRMTexture2_InitFromImage(texture2, &initimg);
2928     ok(SUCCEEDED(hr), "Cannot initialize IDirect3DRMTexture2 from image (hr = %#x).\n", hr);
2929     ref2 = get_refcount((IUnknown *)d3drm1);
2930     ok(ref2 > ref1, "expected ref2 > ref1, got ref1 = %u , ref2 = %u.\n", ref1, ref2);
2931     ref3 = get_refcount((IUnknown *)d3drm2);
2932     ok(ref3 == ref1, "expected ref3 == ref1, got ref1 = %u , ref3 = %u.\n", ref1, ref3);
2933     ref4 = get_refcount((IUnknown *)d3drm3);
2934     ok(ref4 == ref1, "expected ref4 == ref1, got ref1 = %u , ref4 = %u.\n", ref1, ref4);
2935 
2936     hr = IDirect3DRMTexture2_InitFromImage(texture2, &initimg);
2937     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
2938     /* Release leaked reference to d3drm1 */
2939     IDirect3DRM_Release(d3drm1);
2940 
2941     d3drm_img = IDirect3DRMTexture2_GetImage(texture2);
2942     ok(!!d3drm_img, "Failed to get image.\n");
2943     ok(d3drm_img == &initimg, "Expected image returned == %p, got %p.\n", &initimg, d3drm_img);
2944     IDirect3DRMTexture2_Release(texture2);
2945     ref2 = get_refcount((IUnknown *)d3drm1);
2946     ok(ref2 == ref1, "expected ref2 == ref1, got ref1 = %u, ref2 = %u.\n", ref1, ref2);
2947     ref3 = get_refcount((IUnknown *)d3drm2);
2948     ok(ref3 == ref1, "expected ref3 == ref1, got ref1 = %u, ref3 = %u.\n", ref1, ref3);
2949     ref4 = get_refcount((IUnknown *)d3drm3);
2950     ok(ref4 == ref1, "expected ref4 == ref1, got ref1 = %u, ref4 = %u.\n", ref1, ref4);
2951 
2952     d3drm_img = NULL;
2953     hr = IDirect3DRMTexture3_InitFromImage(texture3, &initimg);
2954     ok(SUCCEEDED(hr), "Cannot initialize IDirect3DRMTexture3 from image (hr = %#x).\n", hr);
2955     ref2 = get_refcount((IUnknown *)d3drm1);
2956     ok(ref2 > ref1, "expected ref2 > ref1, got ref1 = %u , ref2 = %u.\n", ref1, ref2);
2957     ref3 = get_refcount((IUnknown *)d3drm2);
2958     ok(ref3 == ref1, "expected ref3 == ref1, got ref1 = %u , ref3 = %u.\n", ref1, ref3);
2959     ref4 = get_refcount((IUnknown *)d3drm3);
2960     ok(ref4 == ref1, "expected ref4 == ref1, got ref1 = %u , ref4 = %u.\n", ref1, ref4);
2961 
2962     hr = IDirect3DRMTexture3_InitFromImage(texture3, &initimg);
2963     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
2964     IDirect3DRM_Release(d3drm1);
2965 
2966     d3drm_img = IDirect3DRMTexture3_GetImage(texture3);
2967     ok(!!d3drm_img, "Failed to get image.\n");
2968     ok(d3drm_img == &initimg, "Expected image returned == %p, got %p.\n", &initimg, d3drm_img);
2969     IDirect3DRMTexture3_Release(texture3);
2970     ref2 = get_refcount((IUnknown *)d3drm1);
2971     ok(ref2 == ref1, "expected ref2 == ref1, got ref1 = %u, ref2 = %u.\n", ref1, ref2);
2972     ref3 = get_refcount((IUnknown *)d3drm2);
2973     ok(ref3 == ref1, "expected ref3 == ref1, got ref1 = %u, ref3 = %u.\n", ref1, ref3);
2974     ref4 = get_refcount((IUnknown *)d3drm3);
2975     ok(ref4 == ref1, "expected ref4 == ref1, got ref1 = %u, ref4 = %u.\n", ref1, ref4);
2976 
2977     IDirect3DRM3_Release(d3drm3);
2978     IDirect3DRM2_Release(d3drm2);
2979     IDirect3DRM_Release(d3drm1);
2980 }
2981 
test_Device(void)2982 static void test_Device(void)
2983 {
2984     IDirectDrawClipper *pClipper;
2985     HRESULT hr;
2986     IDirect3DRM *d3drm;
2987     IDirect3DRMDevice *device;
2988     IDirect3DRMWinDevice *win_device;
2989     GUID driver;
2990     HWND window;
2991     RECT rc;
2992 
2993     window = create_window();
2994     GetClientRect(window, &rc);
2995 
2996     hr = Direct3DRMCreate(&d3drm);
2997     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x)\n", hr);
2998 
2999     hr = DirectDrawCreateClipper(0, &pClipper, NULL);
3000     ok(hr == DD_OK, "Cannot get IDirectDrawClipper interface (hr = %x)\n", hr);
3001 
3002     hr = IDirectDrawClipper_SetHWnd(pClipper, 0, window);
3003     ok(hr == DD_OK, "Cannot set HWnd to Clipper (hr = %x)\n", hr);
3004 
3005     memcpy(&driver, &IID_IDirect3DRGBDevice, sizeof(GUID));
3006     hr = IDirect3DRM3_CreateDeviceFromClipper(d3drm, pClipper, &driver, rc.right, rc.bottom, &device);
3007     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMDevice interface (hr = %x)\n", hr);
3008 
3009     test_class_name((IDirect3DRMObject *)device, "Device");
3010     test_object_name((IDirect3DRMObject *)device);
3011 
3012     /* WinDevice */
3013     if (FAILED(hr = IDirect3DRMDevice_QueryInterface(device, &IID_IDirect3DRMWinDevice, (void **)&win_device)))
3014     {
3015         win_skip("Cannot get IDirect3DRMWinDevice interface (hr = %x), skipping tests\n", hr);
3016         goto cleanup;
3017     }
3018 
3019     test_class_name((IDirect3DRMObject *)win_device, "Device");
3020     test_object_name((IDirect3DRMObject *)win_device);
3021     IDirect3DRMWinDevice_Release(win_device);
3022 
3023 cleanup:
3024     IDirect3DRMDevice_Release(device);
3025     IDirectDrawClipper_Release(pClipper);
3026 
3027     IDirect3DRM_Release(d3drm);
3028     DestroyWindow(window);
3029 }
3030 
test_frame_transform(void)3031 static void test_frame_transform(void)
3032 {
3033     IDirect3DRMFrame *frame, *subframe;
3034     D3DRMMATRIX4D matrix, add_matrix;
3035     IDirect3DRM *d3drm;
3036     D3DVECTOR v1, v2;
3037     HRESULT hr;
3038 
3039     hr = Direct3DRMCreate(&d3drm);
3040     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3041 
3042     hr = IDirect3DRM_CreateFrame(d3drm, NULL, &frame);
3043     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3044 
3045     hr = IDirect3DRMFrame_GetTransform(frame, matrix);
3046     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3047     expect_matrix(matrix,
3048             1.0f, 0.0f, 0.0f, 0.0f,
3049             0.0f, 1.0f, 0.0f, 0.0f,
3050             0.0f, 0.0f, 1.0f, 0.0f,
3051             0.0f, 0.0f, 0.0f, 1.0f, 0);
3052 
3053     memcpy(add_matrix, identity, sizeof(add_matrix));
3054     add_matrix[3][0] = 3.0f;
3055     add_matrix[3][1] = 3.0f;
3056     add_matrix[3][2] = 3.0f;
3057 
3058     frame_set_transform(frame,
3059             2.0f, 0.0f, 0.0f, 0.0f,
3060             0.0f, 2.0f, 0.0f, 0.0f,
3061             0.0f, 0.0f, 2.0f, 0.0f,
3062             0.0f, 0.0f, 0.0f, 1.0f);
3063     hr = IDirect3DRMFrame_AddTransform(frame, D3DRMCOMBINE_REPLACE, add_matrix);
3064     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3065     hr = IDirect3DRMFrame_GetTransform(frame, matrix);
3066     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3067     expect_matrix(matrix,
3068             1.0f, 0.0f, 0.0f, 0.0f,
3069             0.0f, 1.0f, 0.0f, 0.0f,
3070             0.0f, 0.0f, 1.0f, 0.0f,
3071             3.0f, 3.0f, 3.0f, 1.0f, 1);
3072 
3073     frame_set_transform(frame,
3074             2.0f, 0.0f, 0.0f, 0.0f,
3075             0.0f, 2.0f, 0.0f, 0.0f,
3076             0.0f, 0.0f, 2.0f, 0.0f,
3077             0.0f, 0.0f, 0.0f, 1.0f);
3078     hr = IDirect3DRMFrame_AddTransform(frame, D3DRMCOMBINE_BEFORE, add_matrix);
3079     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3080     hr = IDirect3DRMFrame_GetTransform(frame, matrix);
3081     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3082     expect_matrix(matrix,
3083             2.0f, 0.0f, 0.0f, 0.0f,
3084             0.0f, 2.0f, 0.0f, 0.0f,
3085             0.0f, 0.0f, 2.0f, 0.0f,
3086             6.0f, 6.0f, 6.0f, 1.0f, 1);
3087 
3088     frame_set_transform(frame,
3089             2.0f, 0.0f, 0.0f, 0.0f,
3090             0.0f, 2.0f, 0.0f, 0.0f,
3091             0.0f, 0.0f, 2.0f, 0.0f,
3092             0.0f, 0.0f, 0.0f, 1.0f);
3093     hr = IDirect3DRMFrame_AddTransform(frame, D3DRMCOMBINE_AFTER, add_matrix);
3094     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3095     hr = IDirect3DRMFrame_GetTransform(frame, matrix);
3096     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3097     expect_matrix(matrix,
3098             2.0f, 0.0f, 0.0f, 0.0f,
3099             0.0f, 2.0f, 0.0f, 0.0f,
3100             0.0f, 0.0f, 2.0f, 0.0f,
3101             3.0f, 3.0f, 3.0f, 1.0f, 1);
3102 
3103     add_matrix[3][3] = 2.0f;
3104     hr = IDirect3DRMFrame_AddTransform(frame, D3DRMCOMBINE_REPLACE, add_matrix);
3105     ok(hr == D3DRMERR_BADVALUE, "Got unexpected hr %#x.\n", hr);
3106 
3107     frame_set_transform(frame,
3108             2.0f, 0.0f, 0.0f, 0.0f,
3109             0.0f, 2.0f, 0.0f, 0.0f,
3110             0.0f, 0.0f, 2.0f, 0.0f,
3111             0.0f, 0.0f, 0.0f, 1.0f);
3112     hr = IDirect3DRMFrame_AddTranslation(frame, D3DRMCOMBINE_REPLACE, 3.0f, 3.0f, 3.0f);
3113     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3114     hr = IDirect3DRMFrame_GetTransform(frame, matrix);
3115     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3116     expect_matrix(matrix,
3117             1.0f, 0.0f, 0.0f, 0.0f,
3118             0.0f, 1.0f, 0.0f, 0.0f,
3119             0.0f, 0.0f, 1.0f, 0.0f,
3120             3.0f, 3.0f, 3.0f, 1.0f, 1);
3121 
3122     frame_set_transform(frame,
3123             2.0f, 0.0f, 0.0f, 0.0f,
3124             0.0f, 2.0f, 0.0f, 0.0f,
3125             0.0f, 0.0f, 2.0f, 0.0f,
3126             0.0f, 0.0f, 0.0f, 1.0f);
3127     hr = IDirect3DRMFrame_AddTranslation(frame, D3DRMCOMBINE_BEFORE, 3.0f, 3.0f, 3.0f);
3128     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3129     hr = IDirect3DRMFrame_GetTransform(frame, matrix);
3130     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3131     expect_matrix(matrix,
3132             2.0f, 0.0f, 0.0f, 0.0f,
3133             0.0f, 2.0f, 0.0f, 0.0f,
3134             0.0f, 0.0f, 2.0f, 0.0f,
3135             6.0f, 6.0f, 6.0f, 1.0f, 1);
3136 
3137     frame_set_transform(frame,
3138             2.0f, 0.0f, 0.0f, 0.0f,
3139             0.0f, 2.0f, 0.0f, 0.0f,
3140             0.0f, 0.0f, 2.0f, 0.0f,
3141             0.0f, 0.0f, 0.0f, 1.0f);
3142     hr = IDirect3DRMFrame_AddTranslation(frame, D3DRMCOMBINE_AFTER, 3.0f, 3.0f, 3.0f);
3143     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3144     hr = IDirect3DRMFrame_GetTransform(frame, matrix);
3145     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3146     expect_matrix(matrix,
3147             2.0f, 0.0f, 0.0f, 0.0f,
3148             0.0f, 2.0f, 0.0f, 0.0f,
3149             0.0f, 0.0f, 2.0f, 0.0f,
3150             3.0f, 3.0f, 3.0f, 1.0f, 1);
3151 
3152     frame_set_transform(frame,
3153             1.0f, 0.0f, 0.0f, 0.0f,
3154             0.0f, 1.0f, 0.0f, 0.0f,
3155             0.0f, 0.0f, 1.0f, 0.0f,
3156             3.0f, 3.0f, 3.0f, 1.0f);
3157     hr = IDirect3DRMFrame_AddScale(frame, D3DRMCOMBINE_REPLACE, 2.0f, 2.0f, 2.0f);
3158     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3159     hr = IDirect3DRMFrame_GetTransform(frame, matrix);
3160     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3161     expect_matrix(matrix,
3162             2.0f, 0.0f, 0.0f, 0.0f,
3163             0.0f, 2.0f, 0.0f, 0.0f,
3164             0.0f, 0.0f, 2.0f, 0.0f,
3165             0.0f, 0.0f, 0.0f, 1.0f, 1);
3166 
3167     frame_set_transform(frame,
3168             1.0f, 0.0f, 0.0f, 0.0f,
3169             0.0f, 1.0f, 0.0f, 0.0f,
3170             0.0f, 0.0f, 1.0f, 0.0f,
3171             3.0f, 3.0f, 3.0f, 1.0f);
3172     hr = IDirect3DRMFrame_AddScale(frame, D3DRMCOMBINE_BEFORE, 2.0f, 2.0f, 2.0f);
3173     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3174     hr = IDirect3DRMFrame_GetTransform(frame, matrix);
3175     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3176     expect_matrix(matrix,
3177             2.0f, 0.0f, 0.0f, 0.0f,
3178             0.0f, 2.0f, 0.0f, 0.0f,
3179             0.0f, 0.0f, 2.0f, 0.0f,
3180             3.0f, 3.0f, 3.0f, 1.0f, 1);
3181 
3182     frame_set_transform(frame,
3183             1.0f, 0.0f, 0.0f, 0.0f,
3184             0.0f, 1.0f, 0.0f, 0.0f,
3185             0.0f, 0.0f, 1.0f, 0.0f,
3186             3.0f, 3.0f, 3.0f, 1.0f);
3187     hr = IDirect3DRMFrame_AddScale(frame, D3DRMCOMBINE_AFTER, 2.0f, 2.0f, 2.0f);
3188     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3189     hr = IDirect3DRMFrame_GetTransform(frame, matrix);
3190     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3191     expect_matrix(matrix,
3192             2.0f, 0.0f, 0.0f, 0.0f,
3193             0.0f, 2.0f, 0.0f, 0.0f,
3194             0.0f, 0.0f, 2.0f, 0.0f,
3195             6.0f, 6.0f, 6.0f, 1.0f, 1);
3196 
3197     frame_set_transform(frame,
3198             1.0f, 0.0f, 0.0f, 0.0f,
3199             0.0f, 1.0f, 0.0f, 0.0f,
3200             0.0f, 0.0f, 1.0f, 0.0f,
3201             3.0f, 3.0f, 3.0f, 1.0f);
3202     hr = IDirect3DRMFrame_AddRotation(frame, D3DRMCOMBINE_REPLACE, 1.0f, 0.0f, 0.0f, M_PI_2);
3203     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3204     hr = IDirect3DRMFrame_GetTransform(frame, matrix);
3205     matrix_sanitise(matrix);
3206     expect_matrix(matrix,
3207             1.0f,  0.0f, 0.0f, 0.0f,
3208             0.0f,  0.0f, 1.0f, 0.0f,
3209             0.0f, -1.0f, 0.0f, 0.0f,
3210             0.0f,  0.0f, 0.0f, 1.0f, 1);
3211 
3212     frame_set_transform(frame,
3213             1.0f, 0.0f, 0.0f, 0.0f,
3214             0.0f, 1.0f, 0.0f, 0.0f,
3215             0.0f, 0.0f, 1.0f, 0.0f,
3216             3.0f, 3.0f, 3.0f, 1.0f);
3217     hr = IDirect3DRMFrame_AddRotation(frame, D3DRMCOMBINE_BEFORE, 1.0f, 0.0f, 0.0f, M_PI_2);
3218     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3219     hr = IDirect3DRMFrame_GetTransform(frame, matrix);
3220     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3221     matrix_sanitise(matrix);
3222     expect_matrix(matrix,
3223             1.0f,  0.0f, 0.0f, 0.0f,
3224             0.0f,  0.0f, 1.0f, 0.0f,
3225             0.0f, -1.0f, 0.0f, 0.0f,
3226             3.0f,  3.0f, 3.0f, 1.0f, 1);
3227 
3228     frame_set_transform(frame,
3229             1.0f, 0.0f, 0.0f, 0.0f,
3230             0.0f, 1.0f, 0.0f, 0.0f,
3231             0.0f, 0.0f, 1.0f, 0.0f,
3232             3.0f, 3.0f, 3.0f, 1.0f);
3233     hr = IDirect3DRMFrame_AddRotation(frame, D3DRMCOMBINE_AFTER, 1.0f, 0.0f, 0.0f, M_PI_2);
3234     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3235     hr = IDirect3DRMFrame_GetTransform(frame, matrix);
3236     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3237     matrix_sanitise(matrix);
3238     expect_matrix(matrix,
3239             1.0f,  0.0f, 0.0f, 0.0f,
3240             0.0f,  0.0f, 1.0f, 0.0f,
3241             0.0f, -1.0f, 0.0f, 0.0f,
3242             3.0f, -3.0f, 3.0f, 1.0f, 1);
3243 
3244     hr = IDirect3DRMFrame_AddRotation(frame, D3DRMCOMBINE_REPLACE, 0.0f, 0.0f, 1.0f, M_PI_2);
3245     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3246     hr = IDirect3DRMFrame_GetTransform(frame, matrix);
3247     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3248     matrix_sanitise(matrix);
3249     expect_matrix(matrix,
3250              0.0f, 1.0f, 0.0f, 0.0f,
3251             -1.0f, 0.0f, 0.0f, 0.0f,
3252              0.0f, 0.0f, 1.0f, 0.0f,
3253              0.0f, 0.0f, 0.0f, 1.0f, 1);
3254 
3255     hr = IDirect3DRMFrame_AddRotation(frame, D3DRMCOMBINE_REPLACE, 0.0f, 0.0f, 0.0f, M_PI_2);
3256     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3257     hr = IDirect3DRMFrame_GetTransform(frame, matrix);
3258     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3259     matrix_sanitise(matrix);
3260     expect_matrix(matrix,
3261             1.0f,  0.0f, 0.0f, 0.0f,
3262             0.0f,  0.0f, 1.0f, 0.0f,
3263             0.0f, -1.0f, 0.0f, 0.0f,
3264             0.0f,  0.0f, 0.0f, 1.0f, 1);
3265 
3266     frame_set_transform(frame,
3267              2.0f,  0.0f,  0.0f, 0.0f,
3268              0.0f,  4.0f,  0.0f, 0.0f,
3269              0.0f,  0.0f,  8.0f, 0.0f,
3270             64.0f, 64.0f, 64.0f, 1.0f);
3271     hr = IDirect3DRM_CreateFrame(d3drm, frame, &subframe);
3272     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3273     frame_set_transform(subframe,
3274              1.0f,  0.0f,  0.0f, 0.0f,
3275              0.0f,  1.0f,  0.0f, 0.0f,
3276              0.0f,  0.0f,  1.0f, 0.0f,
3277             11.0f, 11.0f, 11.0f, 1.0f);
3278     set_vector(&v1, 3.0f, 5.0f, 7.0f);
3279 
3280     hr = IDirect3DRMFrame_Transform(frame, &v2, &v1);
3281     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3282     expect_vector(&v2, 70.0f, 84.0f, 120.0f, 1);
3283 
3284     hr = IDirect3DRMFrame_Transform(subframe, &v2, &v1);
3285     ok(hr == D3DRM_OK, "Got unexpected hr %#x.\n", hr);
3286     expect_vector(&v2, 92.0f, 128.0f, 208.0f, 1);
3287 
3288     IDirect3DRMFrame_Release(subframe);
3289     IDirect3DRMFrame_Release(frame);
3290     IDirect3DRM_Release(d3drm);
3291 }
3292 
3293 static int nb_objects = 0;
3294 static const GUID* refiids[] =
3295 {
3296     &IID_IDirect3DRMMeshBuilder,
3297     &IID_IDirect3DRMMeshBuilder,
3298     &IID_IDirect3DRMFrame,
3299     &IID_IDirect3DRMMaterial /* Not taken into account and not notified */
3300 };
3301 
object_load_callback(IDirect3DRMObject * object,REFIID objectguid,void * arg)3302 static void __cdecl object_load_callback(IDirect3DRMObject *object, REFIID objectguid, void *arg)
3303 {
3304     ok(object != NULL, "Arg 1 should not be null\n");
3305     ok(IsEqualGUID(objectguid, refiids[nb_objects]), "Arg 2 is incorrect\n");
3306     ok(arg == (void *)0xdeadbeef, "Arg 3 should be 0xdeadbeef (got %p)\n", arg);
3307     nb_objects++;
3308 }
3309 
test_d3drm_load(void)3310 static void test_d3drm_load(void)
3311 {
3312     HRESULT hr;
3313     IDirect3DRM *d3drm;
3314     D3DRMLOADMEMORY info;
3315     const GUID* req_refiids[] = { &IID_IDirect3DRMMeshBuilder, &IID_IDirect3DRMFrame, &IID_IDirect3DRMMaterial };
3316 
3317     hr = Direct3DRMCreate(&d3drm);
3318     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x)\n", hr);
3319 
3320     info.lpMemory = data_d3drm_load;
3321     info.dSize = strlen(data_d3drm_load);
3322     hr = IDirect3DRM_Load(d3drm, &info, NULL, (GUID **)req_refiids, 3, D3DRMLOAD_FROMMEMORY,
3323             object_load_callback, (void *)0xdeadbeef, NULL, NULL, NULL);
3324     ok(hr == D3DRM_OK, "Cannot load data (hr = %x)\n", hr);
3325     ok(nb_objects == 3, "Should have loaded 3 objects (got %d)\n", nb_objects);
3326 
3327     IDirect3DRM_Release(d3drm);
3328 }
3329 
3330 IDirect3DRMMeshBuilder *mesh_builder = NULL;
3331 
object_load_callback_frame(IDirect3DRMObject * object,REFIID object_guid,void * arg)3332 static void __cdecl object_load_callback_frame(IDirect3DRMObject *object, REFIID object_guid, void *arg)
3333 {
3334     HRESULT hr;
3335     IDirect3DRMFrame *frame;
3336     IDirect3DRMVisualArray *array;
3337     IDirect3DRMVisual *visual;
3338     ULONG size;
3339     char name[128];
3340 
3341     hr = IDirect3DRMObject_QueryInterface(object, &IID_IDirect3DRMFrame, (void**)&frame);
3342     ok(hr == D3DRM_OK, "IDirect3DRMObject_QueryInterface returned %x\n", hr);
3343 
3344     hr = IDirect3DRMFrame_GetVisuals(frame, &array);
3345     ok(hr == D3DRM_OK, "IDirect3DRMFrame_GetVisuals returned %x\n", hr);
3346 
3347     size = IDirect3DRMVisualArray_GetSize(array);
3348     ok(size == 1, "Wrong size %u returned, expected 1\n", size);
3349 
3350     hr = IDirect3DRMVisualArray_GetElement(array, 0, &visual);
3351     ok(hr == D3DRM_OK, "IDirect3DRMVisualArray_GetElement returned %x\n", hr);
3352 
3353     hr = IDirect3DRMVisual_QueryInterface(visual, &IID_IDirect3DRMMeshBuilder, (void**)&mesh_builder);
3354     ok(hr == D3DRM_OK, "IDirect3DRMVisualArray_GetSize returned %x\n", hr);
3355 
3356     size = sizeof(name);
3357     hr = IDirect3DRMMeshBuilder_GetName(mesh_builder, &size, name);
3358     ok(hr == D3DRM_OK, "IDirect3DRMMeshBuilder_GetName returned %x\n", hr);
3359     ok(!strcmp(name, "mesh1"), "Wrong name %s, expected mesh1\n", name);
3360 
3361     IDirect3DRMVisual_Release(visual);
3362     IDirect3DRMVisualArray_Release(array);
3363     IDirect3DRMFrame_Release(frame);
3364 }
3365 
3366 struct {
3367     int vertex_count;
3368     int face_count;
3369     int vertex_per_face;
3370     int face_data_size;
3371     DWORD color;
3372     float power;
3373     float specular[3];
3374     float emissive[3];
3375 } groups[3] = {
3376     { 4, 3, 3, 9, 0x4c0000ff, 30.0f, { 0.31f, 0.32f, 0.33f }, { 0.34f, 0.35f, 0.36f } },
3377     { 4, 2, 3, 6, 0x3300ff00, 20.0f, { 0.21f, 0.22f, 0.23f }, { 0.24f, 0.25f, 0.26f } },
3378     { 3, 1, 3, 3, 0x19ff0000, 10.0f, { 0.11f, 0.12f, 0.13f }, { 0.14f, 0.15f, 0.16f } }
3379 };
3380 
test_frame_mesh_materials(void)3381 static void test_frame_mesh_materials(void)
3382 {
3383     HRESULT hr;
3384     IDirect3DRM *d3drm;
3385     D3DRMLOADMEMORY info;
3386     const GUID *req_refiids[] = { &IID_IDirect3DRMFrame };
3387     IDirect3DRMMesh *mesh;
3388     ULONG size;
3389     IDirect3DRMMaterial *material;
3390     IDirect3DRMTexture *texture;
3391     int i;
3392 
3393     hr = Direct3DRMCreate(&d3drm);
3394     ok(hr == D3DRM_OK, "Direct3DRMCreate returned %x\n", hr);
3395 
3396     info.lpMemory = data_frame_mesh_materials;
3397     info.dSize = strlen(data_frame_mesh_materials);
3398     hr = IDirect3DRM_Load(d3drm, &info, NULL, (GUID**)req_refiids, 1, D3DRMLOAD_FROMMEMORY, object_load_callback_frame, (void*)0xdeadbeef, NULL, NULL, NULL);
3399     ok(hr == D3DRM_OK, "Cannot load data (hr = %x)\n", hr);
3400 
3401     hr = IDirect3DRMMeshBuilder_CreateMesh(mesh_builder, &mesh);
3402     ok(hr == D3DRM_OK, "IDirect3DRMMeshBuilder_CreateMesh returned %x\n", hr);
3403 
3404     size = IDirect3DRMMesh_GetGroupCount(mesh);
3405     ok(size == 3, "Wrong size %u returned, expected 3\n", size);
3406 
3407     for (i = 0; i < size; i++)
3408     {
3409         D3DVALUE red, green, blue, power;
3410         D3DCOLOR color;
3411         unsigned vertex_count, face_count, vertex_per_face;
3412         DWORD face_data_size;
3413 
3414         hr = IDirect3DRMMesh_GetGroup(mesh, i, &vertex_count, &face_count, &vertex_per_face, &face_data_size, NULL);
3415         ok(hr == D3DRM_OK, "Group %d: IDirect3DRMMesh_GetGroup returned %x\n", i, hr);
3416         ok(vertex_count == groups[i].vertex_count, "Group %d: Wrong vertex count %d, expected %d\n", i, vertex_count, groups[i].vertex_count);
3417         ok(face_count == groups[i].face_count, "Group %d: Wrong face count %d; expected %d\n", i, face_count, groups[i].face_count);
3418         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);
3419         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);
3420 
3421         color = IDirect3DRMMesh_GetGroupColor(mesh, i);
3422         ok(color == groups[i].color, "Group %d: Wrong color %x, expected %x\n", i, color, groups[i].color);
3423 
3424         hr = IDirect3DRMMesh_GetGroupMaterial(mesh, i, &material);
3425         ok(hr == D3DRM_OK, "Group %d: IDirect3DRMMesh_GetGroupMaterial returned %x\n", i, hr);
3426         ok(material != NULL, "Group %d: No material\n", i);
3427         power = IDirect3DRMMaterial_GetPower(material);
3428         ok(power == groups[i].power, "Group %d: Wrong power %f, expected %f\n", i, power,  groups[i].power);
3429         hr = IDirect3DRMMaterial_GetSpecular(material, &red, &green, &blue);
3430         ok(hr == D3DRM_OK, "Group %d: IDirect3DRMMaterial_GetSpecular returned %x\n", i, hr);
3431         ok(red == groups[i].specular[0], "Group %d: Wrong specular red %f, expected %f\n", i, red, groups[i].specular[0]);
3432         ok(green == groups[i].specular[1], "Group %d: Wrong specular green %f, pD3DRMexpected %f\n", i, green, groups[i].specular[1]);
3433         ok(blue == groups[i].specular[2], "Group %d: Wrong specular blue %f, expected %f\n", i, blue, groups[i].specular[2]);
3434         hr = IDirect3DRMMaterial_GetEmissive(material, &red, &green, &blue);
3435         ok(hr == D3DRM_OK, "Group %d: IDirect3DRMMaterial_GetEmissive returned %x\n", i, hr);
3436         ok(red == groups[i].emissive[0], "Group %d: Wrong emissive red %f, expected %f\n", i, red, groups[i].emissive[0]);
3437         ok(green == groups[i].emissive[1], "Group %d: Wrong emissive green %f, expected %f\n", i, green, groups[i].emissive[1]);
3438         ok(blue == groups[i].emissive[2], "Group %d: Wrong emissive blue %f, expected %f\n", i, blue, groups[i].emissive[2]);
3439 
3440         hr = IDirect3DRMMesh_GetGroupTexture(mesh, i, &texture);
3441         ok(hr == D3DRM_OK, "Group %d: IDirect3DRMMesh_GetGroupTexture returned %x\n", i, hr);
3442         ok(!texture, "Group %d: Unexpected texture\n", i);
3443 
3444         if (material)
3445             IDirect3DRMMaterial_Release(material);
3446         if (texture)
3447             IDirect3DRMTexture_Release(texture);
3448     }
3449 
3450     IDirect3DRMMesh_Release(mesh);
3451     IDirect3DRMMeshBuilder_Release(mesh_builder);
3452     IDirect3DRM_Release(d3drm);
3453 }
3454 
3455 struct qi_test
3456 {
3457     REFIID iid;
3458     REFIID refcount_iid;
3459     REFIID vtable_iid;
3460     HRESULT hr;
3461 };
3462 
test_qi(const char * test_name,IUnknown * base_iface,REFIID refcount_iid,const struct qi_test * tests,UINT entry_count)3463 static void test_qi(const char *test_name, IUnknown *base_iface,
3464                     REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
3465 {
3466     ULONG refcount, expected_refcount;
3467     IUnknown *iface1, *iface2;
3468     HRESULT hr;
3469     UINT i, j;
3470 
3471     for (i = 0; i < entry_count; ++i)
3472     {
3473         hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
3474         ok(hr == tests[i].hr, "Got hr %#x for test \"%s\" %u.\n", hr, test_name, i);
3475         if (SUCCEEDED(hr))
3476         {
3477             for (j = 0; j < entry_count; ++j)
3478             {
3479                 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
3480                 ok(hr == tests[j].hr, "Got hr %#x for test \"%s\" %u, %u.\n", hr, test_name, i, j);
3481                 if (SUCCEEDED(hr))
3482                 {
3483                     expected_refcount = 0;
3484                     if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
3485                         ++expected_refcount;
3486                     if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
3487                         ++expected_refcount;
3488                     refcount = IUnknown_Release(iface2);
3489                     ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, %u, expected %u.\n",
3490                                 refcount, test_name, i, j, expected_refcount);
3491                     if (tests[i].vtable_iid && tests[j].vtable_iid && IsEqualGUID(tests[i].vtable_iid, tests[j].vtable_iid))
3492                         ok(iface1 == iface2,
3493                                 "Expected iface1 == iface2 for test \"%s\" %u, %u. Got iface1 = %p, iface 2 = %p.\n",
3494                                 test_name, i, j, iface1, iface2);
3495                     else if (tests[i].vtable_iid && tests[j].vtable_iid)
3496                         ok(iface1 != iface2,
3497                                 "Expected iface1 != iface2 for test \"%s\" %u, %u. Got iface1 == iface2 == %p.\n",
3498                                 test_name, i, j, iface1);
3499                 }
3500             }
3501 
3502             expected_refcount = 0;
3503             if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
3504                 ++expected_refcount;
3505             refcount = IUnknown_Release(iface1);
3506             ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, expected %u.\n",
3507                         refcount, test_name, i, expected_refcount);
3508         }
3509     }
3510 }
3511 
test_d3drm_qi(void)3512 static void test_d3drm_qi(void)
3513 {
3514     static const struct qi_test tests[] =
3515     {
3516         { &IID_IDirect3DRM3,               &IID_IDirect3DRM3, &IID_IDirect3DRM3, S_OK                      },
3517         { &IID_IDirect3DRM2,               &IID_IDirect3DRM2, &IID_IDirect3DRM2, S_OK                      },
3518         { &IID_IDirect3DRM,                &IID_IDirect3DRM,  &IID_IDirect3DRM,  S_OK                      },
3519         { &IID_IDirect3DRMDevice,          NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3520         { &IID_IDirect3DRMObject,          NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3521         { &IID_IDirect3DRMObject2,         NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3522         { &IID_IDirect3DRMDevice2,         NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3523         { &IID_IDirect3DRMDevice3,         NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3524         { &IID_IDirect3DRMViewport,        NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3525         { &IID_IDirect3DRMViewport2,       NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3526         { &IID_IDirect3DRMFrame,           NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3527         { &IID_IDirect3DRMFrame2,          NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3528         { &IID_IDirect3DRMFrame3,          NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3529         { &IID_IDirect3DRMVisual,          NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3530         { &IID_IDirect3DRMMesh,            NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3531         { &IID_IDirect3DRMMeshBuilder,     NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3532         { &IID_IDirect3DRMMeshBuilder2,    NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3533         { &IID_IDirect3DRMMeshBuilder3,    NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3534         { &IID_IDirect3DRMFace,            NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3535         { &IID_IDirect3DRMFace2,           NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3536         { &IID_IDirect3DRMLight,           NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3537         { &IID_IDirect3DRMTexture,         NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3538         { &IID_IDirect3DRMTexture2,        NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3539         { &IID_IDirect3DRMTexture3,        NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3540         { &IID_IDirect3DRMWrap,            NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3541         { &IID_IDirect3DRMMaterial,        NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3542         { &IID_IDirect3DRMMaterial2,       NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3543         { &IID_IDirect3DRMAnimation,       NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3544         { &IID_IDirect3DRMAnimation2,      NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3545         { &IID_IDirect3DRMAnimationSet,    NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3546         { &IID_IDirect3DRMAnimationSet2,   NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3547         { &IID_IDirect3DRMObjectArray,     NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3548         { &IID_IDirect3DRMDeviceArray,     NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3549         { &IID_IDirect3DRMViewportArray,   NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3550         { &IID_IDirect3DRMFrameArray,      NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3551         { &IID_IDirect3DRMVisualArray,     NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3552         { &IID_IDirect3DRMLightArray,      NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3553         { &IID_IDirect3DRMPickedArray,     NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3554         { &IID_IDirect3DRMFaceArray,       NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3555         { &IID_IDirect3DRMAnimationArray,  NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3556         { &IID_IDirect3DRMUserVisual,      NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3557         { &IID_IDirect3DRMShadow,          NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3558         { &IID_IDirect3DRMShadow2,         NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3559         { &IID_IDirect3DRMInterpolator,    NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3560         { &IID_IDirect3DRMProgressiveMesh, NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3561         { &IID_IDirect3DRMPicked2Array,    NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3562         { &IID_IDirect3DRMClippedVisual,   NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3563         { &IID_IDirectDrawClipper,         NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3564         { &IID_IDirectDrawSurface7,        NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3565         { &IID_IDirectDrawSurface4,        NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3566         { &IID_IDirectDrawSurface3,        NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3567         { &IID_IDirectDrawSurface2,        NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3568         { &IID_IDirectDrawSurface,         NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3569         { &IID_IDirect3DDevice7,           NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3570         { &IID_IDirect3DDevice3,           NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3571         { &IID_IDirect3DDevice2,           NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3572         { &IID_IDirect3DDevice,            NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3573         { &IID_IDirect3D7,                 NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3574         { &IID_IDirect3D3,                 NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3575         { &IID_IDirect3D2,                 NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3576         { &IID_IDirect3D,                  NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3577         { &IID_IDirectDraw7,               NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3578         { &IID_IDirectDraw4,               NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3579         { &IID_IDirectDraw3,               NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3580         { &IID_IDirectDraw2,               NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3581         { &IID_IDirectDraw,                NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3582         { &IID_IDirect3DLight,             NULL,              NULL,              CLASS_E_CLASSNOTAVAILABLE },
3583         { &IID_IUnknown,                   &IID_IDirect3DRM,  &IID_IDirect3DRM,  S_OK                      },
3584     };
3585     HRESULT hr;
3586     IDirect3DRM *d3drm;
3587 
3588     hr = Direct3DRMCreate(&d3drm);
3589     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x)\n", hr);
3590 
3591     test_qi("d3drm_qi", (IUnknown *)d3drm, &IID_IDirect3DRM, tests, ARRAY_SIZE(tests));
3592 
3593     IDirect3DRM_Release(d3drm);
3594 }
3595 
test_frame_qi(void)3596 static void test_frame_qi(void)
3597 {
3598     static const struct qi_test tests[] =
3599     {
3600         { &IID_IDirect3DRMFrame3,          &IID_IUnknown, &IID_IDirect3DRMFrame3, S_OK                      },
3601         { &IID_IDirect3DRMFrame2,          &IID_IUnknown, &IID_IDirect3DRMFrame2, S_OK                      },
3602         { &IID_IDirect3DRMFrame,           &IID_IUnknown, &IID_IDirect3DRMFrame,  S_OK                      },
3603         { &IID_IDirect3DRM,                NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3604         { &IID_IDirect3DRMDevice,          NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3605         { &IID_IDirect3DRMObject,          &IID_IUnknown, &IID_IDirect3DRMFrame,  S_OK                      },
3606         { &IID_IDirect3DRMDevice2,         NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3607         { &IID_IDirect3DRMDevice3,         NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3608         { &IID_IDirect3DRMViewport,        NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3609         { &IID_IDirect3DRMViewport2,       NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3610         { &IID_IDirect3DRM3,               NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3611         { &IID_IDirect3DRM2,               NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3612         { &IID_IDirect3DRMVisual,          &IID_IUnknown, &IID_IDirect3DRMFrame,  S_OK                      },
3613         { &IID_IDirect3DRMMesh,            NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3614         { &IID_IDirect3DRMMeshBuilder,     NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3615         { &IID_IDirect3DRMMeshBuilder2,    NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3616         { &IID_IDirect3DRMMeshBuilder3,    NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3617         { &IID_IDirect3DRMFace,            NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3618         { &IID_IDirect3DRMFace2,           NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3619         { &IID_IDirect3DRMLight,           NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3620         { &IID_IDirect3DRMTexture,         NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3621         { &IID_IDirect3DRMTexture2,        NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3622         { &IID_IDirect3DRMTexture3,        NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3623         { &IID_IDirect3DRMWrap,            NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3624         { &IID_IDirect3DRMMaterial,        NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3625         { &IID_IDirect3DRMMaterial2,       NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3626         { &IID_IDirect3DRMAnimation,       NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3627         { &IID_IDirect3DRMAnimation2,      NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3628         { &IID_IDirect3DRMAnimationSet,    NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3629         { &IID_IDirect3DRMAnimationSet2,   NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3630         { &IID_IDirect3DRMObjectArray,     NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3631         { &IID_IDirect3DRMDeviceArray,     NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3632         { &IID_IDirect3DRMViewportArray,   NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3633         { &IID_IDirect3DRMFrameArray,      NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3634         { &IID_IDirect3DRMVisualArray,     NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3635         { &IID_IDirect3DRMLightArray,      NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3636         { &IID_IDirect3DRMPickedArray,     NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3637         { &IID_IDirect3DRMFaceArray,       NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3638         { &IID_IDirect3DRMAnimationArray,  NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3639         { &IID_IDirect3DRMUserVisual,      NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3640         { &IID_IDirect3DRMShadow,          NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3641         { &IID_IDirect3DRMShadow2,         NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3642         { &IID_IDirect3DRMInterpolator,    NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3643         { &IID_IDirect3DRMProgressiveMesh, NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3644         { &IID_IDirect3DRMPicked2Array,    NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3645         { &IID_IDirect3DRMClippedVisual,   NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3646         { &IID_IDirectDrawClipper,         NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3647         { &IID_IDirectDrawSurface7,        NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3648         { &IID_IDirectDrawSurface4,        NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3649         { &IID_IDirectDrawSurface3,        NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3650         { &IID_IDirectDrawSurface2,        NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3651         { &IID_IDirectDrawSurface,         NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3652         { &IID_IDirect3DDevice7,           NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3653         { &IID_IDirect3DDevice3,           NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3654         { &IID_IDirect3DDevice2,           NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3655         { &IID_IDirect3DDevice,            NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3656         { &IID_IDirect3D7,                 NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3657         { &IID_IDirect3D3,                 NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3658         { &IID_IDirect3D2,                 NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3659         { &IID_IDirect3D,                  NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3660         { &IID_IDirectDraw7,               NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3661         { &IID_IDirectDraw4,               NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3662         { &IID_IDirectDraw3,               NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3663         { &IID_IDirectDraw2,               NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3664         { &IID_IDirectDraw,                NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3665         { &IID_IDirect3DLight,             NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
3666         { &IID_IUnknown,                   &IID_IUnknown, NULL,                   S_OK                      },
3667     };
3668     HRESULT hr;
3669     IDirect3DRM *d3drm1;
3670     IDirect3DRM2 *d3drm2;
3671     IDirect3DRM3 *d3drm3;
3672     IDirect3DRMFrame *frame1;
3673     IDirect3DRMFrame2 *frame2;
3674     IDirect3DRMFrame3 *frame3;
3675     IUnknown *unknown;
3676 
3677     hr = Direct3DRMCreate(&d3drm1);
3678     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x)\n", hr);
3679 
3680     hr = IDirect3DRM_CreateFrame(d3drm1, NULL, &frame1);
3681     ok(hr == D3DRM_OK, "Failed to create frame1 (hr = %x)\n", hr);
3682     hr = IDirect3DRMFrame_QueryInterface(frame1, &IID_IUnknown, (void **)&unknown);
3683     ok(hr == D3DRM_OK, "Failed to create IUnknown from frame1 (hr = %x)\n", hr);
3684     IDirect3DRMFrame_Release(frame1);
3685     test_qi("frame1_qi", unknown, &IID_IUnknown, tests, ARRAY_SIZE(tests));
3686     IUnknown_Release(unknown);
3687 
3688     hr = IDirect3DRM_QueryInterface(d3drm1, &IID_IDirect3DRM2, (void **)&d3drm2);
3689     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM2 interface (hr = %x).\n", hr);
3690     hr = IDirect3DRM2_CreateFrame(d3drm2, NULL, &frame2);
3691     ok(hr == D3DRM_OK, "Failed to create frame2 (hr = %x)\n", hr);
3692     hr = IDirect3DRMFrame2_QueryInterface(frame2, &IID_IUnknown, (void **)&unknown);
3693     ok(hr == D3DRM_OK, "Failed to create IUnknown from frame2 (hr = %x)\n", hr);
3694     IDirect3DRMFrame2_Release(frame2);
3695     test_qi("frame2_qi", unknown, &IID_IUnknown, tests, ARRAY_SIZE(tests));
3696     IUnknown_Release(unknown);
3697 
3698     hr = IDirect3DRM_QueryInterface(d3drm1, &IID_IDirect3DRM3, (void **)&d3drm3);
3699     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM3 interface (hr = %x).\n", hr);
3700     hr = IDirect3DRM3_CreateFrame(d3drm3, NULL, &frame3);
3701     ok(hr == D3DRM_OK, "Failed to create frame3 (hr = %x)\n", hr);
3702     hr = IDirect3DRMFrame3_QueryInterface(frame3, &IID_IUnknown, (void **)&unknown);
3703     ok(hr == D3DRM_OK, "Failed to create IUnknown from frame3 (hr = %x)\n", hr);
3704     IDirect3DRMFrame3_Release(frame3);
3705     test_qi("frame3_qi", unknown, &IID_IUnknown, tests, ARRAY_SIZE(tests));
3706     IUnknown_Release(unknown);
3707 
3708     IDirect3DRM3_Release(d3drm3);
3709     IDirect3DRM2_Release(d3drm2);
3710     IDirect3DRM_Release(d3drm1);
3711 }
3712 
test_device_qi(void)3713 static void test_device_qi(void)
3714 {
3715     static const struct qi_test tests[] =
3716     {
3717         { &IID_IDirect3DRM3,               NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3718         { &IID_IDirect3DRM2,               NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3719         { &IID_IDirect3DRM,                NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3720         { &IID_IDirect3DRMDevice,          &IID_IUnknown, &IID_IDirect3DRMDevice,    S_OK,                     },
3721         { &IID_IDirect3DRMDevice2,         &IID_IUnknown, &IID_IDirect3DRMDevice2,   S_OK,                     },
3722         { &IID_IDirect3DRMDevice3,         &IID_IUnknown, &IID_IDirect3DRMDevice3,   S_OK,                     },
3723         { &IID_IDirect3DRMWinDevice,       &IID_IUnknown, &IID_IDirect3DRMWinDevice, S_OK,                     },
3724         { &IID_IDirect3DRMObject,          &IID_IUnknown, &IID_IDirect3DRMDevice,    S_OK,                     },
3725         { &IID_IDirect3DRMViewport,        NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3726         { &IID_IDirect3DRMViewport2,       NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3727         { &IID_IDirect3DRMFrame,           NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3728         { &IID_IDirect3DRMFrame2,          NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3729         { &IID_IDirect3DRMFrame3,          NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3730         { &IID_IDirect3DRMVisual,          NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3731         { &IID_IDirect3DRMMesh,            NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3732         { &IID_IDirect3DRMMeshBuilder,     NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3733         { &IID_IDirect3DRMMeshBuilder2,    NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3734         { &IID_IDirect3DRMMeshBuilder3,    NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3735         { &IID_IDirect3DRMFace,            NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3736         { &IID_IDirect3DRMFace2,           NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3737         { &IID_IDirect3DRMLight,           NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3738         { &IID_IDirect3DRMTexture,         NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3739         { &IID_IDirect3DRMTexture2,        NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3740         { &IID_IDirect3DRMTexture3,        NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3741         { &IID_IDirect3DRMWrap,            NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3742         { &IID_IDirect3DRMMaterial,        NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3743         { &IID_IDirect3DRMMaterial2,       NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3744         { &IID_IDirect3DRMAnimation,       NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3745         { &IID_IDirect3DRMAnimation2,      NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3746         { &IID_IDirect3DRMAnimationSet,    NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3747         { &IID_IDirect3DRMAnimationSet2,   NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3748         { &IID_IDirect3DRMObjectArray,     NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3749         { &IID_IDirect3DRMDeviceArray,     NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3750         { &IID_IDirect3DRMViewportArray,   NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3751         { &IID_IDirect3DRMFrameArray,      NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3752         { &IID_IDirect3DRMVisualArray,     NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3753         { &IID_IDirect3DRMLightArray,      NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3754         { &IID_IDirect3DRMPickedArray,     NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3755         { &IID_IDirect3DRMFaceArray,       NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3756         { &IID_IDirect3DRMAnimationArray,  NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3757         { &IID_IDirect3DRMUserVisual,      NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3758         { &IID_IDirect3DRMShadow,          NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3759         { &IID_IDirect3DRMShadow2,         NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3760         { &IID_IDirect3DRMInterpolator,    NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3761         { &IID_IDirect3DRMProgressiveMesh, NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3762         { &IID_IDirect3DRMPicked2Array,    NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3763         { &IID_IDirect3DRMClippedVisual,   NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3764         { &IID_IDirectDrawClipper,         NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3765         { &IID_IDirectDrawSurface7,        NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3766         { &IID_IDirectDrawSurface4,        NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3767         { &IID_IDirectDrawSurface3,        NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3768         { &IID_IDirectDrawSurface2,        NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3769         { &IID_IDirectDrawSurface,         NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3770         { &IID_IDirect3DDevice7,           NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3771         { &IID_IDirect3DDevice3,           NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3772         { &IID_IDirect3DDevice2,           NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3773         { &IID_IDirect3DDevice,            NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3774         { &IID_IDirect3D7,                 NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3775         { &IID_IDirect3D3,                 NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3776         { &IID_IDirect3D2,                 NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3777         { &IID_IDirect3D,                  NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3778         { &IID_IDirectDraw7,               NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3779         { &IID_IDirectDraw4,               NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3780         { &IID_IDirectDraw3,               NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3781         { &IID_IDirectDraw2,               NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3782         { &IID_IDirectDraw,                NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3783         { &IID_IDirect3DLight,             NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
3784         { &IID_IUnknown,                   &IID_IUnknown, NULL,                      S_OK,                     },
3785     };
3786     HRESULT hr;
3787     IDirect3DRM *d3drm1;
3788     IDirect3DRM2 *d3drm2;
3789     IDirect3DRM3 *d3drm3;
3790     IDirectDrawClipper *clipper;
3791     IDirect3DRMDevice *device1;
3792     IDirect3DRMDevice2 *device2;
3793     IDirect3DRMDevice3 *device3;
3794     IUnknown *unknown;
3795     HWND window;
3796     GUID driver;
3797     RECT rc;
3798 
3799     window = create_window();
3800     GetClientRect(window, &rc);
3801     hr = DirectDrawCreateClipper(0, &clipper, NULL);
3802     ok(hr == DD_OK, "Cannot get IDirectDrawClipper interface (hr = %x)\n", hr);
3803     hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
3804     ok(hr == DD_OK, "Cannot set HWnd to Clipper (hr = %x)\n", hr);
3805 
3806     hr = Direct3DRMCreate(&d3drm1);
3807     ok(SUCCEEDED(hr), "Cannot get IDirect3DRM interface (hr = %x)\n", hr);
3808     memcpy(&driver, &IID_IDirect3DRGBDevice, sizeof(GUID));
3809     hr = IDirect3DRM_CreateDeviceFromClipper(d3drm1, clipper, &driver, rc.right, rc.bottom, &device1);
3810     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMDevice interface (hr = %x)\n", hr);
3811     hr = IDirect3DRMDevice_QueryInterface(device1, &IID_IUnknown, (void **)&unknown);
3812     ok(SUCCEEDED(hr), "Cannot get IUnknown interface from IDirect3DRMDevice (hr = %x)\n", hr);
3813     IDirect3DRMDevice_Release(device1);
3814     test_qi("device1_qi", unknown, &IID_IUnknown, tests, ARRAY_SIZE(tests));
3815     IUnknown_Release(unknown);
3816 
3817     hr = IDirect3DRM_QueryInterface(d3drm1, &IID_IDirect3DRM2, (void **)&d3drm2);
3818     ok(SUCCEEDED(hr), "Cannot get IDirect3DRM2 interface (hr = %x).\n", hr);
3819     hr = IDirect3DRM2_CreateDeviceFromClipper(d3drm2, clipper, &driver, rc.right, rc.bottom, &device2);
3820     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMDevice2 interface (hr = %x)\n", hr);
3821     hr = IDirect3DRMDevice2_QueryInterface(device2, &IID_IUnknown, (void **)&unknown);
3822     ok(SUCCEEDED(hr), "Cannot get IUnknown interface from IDirect3DRMDevice2 (hr = %x)\n", hr);
3823     IDirect3DRMDevice2_Release(device2);
3824     test_qi("device2_qi", unknown, &IID_IUnknown, tests, ARRAY_SIZE(tests));
3825     IUnknown_Release(unknown);
3826 
3827     hr = IDirect3DRM_QueryInterface(d3drm1, &IID_IDirect3DRM3, (void **)&d3drm3);
3828     ok(SUCCEEDED(hr), "Cannot get IDirect3DRM3 interface (hr = %x).\n", hr);
3829     hr = IDirect3DRM3_CreateDeviceFromClipper(d3drm3, clipper, &driver, rc.right, rc.bottom, &device3);
3830     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMDevice3 interface (hr = %x)\n", hr);
3831     hr = IDirect3DRMDevice3_QueryInterface(device3, &IID_IUnknown, (void **)&unknown);
3832     ok(SUCCEEDED(hr), "Cannot get IUnknown interface from IDirect3DRMDevice3 (hr = %x)\n", hr);
3833     IDirect3DRMDevice3_Release(device3);
3834     test_qi("device3_qi", unknown, &IID_IUnknown, tests, ARRAY_SIZE(tests));
3835     IUnknown_Release(unknown);
3836 
3837     IDirectDrawClipper_Release(clipper);
3838     IDirect3DRM3_Release(d3drm3);
3839     IDirect3DRM2_Release(d3drm2);
3840     IDirect3DRM_Release(d3drm1);
3841     DestroyWindow(window);
3842 }
3843 
3844 
surface_callback(IDirectDrawSurface * surface,DDSURFACEDESC * desc,void * context)3845 static HRESULT CALLBACK surface_callback(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
3846 {
3847     IDirectDrawSurface **primary = context;
3848 
3849     if (desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
3850     {
3851         *primary = surface;
3852         return DDENUMRET_CANCEL;
3853     }
3854     IDirectDrawSurface_Release(surface);
3855 
3856     return DDENUMRET_OK;
3857 }
3858 
test_create_device_from_clipper1(void)3859 static void test_create_device_from_clipper1(void)
3860 {
3861     DDSCAPS caps = { DDSCAPS_ZBUFFER };
3862     IDirect3DRM *d3drm1 = NULL;
3863     IDirectDraw *ddraw = NULL;
3864     IUnknown *unknown = NULL;
3865     IDirect3DRMDevice *device1 = (IDirect3DRMDevice *)0xdeadbeef;
3866     IDirect3DDevice *d3ddevice1 = NULL;
3867     IDirectDrawClipper *clipper = NULL, *d3drm_clipper = NULL;
3868     IDirectDrawSurface *surface = NULL, *ds = NULL, *d3drm_primary = NULL;
3869     IDirectDrawSurface7 *surface7 = NULL;
3870     DDSURFACEDESC desc, surface_desc;
3871     DWORD expected_flags, ret_val;
3872     HWND window;
3873     GUID driver = IID_IDirect3DRGBDevice;
3874     HRESULT hr;
3875     ULONG ref1, ref2, cref1, cref2;
3876     RECT rc;
3877 
3878     window = create_window();
3879     GetClientRect(window, &rc);
3880     hr = DirectDrawCreateClipper(0, &clipper, NULL);
3881     ok(hr == DD_OK, "Cannot get IDirectDrawClipper interface (hr = %x).\n", hr);
3882     hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
3883     ok(hr == DD_OK, "Cannot set HWnd to Clipper (hr = %x).\n", hr);
3884 
3885     hr = Direct3DRMCreate(&d3drm1);
3886     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x).\n", hr);
3887     ref1 = get_refcount((IUnknown *)d3drm1);
3888     cref1 = get_refcount((IUnknown *)clipper);
3889 
3890     hr = IDirect3DRM_CreateDeviceFromClipper(d3drm1, clipper, &driver, 0, 0, &device1);
3891     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %x.\n", hr);
3892     ok(device1 == NULL, "Expected device returned == NULL, got %p.\n", device1);
3893 
3894     /* If NULL is passed for clipper, CreateDeviceFromClipper returns D3DRMERR_BADVALUE */
3895     hr = IDirect3DRM_CreateDeviceFromClipper(d3drm1, NULL, &driver, 300, 200, &device1);
3896     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %x.\n", hr);
3897 
3898     hr = IDirect3DRM_CreateDeviceFromClipper(d3drm1, clipper, &driver, 300, 200, NULL);
3899     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %x.\n", hr);
3900 
3901     hr = IDirect3DRM_CreateDeviceFromClipper(d3drm1, clipper, &driver, 300, 200, &device1);
3902     ok(hr == D3DRM_OK, "Cannot create IDirect3DRMDevice interface (hr = %x).\n", hr);
3903     ref2 = get_refcount((IUnknown *)d3drm1);
3904     ok(ref2 > ref1, "expected ref2 > ref1, got ref1 = %u , ref2 = %u.\n", ref1, ref2);
3905     cref2 = get_refcount((IUnknown *)clipper);
3906     ok(cref2 > cref1, "expected cref2 > cref1, got cref1 = %u , cref2 = %u.\n", cref1, cref2);
3907     ret_val = IDirect3DRMDevice_GetWidth(device1);
3908     ok(ret_val == 300, "Expected device width = 300, got %u.\n", ret_val);
3909     ret_val = IDirect3DRMDevice_GetHeight(device1);
3910     ok(ret_val == 200, "Expected device height == 200, got %u.\n", ret_val);
3911 
3912     /* Fetch immediate mode device in order to access render target */
3913     hr = IDirect3DRMDevice_GetDirect3DDevice(device1, &d3ddevice1);
3914     ok(hr == D3DRM_OK, "Cannot get IDirect3DDevice interface (hr = %x).\n", hr);
3915 
3916     hr = IDirect3DDevice_QueryInterface(d3ddevice1, &IID_IDirectDrawSurface, (void **)&surface);
3917     ok(hr == DD_OK, "Cannot get surface to the render target (hr = %x).\n", hr);
3918 
3919     hr = IDirectDrawSurface_GetClipper(surface, &d3drm_clipper);
3920     ok(hr == DDERR_NOCLIPPERATTACHED, "Expected hr == DDERR_NOCLIPPERATTACHED, got %x.\n", hr);
3921 
3922     /* Check if CreateDeviceFromClipper creates a primary surface and attaches the clipper to it */
3923     hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface7, (void **)&surface7);
3924     ok(hr == DD_OK, "Cannot get IDirectDrawSurface7 interface (hr = %x).\n", hr);
3925     IDirectDrawSurface7_GetDDInterface(surface7, (void **)&unknown);
3926     hr = IUnknown_QueryInterface(unknown, &IID_IDirectDraw, (void **)&ddraw);
3927     ok(hr == DD_OK, "Cannot get IDirectDraw interface (hr = %x).\n", hr);
3928     IUnknown_Release(unknown);
3929     hr = IDirectDraw_EnumSurfaces(ddraw, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
3930             NULL, &d3drm_primary, surface_callback);
3931     ok(hr == DD_OK, "Failed to enumerate surfaces (hr = %x).\n", hr);
3932     ok(d3drm_primary != NULL, "No primary surface was enumerated.\n");
3933     hr = IDirectDrawSurface_GetClipper(d3drm_primary, &d3drm_clipper);
3934     ok(hr == DD_OK, "Cannot get attached clipper from primary surface (hr = %x).\n", hr);
3935     ok(d3drm_clipper == clipper, "Expected clipper returned == %p, got %p.\n", clipper , d3drm_clipper);
3936 
3937     IDirectDrawClipper_Release(d3drm_clipper);
3938     IDirectDrawSurface_Release(d3drm_primary);
3939     IDirectDrawSurface7_Release(surface7);
3940     IDirectDraw_Release(ddraw);
3941 
3942     /* Check properties of render target and depth surface */
3943     surface_desc.dwSize = sizeof(surface_desc);
3944     hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
3945     ok(hr == DD_OK, "Cannot get surface desc structure (hr = %x).\n", hr);
3946 
3947     ok((surface_desc.dwWidth == 300) && (surface_desc.dwHeight == 200), "Expected surface dimensions = 300, 200, got %u, %u.\n",
3948             surface_desc.dwWidth, surface_desc.dwHeight);
3949     ok((surface_desc.ddsCaps.dwCaps & (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE)) == (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE),
3950             "Expected caps containing %x, got %x.\n", DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE, surface_desc.ddsCaps.dwCaps);
3951     expected_flags = DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH;
3952     ok(surface_desc.dwFlags == expected_flags, "Expected %x for flags, got %x.\n", expected_flags, surface_desc.dwFlags);
3953 
3954     hr = DirectDrawCreate(NULL, &ddraw, NULL);
3955     ok(hr == DD_OK, "Cannot get IDirectDraw interface (hr = %x).\n", hr);
3956     desc.dwSize = sizeof(desc);
3957     hr = IDirectDraw_GetDisplayMode(ddraw, &desc);
3958     ok(hr == DD_OK, "Cannot get IDirectDraw display mode (hr = %x)\n", hr);
3959     ok(desc.ddpfPixelFormat.dwRGBBitCount == surface_desc.ddpfPixelFormat.dwRGBBitCount, "Expected %u bpp, got %u bpp.\n",
3960             surface_desc.ddpfPixelFormat.dwRGBBitCount, desc.ddpfPixelFormat.dwRGBBitCount);
3961 
3962     hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &ds);
3963     ok(hr == DD_OK, "Cannot get attached depth surface (hr = %x).\n", hr);
3964 
3965     desc.dwSize = sizeof(desc);
3966     hr = IDirectDrawSurface_GetSurfaceDesc(ds, &desc);
3967     ok(hr == DD_OK, "Cannot get z surface desc structure (hr = %x).\n", hr);
3968 
3969     ok((desc.dwWidth == 300) && (desc.dwHeight == 200), "Expected surface dimensions = 300, 200, got %u, %u.\n",
3970             desc.dwWidth, desc.dwHeight);
3971     ok((desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) == DDSCAPS_ZBUFFER, "Expected caps containing %x, got %x.\n", DDSCAPS_ZBUFFER, desc.ddsCaps.dwCaps);
3972     expected_flags = DDSD_ZBUFFERBITDEPTH | DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH;
3973     ok(desc.dwFlags == expected_flags, "Expected %x for flags, got %x.\n", expected_flags, desc.dwFlags);
3974     ok(desc.dwZBufferBitDepth == 16, "Expected 16 for Z buffer bit depth, got %u.\n", desc.dwZBufferBitDepth);
3975     ok(desc.ddpfPixelFormat.dwStencilBitMask == 0, "Expected 0 stencil bits, got %x.\n", desc.ddpfPixelFormat.dwStencilBitMask);
3976 
3977     /* Release old objects and check refcount of device and clipper */
3978     IDirectDrawSurface_Release(ds);
3979     ds = NULL;
3980     IDirectDrawSurface_Release(surface);
3981     surface = NULL;
3982     IDirect3DDevice_Release(d3ddevice1);
3983     d3ddevice1 = NULL;
3984     IDirect3DRMDevice_Release(device1);
3985     ref2 = get_refcount((IUnknown *)d3drm1);
3986     ok(ref1 == ref2, "expected ref1 == ref2, got ref1 = %u, ref2 = %u.\n", ref1, ref2);
3987     cref2 = get_refcount((IUnknown *)clipper);
3988     ok(cref1 == cref2, "expected cref1 == cref2, got cref1 = %u, cref2 = %u.\n", cref1, cref2);
3989 
3990     /* Test if render target format follows the screen format */
3991     hr = IDirectDraw_GetDisplayMode(ddraw, &desc);
3992     ok(hr == DD_OK, "Cannot get IDirectDraw display mode (hr = %x)\n", hr);
3993     hr = IDirectDraw_SetDisplayMode(ddraw, desc.dwWidth, desc.dwHeight, 16);
3994     ok(hr == DD_OK, "Cannot set display mode to 16bpp (hr = %x).\n", hr);
3995 
3996     hr = IDirectDraw_GetDisplayMode(ddraw, &desc);
3997     ok(hr == DD_OK, "Cannot get IDirectDraw display mode (hr = %x)\n", hr);
3998     ok(desc.ddpfPixelFormat.dwRGBBitCount == 16, "Expected 16 bpp, got %u.\n", desc.ddpfPixelFormat.dwRGBBitCount);
3999 
4000     hr = IDirect3DRM_CreateDeviceFromClipper(d3drm1, clipper, &driver, rc.right, rc.bottom, &device1);
4001     ok(hr == D3DRM_OK, "Cannot create IDirect3DRMDevice interface (hr = %x).\n", hr);
4002 
4003     hr = IDirect3DRMDevice_GetDirect3DDevice(device1, &d3ddevice1);
4004     ok(hr == D3DRM_OK, "Cannot get IDirect3DDevice interface (hr = %x).\n", hr);
4005 
4006     hr = IDirect3DDevice_QueryInterface(d3ddevice1, &IID_IDirectDrawSurface, (void **)&surface);
4007     ok(hr == DD_OK, "Cannot get surface to the render target (hr = %x).\n", hr);
4008 
4009     surface_desc.dwSize = sizeof(surface_desc);
4010     hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
4011     ok(hr == DD_OK, "Cannot get surface desc structure (hr = %x).\n", hr);
4012     todo_wine ok(surface_desc.ddpfPixelFormat.dwRGBBitCount == 16, "Expected 16bpp, got %ubpp.\n",
4013             surface_desc.ddpfPixelFormat.dwRGBBitCount);
4014 
4015     hr = IDirectDraw2_RestoreDisplayMode(ddraw);
4016     ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
4017 
4018     if (ds)
4019         IDirectDrawSurface_Release(ds);
4020     IDirectDrawSurface_Release(surface);
4021     IDirect3DDevice_Release(d3ddevice1);
4022     IDirect3DRMDevice_Release(device1);
4023     IDirect3DRM_Release(d3drm1);
4024     IDirectDrawClipper_Release(clipper);
4025     IDirectDraw_Release(ddraw);
4026     DestroyWindow(window);
4027 }
4028 
test_create_device_from_clipper2(void)4029 static void test_create_device_from_clipper2(void)
4030 {
4031     DDSCAPS caps = { DDSCAPS_ZBUFFER };
4032     IDirect3DRM *d3drm1 = NULL;
4033     IDirect3DRM2 *d3drm2 = NULL;
4034     IDirectDraw *ddraw = NULL;
4035     IUnknown *unknown = NULL;
4036     IDirect3DRMDevice2 *device2 = (IDirect3DRMDevice2 *)0xdeadbeef;
4037     IDirect3DDevice2 *d3ddevice2 = NULL;
4038     IDirectDrawClipper *clipper = NULL, *d3drm_clipper = NULL;
4039     IDirectDrawSurface *surface = NULL, *ds = NULL, *d3drm_primary = NULL;
4040     IDirectDrawSurface7 *surface7 = NULL;
4041     DDSURFACEDESC desc, surface_desc;
4042     DWORD expected_flags, ret_val;
4043     HWND window;
4044     GUID driver = IID_IDirect3DRGBDevice;
4045     HRESULT hr;
4046     ULONG ref1, ref2, ref3, cref1, cref2;
4047     RECT rc;
4048 
4049     window = create_window();
4050     GetClientRect(window, &rc);
4051     hr = DirectDrawCreateClipper(0, &clipper, NULL);
4052     ok(hr == DD_OK, "Cannot get IDirectDrawClipper interface (hr = %x).\n", hr);
4053     hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
4054     ok(hr == DD_OK, "Cannot set HWnd to Clipper (hr = %x).\n", hr);
4055 
4056     hr = Direct3DRMCreate(&d3drm1);
4057     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x).\n", hr);
4058     ref1 = get_refcount((IUnknown *)d3drm1);
4059     cref1 = get_refcount((IUnknown *)clipper);
4060 
4061     hr = IDirect3DRM_QueryInterface(d3drm1, &IID_IDirect3DRM2, (void **)&d3drm2);
4062     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM2 interface (hr = %x).\n", hr);
4063     ref2 = get_refcount((IUnknown *)d3drm2);
4064 
4065     hr = IDirect3DRM2_CreateDeviceFromClipper(d3drm2, clipper, &driver, 0, 0, &device2);
4066     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %x.\n", hr);
4067     ok(device2 == NULL, "Expected device returned == NULL, got %p.\n", device2);
4068 
4069     /* If NULL is passed for clipper, CreateDeviceFromClipper returns D3DRMERR_BADVALUE */
4070     hr = IDirect3DRM2_CreateDeviceFromClipper(d3drm2, NULL, &driver, 300, 200, &device2);
4071     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %x.\n", hr);
4072 
4073     hr = IDirect3DRM2_CreateDeviceFromClipper(d3drm2, clipper, &driver, 300, 200, NULL);
4074     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %x.\n", hr);
4075 
4076     hr = IDirect3DRM2_CreateDeviceFromClipper(d3drm2, clipper, &driver, 300, 200, &device2);
4077     ok(hr == D3DRM_OK, "Cannot create IDirect3DRMDevice2 interface (hr = %x).\n", hr);
4078     ref3 = get_refcount((IUnknown *)d3drm1);
4079     ok(ref3 > ref1, "expected ref3 > ref1, got ref1 = %u , ref3 = %u.\n", ref1, ref3);
4080     ref3 = get_refcount((IUnknown *)d3drm2);
4081     ok(ref3 == ref2, "expected ref3 == ref2, got ref2 = %u , ref3 = %u.\n", ref2, ref3);
4082     cref2 = get_refcount((IUnknown *)clipper);
4083     ok(cref2 > cref1, "expected cref2 > cref1, got cref1 = %u , cref2 = %u.\n", cref1, cref2);
4084     ret_val = IDirect3DRMDevice2_GetWidth(device2);
4085     ok(ret_val == 300, "Expected device width = 300, got %u.\n", ret_val);
4086     ret_val = IDirect3DRMDevice2_GetHeight(device2);
4087     ok(ret_val == 200, "Expected device height == 200, got %u.\n", ret_val);
4088 
4089     /* Fetch immediate mode device in order to access render target */
4090     hr = IDirect3DRMDevice2_GetDirect3DDevice2(device2, &d3ddevice2);
4091     ok(hr == D3DRM_OK, "Cannot get IDirect3DDevice2 interface (hr = %x).\n", hr);
4092 
4093     hr = IDirect3DDevice2_GetRenderTarget(d3ddevice2, &surface);
4094     ok(hr == DD_OK, "Cannot get surface to the render target (hr = %x).\n", hr);
4095 
4096     hr = IDirectDrawSurface_GetClipper(surface, &d3drm_clipper);
4097     ok(hr == DDERR_NOCLIPPERATTACHED, "Expected hr == DDERR_NOCLIPPERATTACHED, got %x.\n", hr);
4098 
4099     /* Check if CreateDeviceFromClipper creates a primary surface and attaches the clipper to it */
4100     hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface7, (void **)&surface7);
4101     ok(hr == DD_OK, "Cannot get IDirectDrawSurface7 interface (hr = %x).\n", hr);
4102     IDirectDrawSurface7_GetDDInterface(surface7, (void **)&unknown);
4103     hr = IUnknown_QueryInterface(unknown, &IID_IDirectDraw, (void **)&ddraw);
4104     ok(hr == DD_OK, "Cannot get IDirectDraw interface (hr = %x).\n", hr);
4105     IUnknown_Release(unknown);
4106     hr = IDirectDraw_EnumSurfaces(ddraw, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
4107             NULL, &d3drm_primary, surface_callback);
4108     ok(hr == DD_OK, "Failed to enumerate surfaces (hr = %x).\n", hr);
4109     ok(d3drm_primary != NULL, "No primary surface was enumerated.\n");
4110     hr = IDirectDrawSurface_GetClipper(d3drm_primary, &d3drm_clipper);
4111     ok(hr == DD_OK, "Cannot get attached clipper from primary surface (hr = %x).\n", hr);
4112     ok(d3drm_clipper == clipper, "Expected clipper returned == %p, got %p.\n", clipper , d3drm_clipper);
4113 
4114     IDirectDrawClipper_Release(d3drm_clipper);
4115     IDirectDrawSurface_Release(d3drm_primary);
4116     IDirectDrawSurface7_Release(surface7);
4117     IDirectDraw_Release(ddraw);
4118 
4119     /* Check properties of render target and depth surface */
4120     surface_desc.dwSize = sizeof(surface_desc);
4121     hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
4122     ok(hr == DD_OK, "Cannot get surface desc structure (hr = %x).\n", hr);
4123 
4124     ok((surface_desc.dwWidth == 300) && (surface_desc.dwHeight == 200), "Expected surface dimensions = 300, 200, got %u, %u.\n",
4125             surface_desc.dwWidth, surface_desc.dwHeight);
4126     ok((surface_desc.ddsCaps.dwCaps & (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE)) == (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE),
4127             "Expected caps containing %x, got %x.\n", DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE, surface_desc.ddsCaps.dwCaps);
4128     expected_flags = DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH;
4129     ok(surface_desc.dwFlags == expected_flags, "Expected %x for flags, got %x.\n", expected_flags, surface_desc.dwFlags);
4130 
4131     hr = DirectDrawCreate(NULL, &ddraw, NULL);
4132     ok(hr == DD_OK, "Cannot get IDirectDraw interface (hr = %x).\n", hr);
4133     desc.dwSize = sizeof(desc);
4134     hr = IDirectDraw_GetDisplayMode(ddraw, &desc);
4135     ok(hr == DD_OK, "Cannot get IDirectDraw display mode (hr = %x)\n", hr);
4136     ok(desc.ddpfPixelFormat.dwRGBBitCount == surface_desc.ddpfPixelFormat.dwRGBBitCount, "Expected %u bpp, got %u bpp.\n",
4137             surface_desc.ddpfPixelFormat.dwRGBBitCount, desc.ddpfPixelFormat.dwRGBBitCount);
4138 
4139     hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &ds);
4140     ok(hr == DD_OK, "Cannot get attached depth surface (hr = %x).\n", hr);
4141 
4142     desc.dwSize = sizeof(desc);
4143     hr = IDirectDrawSurface_GetSurfaceDesc(ds, &desc);
4144     ok(hr == DD_OK, "Cannot get z surface desc structure (hr = %x).\n", hr);
4145 
4146     ok((desc.dwWidth == 300) && (desc.dwHeight == 200), "Expected surface dimensions = 300, 200, got %u, %u.\n",
4147             desc.dwWidth, desc.dwHeight);
4148     ok((desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) == DDSCAPS_ZBUFFER, "Expected caps containing %x, got %x.\n", DDSCAPS_ZBUFFER, desc.ddsCaps.dwCaps);
4149     expected_flags = DDSD_ZBUFFERBITDEPTH | DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH;
4150     ok(desc.dwFlags == expected_flags, "Expected %x for flags, got %x.\n", expected_flags, desc.dwFlags);
4151     ok(desc.dwZBufferBitDepth == 16, "Expected 16 for Z buffer bit depth, got %u.\n", desc.dwZBufferBitDepth);
4152     ok(desc.ddpfPixelFormat.dwStencilBitMask == 0, "Expected 0 stencil bits, got %x.\n", desc.ddpfPixelFormat.dwStencilBitMask);
4153 
4154     /* Release old objects and check refcount of device and clipper */
4155     IDirectDrawSurface_Release(ds);
4156     ds = NULL;
4157     IDirectDrawSurface_Release(surface);
4158     surface = NULL;
4159     IDirect3DDevice2_Release(d3ddevice2);
4160     d3ddevice2 = NULL;
4161     IDirect3DRMDevice2_Release(device2);
4162     ref3 = get_refcount((IUnknown *)d3drm1);
4163     ok(ref1 == ref3, "expected ref1 == ref3, got ref1 = %u, ref3 = %u.\n", ref1, ref3);
4164     ref3 = get_refcount((IUnknown *)d3drm2);
4165     ok(ref3 == ref2, "expected ref3 == ref2, got ref2 = %u , ref3 = %u.\n", ref2, ref3);
4166     cref2 = get_refcount((IUnknown *)clipper);
4167     ok(cref1 == cref2, "expected cref1 == cref2, got cref1 = %u, cref2 = %u.\n", cref1, cref2);
4168 
4169     /* Test if render target format follows the screen format */
4170     hr = IDirectDraw_GetDisplayMode(ddraw, &desc);
4171     ok(hr == DD_OK, "Cannot get IDirectDraw display mode (hr = %x)\n", hr);
4172     hr = IDirectDraw_SetDisplayMode(ddraw, desc.dwWidth, desc.dwHeight, 16);
4173     ok(hr == DD_OK, "Cannot set display mode to 16bpp (hr = %x).\n", hr);
4174 
4175     hr = IDirectDraw_GetDisplayMode(ddraw, &desc);
4176     ok(hr == DD_OK, "Cannot get IDirectDraw display mode (hr = %x)\n", hr);
4177     ok(desc.ddpfPixelFormat.dwRGBBitCount == 16, "Expected 16 bpp, got %u.\n", desc.ddpfPixelFormat.dwRGBBitCount);
4178 
4179     hr = IDirect3DRM2_CreateDeviceFromClipper(d3drm2, clipper, &driver, rc.right, rc.bottom, &device2);
4180     ok(hr == D3DRM_OK, "Cannot create IDirect3DRMDevice2 interface (hr = %x).\n", hr);
4181 
4182     hr = IDirect3DRMDevice2_GetDirect3DDevice2(device2, &d3ddevice2);
4183     ok(hr == D3DRM_OK, "Cannot get IDirect3DDevice2 interface (hr = %x).\n", hr);
4184 
4185     hr = IDirect3DDevice2_GetRenderTarget(d3ddevice2, &surface);
4186     ok(hr == DD_OK, "Cannot get surface to the render target (hr = %x).\n", hr);
4187 
4188     surface_desc.dwSize = sizeof(surface_desc);
4189     hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
4190     ok(hr == DD_OK, "Cannot get surface desc structure (hr = %x).\n", hr);
4191     todo_wine ok(surface_desc.ddpfPixelFormat.dwRGBBitCount == 16, "Expected 16bpp, got %ubpp.\n",
4192             surface_desc.ddpfPixelFormat.dwRGBBitCount);
4193 
4194     hr = IDirectDraw2_RestoreDisplayMode(ddraw);
4195     ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
4196 
4197     IDirectDrawSurface_Release(surface);
4198     IDirect3DDevice2_Release(d3ddevice2);
4199     IDirect3DRMDevice2_Release(device2);
4200     IDirect3DRM2_Release(d3drm2);
4201     IDirect3DRM_Release(d3drm1);
4202     IDirectDrawClipper_Release(clipper);
4203     IDirectDraw_Release(ddraw);
4204     DestroyWindow(window);
4205 }
4206 
test_create_device_from_clipper3(void)4207 static void test_create_device_from_clipper3(void)
4208 {
4209     DDSCAPS caps = { DDSCAPS_ZBUFFER };
4210     IDirect3DRM *d3drm1 = NULL;
4211     IDirect3DRM3 *d3drm3 = NULL;
4212     IDirectDraw *ddraw = NULL;
4213     IUnknown *unknown = NULL;
4214     IDirect3DRMDevice3 *device3 = (IDirect3DRMDevice3 *)0xdeadbeef;
4215     IDirect3DDevice2 *d3ddevice2 = NULL;
4216     IDirectDrawClipper *clipper = NULL, *d3drm_clipper = NULL;
4217     IDirectDrawSurface *surface = NULL, *ds = NULL, *d3drm_primary = NULL;
4218     IDirectDrawSurface7 *surface7 = NULL;
4219     DDSURFACEDESC desc, surface_desc;
4220     DWORD expected_flags, ret_val;
4221     HWND window;
4222     GUID driver = IID_IDirect3DRGBDevice;
4223     HRESULT hr;
4224     ULONG ref1, ref2, ref3, cref1, cref2;
4225     RECT rc;
4226 
4227     window = create_window();
4228     GetClientRect(window, &rc);
4229     hr = DirectDrawCreateClipper(0, &clipper, NULL);
4230     ok(hr == DD_OK, "Cannot get IDirectDrawClipper interface (hr = %x).\n", hr);
4231     hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
4232     ok(hr == DD_OK, "Cannot set HWnd to Clipper (hr = %x).\n", hr);
4233 
4234     hr = Direct3DRMCreate(&d3drm1);
4235     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x).\n", hr);
4236     ref1 = get_refcount((IUnknown *)d3drm1);
4237     cref1 = get_refcount((IUnknown *)clipper);
4238 
4239     hr = IDirect3DRM_QueryInterface(d3drm1, &IID_IDirect3DRM3, (void **)&d3drm3);
4240     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM3 interface (hr = %x).\n", hr);
4241     ref2 = get_refcount((IUnknown *)d3drm3);
4242 
4243     hr = IDirect3DRM3_CreateDeviceFromClipper(d3drm3, clipper, &driver, 0, 0, &device3);
4244     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %x.\n", hr);
4245     ok(device3 == NULL, "Expected device returned == NULL, got %p.\n", device3);
4246 
4247     /* If NULL is passed for clipper, CreateDeviceFromClipper returns D3DRMERR_BADVALUE */
4248     hr = IDirect3DRM3_CreateDeviceFromClipper(d3drm3, NULL, &driver, 300, 200, &device3);
4249     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %x.\n", hr);
4250 
4251     hr = IDirect3DRM3_CreateDeviceFromClipper(d3drm3, clipper, &driver, 300, 200, NULL);
4252     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %x.\n", hr);
4253 
4254     hr = IDirect3DRM3_CreateDeviceFromClipper(d3drm3, clipper, &driver, 300, 200, &device3);
4255     ok(hr == D3DRM_OK, "Cannot create IDirect3DRMDevice3 interface (hr = %x).\n", hr);
4256     ref3 = get_refcount((IUnknown *)d3drm1);
4257     ok(ref3 > ref1, "expected ref3 > ref1, got ref1 = %u , ref3 = %u.\n", ref1, ref3);
4258     ref3 = get_refcount((IUnknown *)d3drm3);
4259     ok(ref3 == ref2, "expected ref3 == ref2, got ref2 = %u , ref3 = %u.\n", ref2, ref3);
4260     cref2 = get_refcount((IUnknown *)clipper);
4261     ok(cref2 > cref1, "expected cref2 > cref1, got cref1 = %u , cref2 = %u.\n", cref1, cref2);
4262     ret_val = IDirect3DRMDevice3_GetWidth(device3);
4263     ok(ret_val == 300, "Expected device width = 300, got %u.\n", ret_val);
4264     ret_val = IDirect3DRMDevice3_GetHeight(device3);
4265     ok(ret_val == 200, "Expected device height == 200, got %u.\n", ret_val);
4266 
4267     /* Fetch immediate mode device in order to access render target */
4268     hr = IDirect3DRMDevice3_GetDirect3DDevice2(device3, &d3ddevice2);
4269     ok(hr == D3DRM_OK, "Cannot get IDirect3DDevice2 interface (hr = %x).\n", hr);
4270 
4271     hr = IDirect3DDevice2_GetRenderTarget(d3ddevice2, &surface);
4272     ok(hr == DD_OK, "Cannot get surface to the render target (hr = %x).\n", hr);
4273 
4274     hr = IDirectDrawSurface_GetClipper(surface, &d3drm_clipper);
4275     ok(hr == DDERR_NOCLIPPERATTACHED, "Expected hr == DDERR_NOCLIPPERATTACHED, got %x.\n", hr);
4276 
4277     /* Check if CreateDeviceFromClipper creates a primary surface and attaches the clipper to it */
4278     hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface7, (void **)&surface7);
4279     ok(hr == DD_OK, "Cannot get IDirectDrawSurface7 interface (hr = %x).\n", hr);
4280     IDirectDrawSurface7_GetDDInterface(surface7, (void **)&unknown);
4281     hr = IUnknown_QueryInterface(unknown, &IID_IDirectDraw, (void **)&ddraw);
4282     ok(hr == DD_OK, "Cannot get IDirectDraw interface (hr = %x).\n", hr);
4283     IUnknown_Release(unknown);
4284     hr = IDirectDraw_EnumSurfaces(ddraw, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
4285             NULL, &d3drm_primary, surface_callback);
4286     ok(hr == DD_OK, "Failed to enumerate surfaces (hr = %x).\n", hr);
4287     ok(d3drm_primary != NULL, "No primary surface was enumerated.\n");
4288     hr = IDirectDrawSurface_GetClipper(d3drm_primary, &d3drm_clipper);
4289     ok(hr == DD_OK, "Cannot get attached clipper from primary surface (hr = %x).\n", hr);
4290     ok(d3drm_clipper == clipper, "Expected clipper returned == %p, got %p.\n", clipper , d3drm_clipper);
4291 
4292     IDirectDrawClipper_Release(d3drm_clipper);
4293     IDirectDrawSurface_Release(d3drm_primary);
4294     IDirectDrawSurface7_Release(surface7);
4295     IDirectDraw_Release(ddraw);
4296 
4297     /* Check properties of render target and depth surface */
4298     surface_desc.dwSize = sizeof(surface_desc);
4299     hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
4300     ok(hr == DD_OK, "Cannot get surface desc structure (hr = %x).\n", hr);
4301 
4302     ok((surface_desc.dwWidth == 300) && (surface_desc.dwHeight == 200), "Expected surface dimensions = 300, 200, got %u, %u.\n",
4303             surface_desc.dwWidth, surface_desc.dwHeight);
4304     ok((surface_desc.ddsCaps.dwCaps & (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE)) == (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE),
4305             "Expected caps containing %x, got %x.\n", DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE, surface_desc.ddsCaps.dwCaps);
4306     expected_flags = DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH;
4307     ok(surface_desc.dwFlags == expected_flags, "Expected %x for flags, got %x.\n", expected_flags, surface_desc.dwFlags);
4308 
4309     hr = DirectDrawCreate(NULL, &ddraw, NULL);
4310     ok(hr == DD_OK, "Cannot get IDirectDraw interface (hr = %x).\n", hr);
4311     desc.dwSize = sizeof(desc);
4312     hr = IDirectDraw_GetDisplayMode(ddraw, &desc);
4313     ok(hr == DD_OK, "Cannot get IDirectDraw display mode (hr = %x)\n", hr);
4314     ok(desc.ddpfPixelFormat.dwRGBBitCount == surface_desc.ddpfPixelFormat.dwRGBBitCount, "Expected %u bpp, got %u bpp.\n",
4315             surface_desc.ddpfPixelFormat.dwRGBBitCount, desc.ddpfPixelFormat.dwRGBBitCount);
4316 
4317     hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &ds);
4318     ok(hr == DD_OK, "Cannot get attached depth surface (hr = %x).\n", hr);
4319 
4320     desc.dwSize = sizeof(desc);
4321     hr = IDirectDrawSurface_GetSurfaceDesc(ds, &desc);
4322     ok(hr == DD_OK, "Cannot get z surface desc structure (hr = %x).\n", hr);
4323 
4324     ok((desc.dwWidth == 300) && (desc.dwHeight == 200), "Expected surface dimensions = 300, 200, got %u, %u.\n",
4325             desc.dwWidth, desc.dwHeight);
4326     ok((desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) == DDSCAPS_ZBUFFER, "Expected caps containing %x, got %x.\n", DDSCAPS_ZBUFFER, desc.ddsCaps.dwCaps);
4327     expected_flags = DDSD_ZBUFFERBITDEPTH | DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH;
4328     ok(desc.dwFlags == expected_flags, "Expected %x for flags, got %x.\n", expected_flags, desc.dwFlags);
4329     ok(desc.dwZBufferBitDepth == 16, "Expected 16 for Z buffer bit depth, got %u.\n", desc.dwZBufferBitDepth);
4330     ok(desc.ddpfPixelFormat.dwStencilBitMask == 0, "Expected 0 stencil bits, got %x.\n", desc.ddpfPixelFormat.dwStencilBitMask);
4331 
4332     /* Release old objects and check refcount of device and clipper */
4333     IDirectDrawSurface_Release(ds);
4334     ds = NULL;
4335     IDirectDrawSurface_Release(surface);
4336     surface = NULL;
4337     IDirect3DDevice2_Release(d3ddevice2);
4338     d3ddevice2 = NULL;
4339     IDirect3DRMDevice3_Release(device3);
4340     ref3 = get_refcount((IUnknown *)d3drm1);
4341     ok(ref1 == ref3, "expected ref1 == ref3, got ref1 = %u, ref3 = %u.\n", ref1, ref3);
4342     ref3 = get_refcount((IUnknown *)d3drm3);
4343     ok(ref3 == ref2, "expected ref3 == ref2, got ref2 = %u , ref3 = %u.\n", ref2, ref3);
4344     cref2 = get_refcount((IUnknown *)clipper);
4345     ok(cref1 == cref2, "expected cref1 == cref2, got cref1 = %u, cref2 = %u.\n", cref1, cref2);
4346 
4347     /* Test if render target format follows the screen format */
4348     hr = IDirectDraw_GetDisplayMode(ddraw, &desc);
4349     ok(hr == DD_OK, "Cannot get IDirectDraw display mode (hr = %x)\n", hr);
4350     hr = IDirectDraw_SetDisplayMode(ddraw, desc.dwWidth, desc.dwHeight, 16);
4351     ok(hr == DD_OK, "Cannot set display mode to 16bpp (hr = %x).\n", hr);
4352 
4353     hr = IDirectDraw_GetDisplayMode(ddraw, &desc);
4354     ok(hr == DD_OK, "Cannot get IDirectDraw display mode (hr = %x)\n", hr);
4355     ok(desc.ddpfPixelFormat.dwRGBBitCount == 16, "Expected 16 bpp, got %u.\n", desc.ddpfPixelFormat.dwRGBBitCount);
4356 
4357     hr = IDirect3DRM3_CreateDeviceFromClipper(d3drm3, clipper, &driver, rc.right, rc.bottom, &device3);
4358     ok(hr == D3DRM_OK, "Cannot create IDirect3DRMDevice3 interface (hr = %x).\n", hr);
4359 
4360     hr = IDirect3DRMDevice3_GetDirect3DDevice2(device3, &d3ddevice2);
4361     ok(hr == D3DRM_OK, "Cannot get IDirect3DDevice2 interface (hr = %x).\n", hr);
4362 
4363     hr = IDirect3DDevice2_GetRenderTarget(d3ddevice2, &surface);
4364     ok(hr == DD_OK, "Cannot get surface to the render target (hr = %x).\n", hr);
4365 
4366     surface_desc.dwSize = sizeof(surface_desc);
4367     hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
4368     ok(hr == DD_OK, "Cannot get surface desc structure (hr = %x).\n", hr);
4369     todo_wine ok(surface_desc.ddpfPixelFormat.dwRGBBitCount == 16, "Expected 16bpp, got %ubpp.\n",
4370             surface_desc.ddpfPixelFormat.dwRGBBitCount);
4371 
4372     hr = IDirectDraw2_RestoreDisplayMode(ddraw);
4373     ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
4374 
4375     IDirectDrawSurface_Release(surface);
4376     IDirect3DDevice2_Release(d3ddevice2);
4377     IDirect3DRMDevice3_Release(device3);
4378     IDirect3DRM3_Release(d3drm3);
4379     IDirect3DRM_Release(d3drm1);
4380     IDirectDrawClipper_Release(clipper);
4381     IDirectDraw_Release(ddraw);
4382     DestroyWindow(window);
4383 }
4384 
test_create_device_from_surface1(void)4385 static void test_create_device_from_surface1(void)
4386 {
4387     DDSCAPS caps = { DDSCAPS_ZBUFFER };
4388     DDSURFACEDESC desc;
4389     IDirectDraw *ddraw = NULL;
4390     IDirect3DRM *d3drm1 = NULL;
4391     IDirect3DRMDevice *device1 = (IDirect3DRMDevice *)0xdeadbeef;
4392     IDirect3DDevice *d3ddevice1 = NULL;
4393     IDirectDrawSurface *surface = NULL, *ds = NULL, *d3drm_surface = NULL, *d3drm_ds = NULL;
4394     DWORD expected_flags, ret_val;
4395     HWND window;
4396     GUID driver = IID_IDirect3DRGBDevice;
4397     ULONG ref1, ref2, surface_ref1, surface_ref2;
4398     RECT rc;
4399     BOOL use_sysmem_zbuffer = FALSE;
4400     HRESULT hr;
4401 
4402     hr = DirectDrawCreate(NULL, &ddraw, NULL);
4403     ok(hr == DD_OK, "Cannot get IDirectDraw interface (hr = %x).\n", hr);
4404 
4405     window = create_window();
4406     GetClientRect(window, &rc);
4407 
4408     hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4409     ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4410 
4411     hr = Direct3DRMCreate(&d3drm1);
4412     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x).\n", hr);
4413     ref1 = get_refcount((IUnknown *)d3drm1);
4414 
4415     /* Create a surface and use it to create the retained mode device. */
4416     memset(&desc, 0, sizeof(desc));
4417     desc.dwSize = sizeof(desc);
4418     desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4419     desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4420     desc.dwWidth = rc.right;
4421     desc.dwHeight = rc.bottom;
4422 
4423     hr = IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL);
4424     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4425 
4426     hr = IDirect3DRM_CreateDeviceFromSurface(d3drm1, &driver, ddraw, surface, &device1);
4427     ok(hr == DDERR_INVALIDCAPS, "Expected hr == DDERR_INVALIDCAPS, got %x.\n", hr);
4428     ok(device1 == NULL, "Expected device returned == NULL, got %p.\n", device1);
4429     IDirectDrawSurface_Release(surface);
4430 
4431     desc.ddsCaps.dwCaps |= DDSCAPS_3DDEVICE;
4432     hr = IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL);
4433     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4434     surface_ref1 = get_refcount((IUnknown *)surface);
4435 
4436     hr = IDirect3DRM_CreateDeviceFromSurface(d3drm1, &driver, ddraw, surface, NULL);
4437     ok(hr == D3DRMERR_BADVALUE, "Expected hr == DDERR_BADVALUE, got %x.\n", hr);
4438     hr = IDirect3DRM_CreateDeviceFromSurface(d3drm1, &driver, ddraw, NULL, &device1);
4439     ok(hr == D3DRMERR_BADDEVICE, "Expected hr == DDERR_BADDEVICE, got %x.\n", hr);
4440     hr = IDirect3DRM_CreateDeviceFromSurface(d3drm1, &driver, NULL, surface, &device1);
4441     ok(hr == D3DRMERR_BADDEVICE, "Expected hr == DDERR_BADDEVICE, got %x.\n", hr);
4442 
4443     hr = IDirect3DRM_CreateDeviceFromSurface(d3drm1, &driver, ddraw, surface, &device1);
4444     ok(SUCCEEDED(hr), "Cannot create IDirect3DRMDevice interface (hr = %x).\n", hr);
4445     ref2 = get_refcount((IUnknown *)d3drm1);
4446     ok(ref2 > ref1, "expected ref2 > ref1, got ref1 = %u , ref2 = %u.\n", ref1, ref2);
4447     surface_ref2 = get_refcount((IUnknown *)surface);
4448     ok(surface_ref2 > surface_ref1, "Expected surface_ref2 > surface_ref1, got surface_ref1 = %u, surface_ref2 = %u.\n", surface_ref1, surface_ref2);
4449     ret_val = IDirect3DRMDevice_GetWidth(device1);
4450     ok(ret_val == rc.right, "Expected device width = 300, got %u.\n", ret_val);
4451     ret_val = IDirect3DRMDevice_GetHeight(device1);
4452     ok(ret_val == rc.bottom, "Expected device height == 200, got %u.\n", ret_val);
4453 
4454     /* Check if CreateDeviceFromSurface creates a primary surface */
4455     hr = IDirectDraw_EnumSurfaces(ddraw, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
4456             NULL, &d3drm_surface, surface_callback);
4457     ok(hr == DD_OK, "Failed to enumerate surfaces (hr = %x).\n", hr);
4458     ok(d3drm_surface == NULL, "No primary surface should have enumerated (%p).\n", d3drm_surface);
4459 
4460     hr = IDirect3DRMDevice_GetDirect3DDevice(device1, &d3ddevice1);
4461     ok(hr == D3DRM_OK, "Cannot get IDirect3DDevice interface (hr = %x).\n", hr);
4462 
4463     hr = IDirect3DDevice_QueryInterface(d3ddevice1, &IID_IDirectDrawSurface, (void **)&d3drm_surface);
4464     ok(hr == DD_OK, "Cannot get surface to the render target (hr = %x).\n", hr);
4465     ok(surface == d3drm_surface, "Expected surface returned == %p, got %p.\n", surface, d3drm_surface);
4466 
4467     /* Check properties of attached depth surface */
4468     hr = IDirectDrawSurface_GetAttachedSurface(d3drm_surface, &caps, &ds);
4469     ok(hr == DD_OK, "Cannot get attached depth surface (hr = %x).\n", hr);
4470 
4471     memset(&desc, 0, sizeof(desc));
4472     desc.dwSize = sizeof(desc);
4473     hr = IDirectDrawSurface_GetSurfaceDesc(ds, &desc);
4474     ok(hr == DD_OK, "Cannot get z surface desc structure (hr = %x).\n", hr);
4475 
4476     use_sysmem_zbuffer = desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
4477     ok((desc.dwWidth == rc.right) && (desc.dwHeight == rc.bottom), "Expected surface dimensions = %u, %u, got %u, %u.\n",
4478             rc.right, rc.bottom, desc.dwWidth, desc.dwHeight);
4479     ok(desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER, "Expected caps containing %x, got %x.\n", DDSCAPS_ZBUFFER, desc.ddsCaps.dwCaps);
4480     expected_flags = DDSD_ZBUFFERBITDEPTH | DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH;
4481     ok(desc.dwFlags == expected_flags, "Expected %x for flags, got %x.\n", expected_flags, desc.dwFlags);
4482 
4483     IDirectDrawSurface_Release(ds);
4484     IDirect3DDevice_Release(d3ddevice1);
4485     IDirectDrawSurface_Release(d3drm_surface);
4486 
4487     IDirect3DRMDevice_Release(device1);
4488     ref2 = get_refcount((IUnknown *)d3drm1);
4489     ok(ref1 == ref2, "expected ref1 == ref2, got ref1 = %u, ref2 = %u.\n", ref1, ref2);
4490     surface_ref2 = get_refcount((IUnknown *)surface);
4491     ok(surface_ref2 == surface_ref1, "Expected surface_ref2 == surface_ref1, got surface_ref1 = %u, surface_ref2 = %u.\n",
4492             surface_ref1, surface_ref2);
4493     hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &ds);
4494     ok(hr == DD_OK, "Cannot get attached depth surface (hr = %x).\n", hr);
4495     /*The render target still holds a reference to ds as the depth surface remains attached to it, so refcount will be 1*/
4496     ref1 = IDirectDrawSurface_Release(ds);
4497     ok(ref1 == 1, "Expected ref1 == 1, got %u.\n", ref1);
4498     ref1 = IDirectDrawSurface_Release(surface);
4499     ok(ref1 == 0, "Expected Render target refcount == 0, got %u.\n", ref1);
4500 
4501     memset(&desc, 0, sizeof(desc));
4502     desc.dwSize = sizeof(desc);
4503     desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4504     desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
4505     desc.dwWidth = rc.right;
4506     desc.dwHeight = rc.bottom;
4507 
4508     hr = IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL);
4509     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4510 
4511     memset(&desc, 0, sizeof(desc));
4512     desc.dwSize = sizeof(desc);
4513     desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
4514     desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | (use_sysmem_zbuffer ? DDSCAPS_SYSTEMMEMORY : 0);
4515     desc.dwZBufferBitDepth = 16;
4516     desc.dwWidth = rc.right;
4517     desc.dwHeight = rc.bottom;
4518     hr = IDirectDraw_CreateSurface(ddraw, &desc, &ds, NULL);
4519     ok(hr == DD_OK, "Cannot create depth surface (hr = %x).\n", hr);
4520     hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
4521     ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
4522 
4523     hr = IDirect3DRM_CreateDeviceFromSurface(d3drm1, &driver, ddraw, surface, &device1);
4524     ok(SUCCEEDED(hr), "Cannot create IDirect3DRMDevice interface (hr = %x).\n", hr);
4525 
4526     hr = IDirect3DRMDevice2_GetDirect3DDevice(device1, &d3ddevice1);
4527     ok(hr == D3DRM_OK, "Cannot get IDirect3DDevice interface (hr = %x).\n", hr);
4528 
4529     hr = IDirect3DDevice_QueryInterface(d3ddevice1, &IID_IDirectDrawSurface, (void **)&d3drm_surface);
4530     ok(hr == DD_OK, "Cannot get surface to the render target (hr = %x).\n", hr);
4531     ok(surface == d3drm_surface, "Expected surface returned == %p, got %p.\n", surface, d3drm_surface);
4532 
4533     /* Check if depth surface matches the one we created  */
4534     hr = IDirectDrawSurface_GetAttachedSurface(d3drm_surface, &caps, &d3drm_ds);
4535     ok(hr == DD_OK, "Cannot get attached depth surface (hr = %x).\n", hr);
4536     ok(ds == d3drm_ds, "Expected depth surface (%p) == surface created internally (%p).\n", ds, d3drm_ds);
4537 
4538     IDirectDrawSurface_Release(d3drm_ds);
4539     IDirectDrawSurface_Release(d3drm_surface);
4540     IDirectDrawSurface_Release(ds);
4541 
4542     IDirect3DDevice_Release(d3ddevice1);
4543     IDirect3DRMDevice_Release(device1);
4544     hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &ds);
4545     ok(hr == DD_OK, "Cannot get attached depth surface (hr = %x).\n", hr);
4546     /*The render target still holds a reference to ds as the depth surface remains attached to it, so refcount will be 1*/
4547     ref1 = IDirectDrawSurface_Release(ds);
4548     ok(ref1 == 1, "Expected ref1 == 1, got %u.\n", ref1);
4549     ref1 = IDirectDrawSurface_Release(surface);
4550     ok(ref1 == 0, "Expected Render target refcount == 0, got %u.\n", ref1);
4551     IDirect3DRM_Release(d3drm1);
4552     IDirectDraw_Release(ddraw);
4553     DestroyWindow(window);
4554 }
4555 
test_create_device_from_surface2(void)4556 static void test_create_device_from_surface2(void)
4557 {
4558     DDSCAPS caps = { DDSCAPS_ZBUFFER };
4559     DDSURFACEDESC desc;
4560     IDirectDraw *ddraw = NULL;
4561     IDirect3DRM *d3drm1 = NULL;
4562     IDirect3DRM2 *d3drm2 = NULL;
4563     IDirect3DRMDevice2 *device2 = (IDirect3DRMDevice2 *)0xdeadbeef;
4564     IDirect3DDevice2 *d3ddevice2 = NULL;
4565     IDirectDrawSurface *surface = NULL, *ds = NULL, *d3drm_surface = NULL, *d3drm_ds = NULL;
4566     DWORD expected_flags, ret_val;
4567     HWND window;
4568     GUID driver = IID_IDirect3DRGBDevice;
4569     ULONG ref1, ref2, ref3, surface_ref1, surface_ref2;
4570     RECT rc;
4571     BOOL use_sysmem_zbuffer = FALSE;
4572     HRESULT hr;
4573 
4574     hr = DirectDrawCreate(NULL, &ddraw, NULL);
4575     ok(hr == DD_OK, "Cannot get IDirectDraw interface (hr = %x).\n", hr);
4576 
4577     window = create_window();
4578     GetClientRect(window, &rc);
4579 
4580     hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4581     ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4582 
4583     hr = Direct3DRMCreate(&d3drm1);
4584     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x).\n", hr);
4585     ref1 = get_refcount((IUnknown *)d3drm1);
4586 
4587     hr = IDirect3DRM_QueryInterface(d3drm1, &IID_IDirect3DRM2, (void **)&d3drm2);
4588     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM2 interface (hr = %x).\n", hr);
4589     ref2 = get_refcount((IUnknown *)d3drm2);
4590 
4591     /* Create a surface and use it to create the retained mode device. */
4592     memset(&desc, 0, sizeof(desc));
4593     desc.dwSize = sizeof(desc);
4594     desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4595     desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4596     desc.dwWidth = rc.right;
4597     desc.dwHeight = rc.bottom;
4598 
4599     hr = IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL);
4600     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4601 
4602     hr = IDirect3DRM2_CreateDeviceFromSurface(d3drm2, &driver, ddraw, surface, &device2);
4603     ok(hr == DDERR_INVALIDCAPS, "Expected hr == DDERR_INVALIDCAPS, got %x.\n", hr);
4604     ok(device2 == NULL, "Expected device returned == NULL, got %p.\n", device2);
4605     IDirectDrawSurface_Release(surface);
4606 
4607     desc.ddsCaps.dwCaps |= DDSCAPS_3DDEVICE;
4608     hr = IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL);
4609     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4610     surface_ref1 = get_refcount((IUnknown *)surface);
4611 
4612     hr = IDirect3DRM2_CreateDeviceFromSurface(d3drm2, &driver, ddraw, surface, NULL);
4613     ok(hr == D3DRMERR_BADVALUE, "Expected hr == DDERR_BADVALUE, got %x.\n", hr);
4614     hr = IDirect3DRM2_CreateDeviceFromSurface(d3drm2, &driver, ddraw, NULL, &device2);
4615     ok(hr == D3DRMERR_BADDEVICE, "Expected hr == DDERR_BADDEVICE, got %x.\n", hr);
4616     hr = IDirect3DRM2_CreateDeviceFromSurface(d3drm2, &driver, NULL, surface, &device2);
4617     ok(hr == D3DRMERR_BADDEVICE, "Expected hr == DDERR_BADDEVICE, got %x.\n", hr);
4618 
4619     hr = IDirect3DRM2_CreateDeviceFromSurface(d3drm2, &driver, ddraw, surface, &device2);
4620     ok(SUCCEEDED(hr), "Cannot create IDirect3DRMDevice2 interface (hr = %x).\n", hr);
4621     ref3 = get_refcount((IUnknown *)d3drm1);
4622     ok(ref3 > ref1, "expected ref3 > ref1, got ref1 = %u , ref3 = %u.\n", ref1, ref3);
4623     ref3 = get_refcount((IUnknown *)d3drm2);
4624     ok(ref3 == ref2, "expected ref3 == ref2, got ref2 = %u , ref3 = %u.\n", ref2, ref3);
4625     surface_ref2 = get_refcount((IUnknown *)surface);
4626     ok(surface_ref2 > surface_ref1, "Expected surface_ref2 > surface_ref1, got surface_ref1 = %u, surface_ref2 = %u.\n", surface_ref1, surface_ref2);
4627     ret_val = IDirect3DRMDevice2_GetWidth(device2);
4628     ok(ret_val == rc.right, "Expected device width = 300, got %u.\n", ret_val);
4629     ret_val = IDirect3DRMDevice2_GetHeight(device2);
4630     ok(ret_val == rc.bottom, "Expected device height == 200, got %u.\n", ret_val);
4631 
4632     /* Check if CreateDeviceFromSurface creates a primary surface */
4633     hr = IDirectDraw_EnumSurfaces(ddraw, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
4634             NULL, &d3drm_surface, surface_callback);
4635     ok(hr == DD_OK, "Failed to enumerate surfaces (hr = %x).\n", hr);
4636     ok(d3drm_surface == NULL, "No primary surface should have enumerated (%p).\n", d3drm_surface);
4637 
4638     hr = IDirect3DRMDevice2_GetDirect3DDevice2(device2, &d3ddevice2);
4639     ok(hr == D3DRM_OK, "Cannot get IDirect3DDevice2 interface (hr = %x).\n", hr);
4640 
4641     hr = IDirect3DDevice2_GetRenderTarget(d3ddevice2, &d3drm_surface);
4642     ok(hr == DD_OK, "Cannot get surface to the render target (hr = %x).\n", hr);
4643     ok(surface == d3drm_surface, "Expected surface returned == %p, got %p.\n", surface, d3drm_surface);
4644 
4645     /* Check properties of attached depth surface */
4646     hr = IDirectDrawSurface_GetAttachedSurface(d3drm_surface, &caps, &ds);
4647     ok(hr == DD_OK, "Cannot get attached depth surface (hr = %x).\n", hr);
4648 
4649     memset(&desc, 0, sizeof(desc));
4650     desc.dwSize = sizeof(desc);
4651     hr = IDirectDrawSurface_GetSurfaceDesc(ds, &desc);
4652     ok(hr == DD_OK, "Cannot get z surface desc structure (hr = %x).\n", hr);
4653 
4654     use_sysmem_zbuffer = desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
4655     ok((desc.dwWidth == rc.right) && (desc.dwHeight == rc.bottom), "Expected surface dimensions = %u, %u, got %u, %u.\n",
4656             rc.right, rc.bottom, desc.dwWidth, desc.dwHeight);
4657     ok(desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER, "Expected caps containing %x, got %x.\n", DDSCAPS_ZBUFFER, desc.ddsCaps.dwCaps);
4658     expected_flags = DDSD_ZBUFFERBITDEPTH | DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH;
4659     ok(desc.dwFlags == expected_flags, "Expected %x for flags, got %x.\n", expected_flags, desc.dwFlags);
4660 
4661     IDirectDrawSurface_Release(ds);
4662     IDirect3DDevice2_Release(d3ddevice2);
4663     IDirectDrawSurface_Release(d3drm_surface);
4664 
4665     IDirect3DRMDevice2_Release(device2);
4666     ref3 = get_refcount((IUnknown *)d3drm1);
4667     ok(ref1 == ref3, "expected ref1 == ref3, got ref1 = %u, ref3 = %u.\n", ref1, ref3);
4668     ref3 = get_refcount((IUnknown *)d3drm2);
4669     ok(ref3 == ref2, "expected ref3 == ref2, got ref2 = %u , ref3 = %u.\n", ref2, ref3);
4670     surface_ref2 = get_refcount((IUnknown *)surface);
4671     ok(surface_ref2 == surface_ref1, "Expected surface_ref2 == surface_ref1, got surface_ref1 = %u, surface_ref2 = %u.\n",
4672             surface_ref1, surface_ref2);
4673     hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &ds);
4674     ok(hr == DD_OK, "Cannot get attached depth surface (hr = %x).\n", hr);
4675     /*The render target still holds a reference to ds as the depth surface remains attached to it, so refcount will be 1*/
4676     ref1 = IDirectDrawSurface_Release(ds);
4677     ok(ref1 == 1, "Expected ref1 == 1, got %u.\n", ref1);
4678 
4679     ref1 = IDirectDrawSurface_Release(surface);
4680     ok(ref1 == 0, "Expected Render target refcount == 0, got %u.\n", ref1);
4681 
4682     memset(&desc, 0, sizeof(desc));
4683     desc.dwSize = sizeof(desc);
4684     desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4685     desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
4686     desc.dwWidth = rc.right;
4687     desc.dwHeight = rc.bottom;
4688 
4689     hr = IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL);
4690     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4691 
4692     memset(&desc, 0, sizeof(desc));
4693     desc.dwSize = sizeof(desc);
4694     desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
4695     desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | (use_sysmem_zbuffer ? DDSCAPS_SYSTEMMEMORY : 0);
4696     desc.dwZBufferBitDepth = 16;
4697     desc.dwWidth = rc.right;
4698     desc.dwHeight = rc.bottom;
4699     hr = IDirectDraw_CreateSurface(ddraw, &desc, &ds, NULL);
4700     ok(hr == DD_OK, "Cannot create depth surface (hr = %x).\n", hr);
4701     hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
4702     ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
4703 
4704     hr = IDirect3DRM2_CreateDeviceFromSurface(d3drm2, &driver, ddraw, surface, &device2);
4705     ok(SUCCEEDED(hr), "Cannot create IDirect3DRMDevice2 interface (hr = %x).\n", hr);
4706 
4707     hr = IDirect3DRMDevice2_GetDirect3DDevice2(device2, &d3ddevice2);
4708     ok(hr == D3DRM_OK, "Cannot get IDirect3DDevice2 interface (hr = %x).\n", hr);
4709 
4710     hr = IDirect3DDevice2_GetRenderTarget(d3ddevice2, &d3drm_surface);
4711     ok(hr == DD_OK, "Cannot get surface to the render target (hr = %x).\n", hr);
4712     ok(surface == d3drm_surface, "Expected surface returned == %p, got %p.\n", surface, d3drm_surface);
4713 
4714     /* Check if depth surface matches the one we created  */
4715     hr = IDirectDrawSurface_GetAttachedSurface(d3drm_surface, &caps, &d3drm_ds);
4716     ok(hr == DD_OK, "Cannot get attached depth surface (hr = %x).\n", hr);
4717     ok(ds == d3drm_ds, "Expected depth surface (%p) == surface created internally (%p).\n", ds, d3drm_ds);
4718 
4719     IDirectDrawSurface_Release(d3drm_ds);
4720     IDirectDrawSurface_Release(d3drm_surface);
4721     IDirectDrawSurface_Release(ds);
4722 
4723     IDirect3DDevice2_Release(d3ddevice2);
4724     IDirect3DRMDevice2_Release(device2);
4725     hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &ds);
4726     ok(hr == DD_OK, "Cannot get attached depth surface (hr = %x).\n", hr);
4727     /*The render target still holds a reference to ds as the depth surface remains attached to it, so refcount will be 1*/
4728     ref1 = IDirectDrawSurface_Release(ds);
4729     ok(ref1 == 1, "Expected ref1 == 1, got %u.\n", ref1);
4730     ref1 = IDirectDrawSurface_Release(surface);
4731     ok(ref1 == 0, "Expected Render target refcount == 0, got %u.\n", ref1);
4732     IDirect3DRM2_Release(d3drm2);
4733     IDirect3DRM_Release(d3drm1);
4734     IDirectDraw_Release(ddraw);
4735     DestroyWindow(window);
4736 }
4737 
test_create_device_from_surface3(void)4738 static void test_create_device_from_surface3(void)
4739 {
4740     DDSCAPS caps = { DDSCAPS_ZBUFFER };
4741     DDSURFACEDESC desc;
4742     IDirectDraw *ddraw = NULL;
4743     IDirect3DRM *d3drm1 = NULL;
4744     IDirect3DRM3 *d3drm3 = NULL;
4745     IDirect3DRMDevice3 *device3 = (IDirect3DRMDevice3 *)0xdeadbeef;
4746     IDirect3DDevice2 *d3ddevice2 = NULL;
4747     IDirectDrawSurface *surface = NULL, *ds = NULL, *d3drm_surface = NULL, *d3drm_ds = NULL;
4748     DWORD expected_flags, ret_val;
4749     HWND window;
4750     GUID driver = IID_IDirect3DRGBDevice;
4751     ULONG ref1, ref2, ref3, surface_ref1, surface_ref2;
4752     RECT rc;
4753     BOOL use_sysmem_zbuffer = FALSE;
4754     HRESULT hr;
4755 
4756     hr = DirectDrawCreate(NULL, &ddraw, NULL);
4757     ok(hr == DD_OK, "Cannot get IDirectDraw interface (hr = %x).\n", hr);
4758 
4759     window = create_window();
4760     GetClientRect(window, &rc);
4761 
4762     hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4763     ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4764 
4765     hr = Direct3DRMCreate(&d3drm1);
4766     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x).\n", hr);
4767     ref1 = get_refcount((IUnknown *)d3drm1);
4768 
4769     hr = IDirect3DRM_QueryInterface(d3drm1, &IID_IDirect3DRM3, (void **)&d3drm3);
4770     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM3 interface (hr = %x).\n", hr);
4771     ref2 = get_refcount((IUnknown *)d3drm3);
4772 
4773     /* Create a surface and use it to create the retained mode device. */
4774     memset(&desc, 0, sizeof(desc));
4775     desc.dwSize = sizeof(desc);
4776     desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4777     desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4778     desc.dwWidth = rc.right;
4779     desc.dwHeight = rc.bottom;
4780 
4781     hr = IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL);
4782     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4783 
4784     hr = IDirect3DRM3_CreateDeviceFromSurface(d3drm3, &driver, ddraw, surface, 0, &device3);
4785     ok(hr == DDERR_INVALIDCAPS, "Expected hr == DDERR_INVALIDCAPS, got %x.\n", hr);
4786     ok(device3 == NULL, "Expected device returned == NULL, got %p.\n", device3);
4787     IDirectDrawSurface_Release(surface);
4788 
4789     desc.ddsCaps.dwCaps |= DDSCAPS_3DDEVICE;
4790     hr = IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL);
4791     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4792     surface_ref1 = get_refcount((IUnknown *)surface);
4793 
4794     hr = IDirect3DRM3_CreateDeviceFromSurface(d3drm3, &driver, ddraw, surface, 0, NULL);
4795     ok(hr == D3DRMERR_BADVALUE, "Expected hr == DDERR_BADVALUE, got %x.\n", hr);
4796     hr = IDirect3DRM3_CreateDeviceFromSurface(d3drm3, &driver, ddraw, NULL, 0, &device3);
4797     ok(hr == D3DRMERR_BADDEVICE, "Expected hr == DDERR_BADDEVICE, got %x.\n", hr);
4798     hr = IDirect3DRM3_CreateDeviceFromSurface(d3drm3, &driver, NULL, surface, 0, &device3);
4799     ok(hr == D3DRMERR_BADDEVICE, "Expected hr == DDERR_BADDEVICE, got %x.\n", hr);
4800 
4801     hr = IDirect3DRM3_CreateDeviceFromSurface(d3drm3, &driver, ddraw, surface, 0, &device3);
4802     ok(SUCCEEDED(hr), "Cannot create IDirect3DRMDevice3 interface (hr = %x).\n", hr);
4803     ref3 = get_refcount((IUnknown *)d3drm1);
4804     ok(ref3 > ref1, "expected ref3 > ref1, got ref1 = %u , ref3 = %u.\n", ref1, ref3);
4805     ref3 = get_refcount((IUnknown *)d3drm3);
4806     ok(ref3 == ref2, "expected ref3 == ref2, got ref2 = %u , ref3 = %u.\n", ref2, ref3);
4807     surface_ref2 = get_refcount((IUnknown *)surface);
4808     ok(surface_ref2 > surface_ref1, "Expected surface_ref2 > surface_ref1, got surface_ref1 = %u, surface_ref2 = %u.\n", surface_ref1, surface_ref2);
4809     ret_val = IDirect3DRMDevice3_GetWidth(device3);
4810     ok(ret_val == rc.right, "Expected device width = 300, got %u.\n", ret_val);
4811     ret_val = IDirect3DRMDevice3_GetHeight(device3);
4812     ok(ret_val == rc.bottom, "Expected device height == 200, got %u.\n", ret_val);
4813 
4814     /* Check if CreateDeviceFromSurface creates a primary surface */
4815     hr = IDirectDraw_EnumSurfaces(ddraw, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
4816             NULL, &d3drm_surface, surface_callback);
4817     ok(hr == DD_OK, "Failed to enumerate surfaces (hr = %x).\n", hr);
4818     ok(d3drm_surface == NULL, "No primary surface should have enumerated (%p).\n", d3drm_surface);
4819 
4820     hr = IDirect3DRMDevice3_GetDirect3DDevice2(device3, &d3ddevice2);
4821     ok(hr == D3DRM_OK, "Cannot get IDirect3DDevice2 interface (hr = %x).\n", hr);
4822 
4823     hr = IDirect3DDevice2_GetRenderTarget(d3ddevice2, &d3drm_surface);
4824     ok(hr == DD_OK, "Cannot get surface to the render target (hr = %x).\n", hr);
4825     ok(surface == d3drm_surface, "Expected surface returned == %p, got %p.\n", surface, d3drm_surface);
4826 
4827     /* Check properties of attached depth surface */
4828     hr = IDirectDrawSurface_GetAttachedSurface(d3drm_surface, &caps, &ds);
4829     ok(hr == DD_OK, "Cannot get attached depth surface (hr = %x).\n", hr);
4830 
4831     memset(&desc, 0, sizeof(desc));
4832     desc.dwSize = sizeof(desc);
4833     hr = IDirectDrawSurface_GetSurfaceDesc(ds, &desc);
4834     ok(hr == DD_OK, "Cannot get z surface desc structure (hr = %x).\n", hr);
4835 
4836     use_sysmem_zbuffer = desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
4837     ok((desc.dwWidth == rc.right) && (desc.dwHeight == rc.bottom), "Expected surface dimensions = %u, %u, got %u, %u.\n",
4838             rc.right, rc.bottom, desc.dwWidth, desc.dwHeight);
4839     ok(desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER, "Expected caps containing %x, got %x.\n", DDSCAPS_ZBUFFER, desc.ddsCaps.dwCaps);
4840     expected_flags = DDSD_ZBUFFERBITDEPTH | DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH;
4841     ok(desc.dwFlags == expected_flags, "Expected %x for flags, got %x.\n", expected_flags, desc.dwFlags);
4842 
4843     IDirectDrawSurface_Release(ds);
4844     IDirect3DDevice2_Release(d3ddevice2);
4845     IDirectDrawSurface_Release(d3drm_surface);
4846     IDirect3DRMDevice3_Release(device3);
4847 
4848     ref3 = get_refcount((IUnknown *)d3drm1);
4849     ok(ref1 == ref3, "expected ref1 == ref3, got ref1 = %u, ref3 = %u.\n", ref1, ref3);
4850     ref3 = get_refcount((IUnknown *)d3drm3);
4851     ok(ref3 == ref2, "expected ref3 == ref2, got ref2 = %u , ref3 = %u.\n", ref2, ref3);
4852     surface_ref2 = get_refcount((IUnknown *)surface);
4853     ok(surface_ref2 == surface_ref1, "Expected surface_ref2 == surface_ref1, got surface_ref1 = %u, surface_ref2 = %u.\n",
4854             surface_ref1, surface_ref2);
4855     /* In version 3, d3drm will destroy all references of the depth surface it created internally. */
4856     hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &ds);
4857     todo_wine ok(hr == DDERR_NOTFOUND, "Expected hr == DDERR_NOTFOUND, got %x.\n", hr);
4858     if (SUCCEEDED(hr))
4859         IDirectDrawSurface_Release(ds);
4860     ref1 = IDirectDrawSurface_Release(surface);
4861     ok(ref1 == 0, "Expected Render target refcount == 0, got %u.\n", ref1);
4862 
4863     memset(&desc, 0, sizeof(desc));
4864     desc.dwSize = sizeof(desc);
4865     desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4866     desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
4867     desc.dwWidth = rc.right;
4868     desc.dwHeight = rc.bottom;
4869 
4870     hr = IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL);
4871     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4872 
4873     memset(&desc, 0, sizeof(desc));
4874     desc.dwSize = sizeof(desc);
4875     desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
4876     desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | (use_sysmem_zbuffer ? DDSCAPS_SYSTEMMEMORY : 0);
4877     desc.dwZBufferBitDepth = 16;
4878     desc.dwWidth = rc.right;
4879     desc.dwHeight = rc.bottom;
4880     hr = IDirectDraw_CreateSurface(ddraw, &desc, &ds, NULL);
4881     ok(hr == DD_OK, "Cannot create depth surface (hr = %x).\n", hr);
4882     hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
4883     ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
4884 
4885     hr = IDirect3DRM3_CreateDeviceFromSurface(d3drm3, &driver, ddraw, surface, D3DRMDEVICE_NOZBUFFER, &device3);
4886     ok(SUCCEEDED(hr), "Cannot create IDirect3DRMDevice3 interface (hr = %x).\n", hr);
4887 
4888     hr = IDirect3DRMDevice3_GetDirect3DDevice2(device3, &d3ddevice2);
4889     ok(hr == D3DRM_OK, "Cannot get IDirect3DDevice2 interface (hr = %x).\n", hr);
4890 
4891     hr = IDirect3DDevice2_GetRenderTarget(d3ddevice2, &d3drm_surface);
4892     ok(hr == DD_OK, "Cannot get surface to the render target (hr = %x).\n", hr);
4893     ok(surface == d3drm_surface, "Expected surface returned == %p, got %p.\n", surface, d3drm_surface);
4894 
4895     /* Check if depth surface matches the one we created  */
4896     hr = IDirectDrawSurface_GetAttachedSurface(d3drm_surface, &caps, &d3drm_ds);
4897     ok(hr == DD_OK, "Cannot get attached depth surface (hr = %x).\n", hr);
4898     ok(ds == d3drm_ds, "Expected depth surface (%p) == surface created internally (%p).\n", ds, d3drm_ds);
4899 
4900     IDirectDrawSurface_Release(d3drm_ds);
4901     IDirectDrawSurface_Release(d3drm_surface);
4902     IDirectDrawSurface_Release(ds);
4903     IDirect3DDevice2_Release(d3ddevice2);
4904     IDirect3DRMDevice3_Release(device3);
4905     hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &ds);
4906     ok(hr == DD_OK, "Cannot get attached depth surface (hr = %x).\n", hr);
4907     /* The render target still holds a reference to ds as the depth surface remains attached to it, so refcount will be 1*/
4908     ref1 = IDirectDrawSurface_Release(ds);
4909     ok(ref1 == 1, "Expected ref1 == 1, got %u.\n", ref1);
4910 
4911     /* What happens if we pass no flags and still attach our own depth surface? */
4912     hr = IDirect3DRM3_CreateDeviceFromSurface(d3drm3, &driver, ddraw, surface, 0, &device3);
4913     ok(SUCCEEDED(hr), "Cannot create IDirect3DRMDevice3 interface (hr = %x).\n", hr);
4914 
4915     hr = IDirect3DRMDevice3_GetDirect3DDevice2(device3, &d3ddevice2);
4916     ok(hr == D3DRM_OK, "Cannot get IDirect3DDevice2 interface (hr = %x).\n", hr);
4917 
4918     hr = IDirect3DDevice2_GetRenderTarget(d3ddevice2, &d3drm_surface);
4919     ok(hr == DD_OK, "Cannot get surface to the render target (hr = %x).\n", hr);
4920     ok(surface == d3drm_surface, "Expected surface returned == %p, got %p.\n", surface, d3drm_surface);
4921 
4922     /* Check if depth surface matches the one we created  */
4923     hr = IDirectDrawSurface_GetAttachedSurface(d3drm_surface, &caps, &d3drm_ds);
4924     ok(hr == DD_OK, "Cannot get attached depth surface (hr = %x).\n", hr);
4925     ok(ds == d3drm_ds, "Expected depth surface (%p) == surface created internally (%p).\n", ds, d3drm_ds);
4926 
4927     IDirectDrawSurface_Release(d3drm_ds);
4928     IDirectDrawSurface_Release(d3drm_surface);
4929     IDirect3DDevice2_Release(d3ddevice2);
4930     IDirect3DRMDevice3_Release(device3);
4931     hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &ds);
4932     ok(hr == DD_OK, "Cannot get attached depth surface (hr = %x).\n", hr);
4933     /*The render target still holds a reference to ds as the depth surface remains attached to it, so refcount will be 1*/
4934     ref1 = IDirectDrawSurface_Release(ds);
4935     ok(ref1 == 1, "Expected ref1 == 1, got %u.\n", ref1);
4936     ref1 = IDirectDrawSurface_Release(surface);
4937     ok(ref1 == 0, "Expected Render target refcount == 0, got %u.\n", ref1);
4938 
4939     memset(&desc, 0, sizeof(desc));
4940     desc.dwSize = sizeof(desc);
4941     desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4942     desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
4943     desc.dwWidth = rc.right;
4944     desc.dwHeight = rc.bottom;
4945 
4946     hr = IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL);
4947     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4948 
4949     /* What happens if we don't pass D3DRMDEVICE_NOZBUFFER and still not attach our own depth surface? */
4950     hr = IDirect3DRM3_CreateDeviceFromSurface(d3drm3, &driver, ddraw, surface, D3DRMDEVICE_NOZBUFFER, &device3);
4951     ok(SUCCEEDED(hr), "Cannot create IDirect3DRMDevice3 interface (hr = %x).\n", hr);
4952 
4953     hr = IDirect3DRMDevice3_GetDirect3DDevice2(device3, &d3ddevice2);
4954     ok(hr == D3DRM_OK, "Cannot get IDirect3DDevice2 interface (hr = %x).\n", hr);
4955 
4956     hr = IDirect3DDevice2_GetRenderTarget(d3ddevice2, &d3drm_surface);
4957     ok(hr == DD_OK, "Cannot get surface to the render target (hr = %x).\n", hr);
4958     ok(surface == d3drm_surface, "Expected surface returned == %p, got %p.\n", surface, d3drm_surface);
4959 
4960     /* Check if depth surface matches the one we created  */
4961     hr = IDirectDrawSurface_GetAttachedSurface(d3drm_surface, &caps, &d3drm_ds);
4962     ok(hr == DDERR_NOTFOUND, "Expected hr == DDERR_NOTFOUND, got %x).\n", hr);
4963     IDirectDrawSurface_Release(d3drm_surface);
4964 
4965     IDirect3DDevice2_Release(d3ddevice2);
4966     IDirect3DRMDevice3_Release(device3);
4967     ref1 = IDirectDrawSurface_Release(surface);
4968     ok(ref1 == 0, "Expected Render target refcount == 0, got %u.\n", ref1);
4969     IDirect3DRM3_Release(d3drm3);
4970     IDirect3DRM_Release(d3drm1);
4971     IDirectDraw_Release(ddraw);
4972     DestroyWindow(window);
4973 }
4974 
create_device1(IDirectDraw * ddraw,HWND window,IDirectDrawSurface ** ds)4975 static IDirect3DDevice *create_device1(IDirectDraw *ddraw, HWND window, IDirectDrawSurface **ds)
4976 {
4977     static const DWORD z_depths[] = { 32, 24, 16 };
4978     IDirectDrawSurface *surface;
4979     IDirect3DDevice *device = NULL;
4980     DDSURFACEDESC surface_desc;
4981     unsigned int i;
4982     HRESULT hr;
4983     RECT rc;
4984 
4985     GetClientRect(window, &rc);
4986     hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4987     ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4988 
4989     memset(&surface_desc, 0, sizeof(surface_desc));
4990     surface_desc.dwSize = sizeof(surface_desc);
4991     surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4992     surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
4993     surface_desc.dwWidth = rc.right;
4994     surface_desc.dwHeight = rc.bottom;
4995 
4996     hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
4997     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4998 
4999     /* We used to use EnumDevices() for this, but it seems
5000     * D3DDEVICEDESC.dwDeviceZBufferBitDepth only has a very casual
5001     * relationship with reality. */
5002     for (i = 0; i < ARRAY_SIZE(z_depths); ++i)
5003     {
5004         memset(&surface_desc, 0, sizeof(surface_desc));
5005         surface_desc.dwSize = sizeof(surface_desc);
5006         surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
5007         surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
5008         U2(surface_desc).dwZBufferBitDepth = z_depths[i];
5009         surface_desc.dwWidth = rc.right;
5010         surface_desc.dwHeight = rc.bottom;
5011         if (FAILED(IDirectDraw_CreateSurface(ddraw, &surface_desc, ds, NULL)))
5012             continue;
5013 
5014         hr = IDirectDrawSurface_AddAttachedSurface(surface, *ds);
5015         ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
5016         if (FAILED(hr))
5017         {
5018             IDirectDrawSurface_Release(*ds);
5019             continue;
5020         }
5021 
5022         if (SUCCEEDED(IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DHALDevice, (void **)&device)))
5023             break;
5024 
5025         IDirectDrawSurface_DeleteAttachedSurface(surface, 0, *ds);
5026         IDirectDrawSurface_Release(*ds);
5027         *ds = NULL;
5028     }
5029 
5030     IDirectDrawSurface_Release(surface);
5031     return device;
5032 }
5033 
test_create_device_from_d3d1(void)5034 static void test_create_device_from_d3d1(void)
5035 {
5036     IDirectDraw *ddraw1 = NULL, *temp_ddraw1;
5037     IDirect3D *d3d1 = NULL, *temp_d3d1;
5038     IDirect3DRM *d3drm1 = NULL;
5039     IDirect3DRMDevice *device1 = (IDirect3DRMDevice *)0xdeadbeef;
5040     IDirect3DRMDevice2 *device2;
5041     IDirect3DRMDevice3 *device3;
5042     IDirect3DDevice *d3ddevice1 = NULL, *d3drm_d3ddevice1 = NULL, *temp_d3ddevice1;
5043     IDirect3DDevice2 *d3ddevice2 = (IDirect3DDevice2 *)0xdeadbeef;
5044     IDirectDrawSurface *surface = NULL, *ds = NULL, *d3drm_ds = NULL;
5045     DWORD expected_flags, ret_val;
5046     DDSCAPS caps = { DDSCAPS_ZBUFFER };
5047     DDSURFACEDESC desc;
5048     RECT rc;
5049     HWND window;
5050     ULONG ref1, ref2, ref3, ref4, device_ref1, device_ref2, d3d_ref1, d3d_ref2;
5051     HRESULT hr;
5052 
5053     hr = DirectDrawCreate(NULL, &ddraw1, NULL);
5054     ok(hr == DD_OK, "Cannot get IDirectDraw interface (hr = %x).\n", hr);
5055 
5056     window = create_window();
5057     GetClientRect(window, &rc);
5058 
5059     hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirect3D, (void **)&d3d1);
5060     ok(hr == DD_OK, "Cannot get IDirect3D2 interface (hr = %x).\n", hr);
5061     d3d_ref1 = get_refcount((IUnknown *)d3d1);
5062 
5063     /* Create the immediate mode device */
5064     d3ddevice1 = create_device1(ddraw1, window, &ds);
5065     if (d3ddevice1 == NULL)
5066     {
5067         win_skip("Cannot create IM device, skipping tests.\n");
5068         IDirect3D_Release(d3d1);
5069         IDirectDraw_Release(ddraw1);
5070         return;
5071     }
5072     device_ref1 = get_refcount((IUnknown *)d3ddevice1);
5073 
5074     hr = Direct3DRMCreate(&d3drm1);
5075     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x).\n", hr);
5076     ref1 = get_refcount((IUnknown *)d3drm1);
5077 
5078     hr = IDirect3DRM_CreateDeviceFromD3D(d3drm1, NULL, d3ddevice1, &device1);
5079     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %x.\n", hr);
5080     ok(device1 == NULL, "Expected device returned == NULL, got %p.\n", device1);
5081     hr = IDirect3DRM_CreateDeviceFromD3D(d3drm1, d3d1, NULL, &device1);
5082     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %x.\n", hr);
5083     hr = IDirect3DRM_CreateDeviceFromD3D(d3drm1, d3d1, d3ddevice1, NULL);
5084     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %x.\n", hr);
5085 
5086     hr = IDirect3DRM_CreateDeviceFromD3D(d3drm1, d3d1, d3ddevice1, &device1);
5087     ok(hr == DD_OK, "Failed to create IDirect3DRMDevice interface (hr = %x)\n", hr);
5088     ref2 = get_refcount((IUnknown *)d3drm1);
5089     ok(ref2 > ref1, "expected ref2 > ref1, got ref1 = %u , ref2 = %u.\n", ref1, ref2);
5090     device_ref2 = get_refcount((IUnknown *)d3ddevice1);
5091     ok(device_ref2 > device_ref1, "Expected device_ref2 > device_ref1, got device_ref1 = %u, device_ref2 = %u.\n", device_ref1, device_ref2);
5092     d3d_ref2 = get_refcount((IUnknown *)d3d1);
5093     ok(d3d_ref2 > d3d_ref1, "Expected d3d_ref2 > d3d_ref1, got d3d_ref1 = %u, d3d_ref2 = %u.\n", d3d_ref1, d3d_ref2);
5094     ret_val = IDirect3DRMDevice_GetWidth(device1);
5095     ok(ret_val == rc.right, "Expected device width = 300, got %u.\n", ret_val);
5096     ret_val = IDirect3DRMDevice_GetHeight(device1);
5097     ok(ret_val == rc.bottom, "Expected device height == 200, got %u.\n", ret_val);
5098 
5099     hr = IDirect3DRMDevice_QueryInterface(device1, &IID_IDirect3DRMDevice2, (void **)&device2);
5100     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMDevice2 Interface (hr = %x).\n", hr);
5101     hr = IDirect3DRMDevice2_GetDirect3DDevice2(device2, &d3ddevice2);
5102     ok(SUCCEEDED(hr), "Expected hr == D3DRM_OK, got %#x.\n", hr);
5103     ok(d3ddevice2 == NULL, "Expected d3ddevice2 == NULL, got %p.\n", d3ddevice2);
5104     IDirect3DRMDevice2_Release(device2);
5105 
5106     d3ddevice2 = (IDirect3DDevice2 *)0xdeadbeef;
5107     hr = IDirect3DRMDevice_QueryInterface(device1, &IID_IDirect3DRMDevice3, (void **)&device3);
5108     ok(hr == DD_OK, "Cannot get IDirect3DRMDevice3 Interface (hr = %x).\n", hr);
5109     hr = IDirect3DRMDevice3_GetDirect3DDevice2(device3, &d3ddevice2);
5110     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
5111     ok(d3ddevice2 == NULL, "Expected d3ddevice2 == NULL, got %p.\n", d3ddevice2);
5112     IDirect3DRMDevice3_Release(device3);
5113 
5114     hr = IDirectDraw_EnumSurfaces(ddraw1, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
5115             NULL, &surface, surface_callback);
5116     ok(hr == DD_OK, "Failed to enumerate surfaces (hr = %x).\n", hr);
5117     ok(surface == NULL, "No primary surface should have enumerated (%p).\n", surface);
5118 
5119     hr = IDirect3DRMDevice_GetDirect3DDevice(device1, &d3drm_d3ddevice1);
5120     ok(hr == D3DRM_OK, "Cannot get IDirect3DDevice interface (hr = %x).\n", hr);
5121     ok(d3ddevice1 == d3drm_d3ddevice1, "Expected Immediate Mode device created == %p, got %p.\n", d3ddevice1, d3drm_d3ddevice1);
5122 
5123     /* Check properties of render target and depth surfaces */
5124     hr = IDirect3DDevice_QueryInterface(d3drm_d3ddevice1, &IID_IDirectDrawSurface, (void **)&surface);
5125     ok(hr == DD_OK, "Cannot get surface to the render target (hr = %x).\n", hr);
5126 
5127     memset(&desc, 0, sizeof(desc));
5128     desc.dwSize = sizeof(desc);
5129     hr = IDirectDrawSurface_GetSurfaceDesc(surface, &desc);
5130     ok(hr == DD_OK, "Cannot get surface desc structure (hr = %x).\n", hr);
5131 
5132     ok((desc.dwWidth == rc.right) && (desc.dwHeight == rc.bottom), "Expected surface dimensions = %u, %u, got %u, %u.\n",
5133             rc.right, rc.bottom, desc.dwWidth, desc.dwHeight);
5134     ok((desc.ddsCaps.dwCaps & (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE)) == (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE),
5135             "Expected caps containing %x, got %x.\n", DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE, desc.ddsCaps.dwCaps);
5136     expected_flags = DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH;
5137     ok(desc.dwFlags == expected_flags, "Expected %x for flags, got %x.\n", expected_flags, desc.dwFlags);
5138 
5139     hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &d3drm_ds);
5140     ok(hr == DD_OK, "Cannot get attached depth surface (hr = %x).\n", hr);
5141     ok(ds == d3drm_ds, "Expected depth surface (%p) == surface created internally (%p).\n", ds, d3drm_ds);
5142 
5143     desc.dwSize = sizeof(desc);
5144     hr = IDirectDrawSurface_GetSurfaceDesc(ds, &desc);
5145     ok(hr == DD_OK, "Cannot get z surface desc structure (hr = %x).\n", hr);
5146 
5147     ok((desc.dwWidth == rc.right) && (desc.dwHeight == rc.bottom), "Expected surface dimensions = %u, %u, got %u, %u.\n",
5148             rc.right, rc.bottom, desc.dwWidth, desc.dwHeight);
5149     ok((desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) == DDSCAPS_ZBUFFER, "Expected caps containing %x, got %x.\n", DDSCAPS_ZBUFFER, desc.ddsCaps.dwCaps);
5150     expected_flags = DDSD_ZBUFFERBITDEPTH | DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH;
5151     ok(desc.dwFlags == expected_flags, "Expected %x for flags, got %x.\n", expected_flags, desc.dwFlags);
5152 
5153     IDirectDrawSurface_Release(d3drm_ds);
5154     IDirectDrawSurface_Release(ds);
5155     IDirectDrawSurface_Release(surface);
5156     IDirect3DDevice_Release(d3drm_d3ddevice1);
5157     IDirect3DRMDevice_Release(device1);
5158     ref2 = get_refcount((IUnknown *)d3drm1);
5159     ok(ref1 == ref2, "expected ref1 == ref2, got ref1 = %u, ref2 = %u.\n", ref1, ref2);
5160     device_ref2 = get_refcount((IUnknown *)d3ddevice1);
5161     ok(device_ref2 == device_ref1, "Expected device_ref2 == device_ref1, got device_ref1 = %u, device_ref2 = %u.\n", device_ref1, device_ref2);
5162 
5163     /* InitFromD3D tests */
5164     hr = IDirect3DRM_CreateObject(d3drm1, &CLSID_CDirect3DRMDevice, NULL, &IID_IDirect3DRMDevice, (void **)&device1);
5165     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMDevice interface (hr = %#x).\n", hr);
5166 
5167     hr = IDirect3DRMDevice_InitFromD3D(device1, NULL, d3ddevice1);
5168     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
5169     hr = IDirect3DRMDevice_InitFromD3D(device1, d3d1, NULL);
5170     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
5171 
5172     hr = IDirect3DRMDevice_InitFromD3D(device1, d3d1, d3ddevice1);
5173     ok(SUCCEEDED(hr), "Failed to initialise IDirect3DRMDevice interface (hr = %#x)\n", hr);
5174     ref2 = get_refcount((IUnknown *)d3drm1);
5175     ok(ref2 > ref1, "expected ref2 > ref1, got ref1 = %u , ref2 = %u.\n", ref1, ref2);
5176     device_ref2 = get_refcount((IUnknown *)d3ddevice1);
5177     ok(device_ref2 > device_ref1, "Expected device_ref2 > device_ref1, got device_ref1 = %u, device_ref2 = %u.\n",
5178             device_ref1, device_ref2);
5179     d3d_ref2 = get_refcount((IUnknown *)d3d1);
5180     ok(d3d_ref2 > d3d_ref1, "Expected d3d_ref2 > d3d_ref1, got d3d_ref1 = %u, d3d_ref2 = %u.\n", d3d_ref1, d3d_ref2);
5181     ret_val = IDirect3DRMDevice_GetWidth(device1);
5182     ok(ret_val == rc.right, "Expected device width = 300, got %u.\n", ret_val);
5183     ret_val = IDirect3DRMDevice_GetHeight(device1);
5184     ok(ret_val == rc.bottom, "Expected device height == 200, got %u.\n", ret_val);
5185 
5186     hr = IDirect3DRMDevice_InitFromD3D(device1, d3d1, d3ddevice1);
5187     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
5188     ref3 = get_refcount((IUnknown *)d3drm1);
5189     ok(ref3 > ref1, "expected ref3 > ref1, got ref1 = %u , ref3 = %u.\n", ref1, ref3);
5190     ref3 = get_refcount((IUnknown *)d3ddevice1);
5191     ok(ref3 > device_ref2, "Expected ref3 > device_ref2, got ref3 = %u, device_ref2 = %u.\n", ref3, device_ref2);
5192     ref3 = get_refcount((IUnknown *)d3d1);
5193     ok(ref3 > d3d_ref2, "Expected ref3 > d3d_ref2, got ref3 = %u, d3d_ref2 = %u.\n", ref3, d3d_ref2);
5194     /* Release leaked references */
5195     while (IDirect3DRM_Release(d3drm1) > ref2);
5196     while (IDirect3DDevice_Release(d3ddevice1) > device_ref2);
5197     while (IDirect3D_Release(d3d1) > d3d_ref2);
5198 
5199     hr = DirectDrawCreate(NULL, &temp_ddraw1, NULL);
5200     ok(SUCCEEDED(hr), "Cannot get IDirectDraw interface (hr = %#x).\n", hr);
5201     ref4 = get_refcount((IUnknown *)temp_ddraw1);
5202 
5203     hr = IDirectDraw_QueryInterface(temp_ddraw1, &IID_IDirect3D, (void **)&temp_d3d1);
5204     ok(SUCCEEDED(hr), "Cannot get IDirect3D2 interface (hr = %#x).\n", hr);
5205     temp_d3ddevice1 = create_device1(temp_ddraw1, window, &surface);
5206     hr = IDirect3DRMDevice_InitFromD3D(device1, temp_d3d1, temp_d3ddevice1);
5207     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
5208     ref3 = get_refcount((IUnknown *)d3drm1);
5209     ok(ref3 > ref2, "expected ref3 > ref1, got ref1 = %u , ref3 = %u.\n", ref1, ref3);
5210     ref3 = get_refcount((IUnknown *)temp_d3ddevice1);
5211     ok(ref3 == device_ref2, "Expected ref3 == device_ref2, got ref3 = %u, device_ref2 = %u.\n", ref3, device_ref2);
5212     ref3 = get_refcount((IUnknown *)temp_d3d1);
5213     todo_wine ok(ref3 < d3d_ref2, "Expected ref3 < d3d_ref2, got ref3 = %u, d3d_ref2 = %u.\n", ref3, d3d_ref2);
5214     /* Release leaked references */
5215     while (IDirect3DRM_Release(d3drm1) > ref2);
5216     while (IDirect3DDevice_Release(temp_d3ddevice1) > 0);
5217     while (IDirect3D_Release(temp_d3d1) > ref4);
5218     IDirectDrawSurface_Release(surface);
5219     IDirectDraw_Release(temp_ddraw1);
5220 
5221     d3ddevice2 = (IDirect3DDevice2 *)0xdeadbeef;
5222     hr = IDirect3DRMDevice_QueryInterface(device1, &IID_IDirect3DRMDevice2, (void **)&device2);
5223     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMDevice2 Interface (hr = %x).\n", hr);
5224     hr = IDirect3DRMDevice2_GetDirect3DDevice2(device2, &d3ddevice2);
5225     ok(SUCCEEDED(hr), "Expected hr == D3DRM_OK, got %#x.\n", hr);
5226     ok(d3ddevice2 == NULL, "Expected d3ddevice2 == NULL, got %p.\n", d3ddevice2);
5227     IDirect3DRMDevice2_Release(device2);
5228 
5229     d3ddevice2 = (IDirect3DDevice2 *)0xdeadbeef;
5230     hr = IDirect3DRMDevice_QueryInterface(device1, &IID_IDirect3DRMDevice3, (void **)&device3);
5231     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMDevice3 Interface (hr = %#x).\n", hr);
5232     hr = IDirect3DRMDevice3_GetDirect3DDevice2(device3, &d3ddevice2);
5233     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
5234     ok(d3ddevice2 == NULL, "Expected d3ddevice2 == NULL, got %p.\n", d3ddevice2);
5235     IDirect3DRMDevice3_Release(device3);
5236 
5237     surface = NULL;
5238     hr = IDirectDraw_EnumSurfaces(ddraw1, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
5239             NULL, &surface, surface_callback);
5240     ok(SUCCEEDED(hr), "Failed to enumerate surfaces (hr = %#x).\n", hr);
5241     ok(surface == NULL, "No primary surface should have enumerated (%p).\n", surface);
5242 
5243     hr = IDirect3DRMDevice_GetDirect3DDevice(device1, &d3drm_d3ddevice1);
5244     ok(SUCCEEDED(hr), "Cannot get IDirect3DDevice interface (hr = %#x).\n", hr);
5245     ok(d3ddevice1 == d3drm_d3ddevice1, "Expected Immediate Mode device created == %p, got %p.\n",
5246             d3ddevice1, d3drm_d3ddevice1);
5247 
5248     /* Check properties of render target and depth surfaces */
5249     hr = IDirect3DDevice_QueryInterface(d3drm_d3ddevice1, &IID_IDirectDrawSurface, (void **)&surface);
5250     ok(SUCCEEDED(hr), "Cannot get surface to the render target (hr = %#x).\n", hr);
5251 
5252     memset(&desc, 0, sizeof(desc));
5253     desc.dwSize = sizeof(desc);
5254     hr = IDirectDrawSurface_GetSurfaceDesc(surface, &desc);
5255     ok(SUCCEEDED(hr), "Cannot get surface desc structure (hr = %#x).\n", hr);
5256 
5257     ok((desc.dwWidth == rc.right) && (desc.dwHeight == rc.bottom), "Expected surface dimensions = %u, %u, got %u, %u.\n",
5258             rc.right, rc.bottom, desc.dwWidth, desc.dwHeight);
5259     ok((desc.ddsCaps.dwCaps & (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE)) == (DDSCAPS_OFFSCREENPLAIN|DDSCAPS_3DDEVICE),
5260             "Expected caps containing %x, got %x.\n", DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE, desc.ddsCaps.dwCaps);
5261     expected_flags = DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH;
5262     ok(desc.dwFlags == expected_flags, "Expected %x for flags, got %x.\n", expected_flags, desc.dwFlags);
5263 
5264     hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &d3drm_ds);
5265     ok(SUCCEEDED(hr), "Cannot get attached depth surface (hr = %x).\n", hr);
5266     ok(ds == d3drm_ds, "Expected depth surface (%p) == surface created internally (%p).\n", ds, d3drm_ds);
5267 
5268     desc.dwSize = sizeof(desc);
5269     hr = IDirectDrawSurface_GetSurfaceDesc(ds, &desc);
5270     ok(SUCCEEDED(hr), "Cannot get z surface desc structure (hr = %#x).\n", hr);
5271 
5272     ok((desc.dwWidth == rc.right) && (desc.dwHeight == rc.bottom), "Expected surface dimensions = %u, %u, got %u, %u.\n",
5273             rc.right, rc.bottom, desc.dwWidth, desc.dwHeight);
5274     ok((desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) == DDSCAPS_ZBUFFER, "Expected caps containing %#x, got %#x.\n",
5275             DDSCAPS_ZBUFFER, desc.ddsCaps.dwCaps);
5276     expected_flags = DDSD_ZBUFFERBITDEPTH | DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH;
5277     ok(desc.dwFlags == expected_flags, "Expected %#x for flags, got %#x.\n", expected_flags, desc.dwFlags);
5278 
5279     IDirectDrawSurface_Release(d3drm_ds);
5280     IDirectDrawSurface_Release(ds);
5281     IDirectDrawSurface_Release(surface);
5282     IDirect3DDevice_Release(d3drm_d3ddevice1);
5283     IDirect3DRMDevice_Release(device1);
5284     ref2 = get_refcount((IUnknown *)d3drm1);
5285     ok(ref1 == ref2, "expected ref1 == ref2, got ref1 = %u, ref2 = %u.\n", ref1, ref2);
5286     device_ref2 = get_refcount((IUnknown *)d3ddevice1);
5287     ok(device_ref2 == device_ref1, "Expected device_ref2 == device_ref1, got device_ref1 = %u, device_ref2 = %u.\n",
5288             device_ref1, device_ref2);
5289     d3d_ref2 = get_refcount((IUnknown *)d3d1);
5290     todo_wine ok(d3d_ref2 > d3d_ref1, "Expected d3d_ref2 > d3d_ref1, got d3d_ref1 = %u, d3d_ref2 = %u.\n", d3d_ref1,
5291             d3d_ref2);
5292 
5293     IDirect3DRM_Release(d3drm1);
5294     IDirect3DDevice_Release(d3ddevice1);
5295     IDirect3D_Release(d3d1);
5296     IDirectDraw_Release(ddraw1);
5297     DestroyWindow(window);
5298 }
5299 
create_device2(IDirectDraw2 * ddraw,HWND window,IDirectDrawSurface ** ds)5300 static IDirect3DDevice2 *create_device2(IDirectDraw2 *ddraw, HWND window, IDirectDrawSurface **ds)
5301 {
5302     static const DWORD z_depths[] = { 32, 24, 16 };
5303     IDirectDrawSurface *surface;
5304     IDirect3DDevice2 *device = NULL;
5305     DDSURFACEDESC surface_desc;
5306     IDirect3D2 *d3d;
5307     unsigned int i;
5308     HRESULT hr;
5309     RECT rc;
5310 
5311     GetClientRect(window, &rc);
5312     hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5313     ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5314 
5315     memset(&surface_desc, 0, sizeof(surface_desc));
5316     surface_desc.dwSize = sizeof(surface_desc);
5317     surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5318     surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
5319     surface_desc.dwWidth = rc.right;
5320     surface_desc.dwHeight = rc.bottom;
5321 
5322     hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5323     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5324 
5325     hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d);
5326     if (FAILED(hr))
5327     {
5328         IDirectDrawSurface_Release(surface);
5329         *ds = NULL;
5330         return NULL;
5331     }
5332 
5333     /* We used to use EnumDevices() for this, but it seems
5334     * D3DDEVICEDESC.dwDeviceZBufferBitDepth only has a very casual
5335     * relationship with reality. */
5336     for (i = 0; i < ARRAY_SIZE(z_depths); ++i)
5337     {
5338         memset(&surface_desc, 0, sizeof(surface_desc));
5339         surface_desc.dwSize = sizeof(surface_desc);
5340         surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
5341         surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
5342         U2(surface_desc).dwZBufferBitDepth = z_depths[i];
5343         surface_desc.dwWidth = rc.right;
5344         surface_desc.dwHeight = rc.bottom;
5345         if (FAILED(IDirectDraw2_CreateSurface(ddraw, &surface_desc, ds, NULL)))
5346             continue;
5347 
5348         hr = IDirectDrawSurface_AddAttachedSurface(surface, *ds);
5349         ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
5350         if (FAILED(hr))
5351         {
5352             IDirectDrawSurface_Release(*ds);
5353             continue;
5354         }
5355 
5356         if (SUCCEEDED(IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device)))
5357             break;
5358 
5359         IDirectDrawSurface_DeleteAttachedSurface(surface, 0, *ds);
5360         IDirectDrawSurface_Release(*ds);
5361         *ds = NULL;
5362     }
5363 
5364     IDirect3D2_Release(d3d);
5365     IDirectDrawSurface_Release(surface);
5366     return device;
5367 }
5368 
test_create_device_from_d3d2(void)5369 static void test_create_device_from_d3d2(void)
5370 {
5371     IDirectDraw *ddraw1 = NULL, *temp_ddraw1;
5372     IDirectDraw2 *ddraw2 = NULL, *temp_ddraw2;
5373     IDirect3D* d3d1;
5374     IDirect3D2 *d3d2 = NULL, *temp_d3d2;
5375     IDirect3DRM *d3drm1 = NULL;
5376     IDirect3DRM2 *d3drm2 = NULL;
5377     IDirect3DRMDevice *device1;
5378     IDirect3DRMDevice2 *device2 = (IDirect3DRMDevice2 *)0xdeadbeef;
5379     IDirect3DDevice *d3ddevice1;
5380     IDirect3DDevice2 *d3ddevice2 = NULL, *d3drm_d3ddevice2 = NULL, *temp_d3ddevice2;
5381     IDirectDrawSurface *surface = NULL, *ds = NULL, *d3drm_ds = NULL;
5382     DWORD expected_flags, ret_val;
5383     DDSCAPS caps = { DDSCAPS_ZBUFFER };
5384     DDSURFACEDESC desc;
5385     RECT rc;
5386     HWND window;
5387     ULONG ref1, ref2, ref3, ref4, ref5, device_ref1, device_ref2, d3d_ref1, d3d_ref2;
5388     HRESULT hr;
5389 
5390     hr = DirectDrawCreate(NULL, &ddraw1, NULL);
5391     ok(hr == DD_OK, "Cannot get IDirectDraw interface (hr = %x).\n", hr);
5392 
5393     window = create_window();
5394     GetClientRect(window, &rc);
5395 
5396     hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirect3D2, (void **)&d3d2);
5397     ok(hr == DD_OK, "Cannot get IDirect3D2 interface (hr = %x).\n", hr);
5398     hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw2, (void **)&ddraw2);
5399     ok(hr == DD_OK, "Cannot get IDirectDraw2 interface (hr = %x).\n", hr);
5400     d3d_ref1 = get_refcount((IUnknown *)d3d2);
5401 
5402     /* Create the immediate mode device */
5403     d3ddevice2 = create_device2(ddraw2, window, &ds);
5404     if (d3ddevice2 == NULL)
5405     {
5406         win_skip("Cannot create IM device, skipping tests.\n");
5407         IDirect3D2_Release(d3d2);
5408         IDirectDraw2_Release(ddraw2);
5409         IDirectDraw_Release(ddraw1);
5410         return;
5411     }
5412     device_ref1 = get_refcount((IUnknown *)d3ddevice2);
5413 
5414     hr = Direct3DRMCreate(&d3drm1);
5415     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x).\n", hr);
5416     ref1 = get_refcount((IUnknown *)d3drm1);
5417 
5418     hr = IDirect3DRM_QueryInterface(d3drm1, &IID_IDirect3DRM2, (void **)&d3drm2);
5419     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM2 interface (hr = %x).\n", hr);
5420     ref2 = get_refcount((IUnknown *)d3drm2);
5421 
5422     hr = IDirect3DRM2_CreateDeviceFromD3D(d3drm2, NULL, d3ddevice2, &device2);
5423     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %x.\n", hr);
5424     ok(device2 == NULL, "Expected device returned == NULL, got %p.\n", device2);
5425     hr = IDirect3DRM2_CreateDeviceFromD3D(d3drm2, d3d2, NULL, &device2);
5426     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %x.\n", hr);
5427     hr = IDirect3DRM2_CreateDeviceFromD3D(d3drm2, d3d2, d3ddevice2, NULL);
5428     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %x.\n", hr);
5429 
5430     hr = IDirect3DRM2_CreateDeviceFromD3D(d3drm2, d3d2, d3ddevice2, &device2);
5431     ok(hr == DD_OK, "Failed to create IDirect3DRMDevice2 interface (hr = %x)\n", hr);
5432     ref3 = get_refcount((IUnknown *)d3drm1);
5433     ok(ref3 > ref1, "expected ref3 > ref1, got ref1 = %u , ref3 = %u.\n", ref1, ref3);
5434     ref3 = get_refcount((IUnknown *)d3drm2);
5435     ok(ref3 == ref2, "expected ref3 == ref2, got ref2 = %u , ref3 = %u.\n", ref2, ref3);
5436     device_ref2 = get_refcount((IUnknown *)d3ddevice2);
5437     ok(device_ref2 > device_ref1, "Expected device_ref2 > device_ref1, got device_ref1 = %u, device_ref2 = %u.\n", device_ref1, device_ref2);
5438     d3d_ref2 = get_refcount((IUnknown *)d3d2);
5439     ok(d3d_ref2 > d3d_ref1, "Expected d3d_ref2 > d3d_ref1, got d3d_ref1 = %u, d3d_ref2 = %u.\n", d3d_ref1, d3d_ref2);
5440     ret_val = IDirect3DRMDevice2_GetWidth(device2);
5441     ok(ret_val == rc.right, "Expected device width = 300, got %u.\n", ret_val);
5442     ret_val = IDirect3DRMDevice2_GetHeight(device2);
5443     ok(ret_val == rc.bottom, "Expected device height == 200, got %u.\n", ret_val);
5444 
5445     hr = IDirectDraw_EnumSurfaces(ddraw1, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
5446             NULL, &surface, surface_callback);
5447     ok(hr == DD_OK, "Failed to enumerate surfaces (hr = %x).\n", hr);
5448     ok(surface == NULL, "No primary surface should have enumerated (%p).\n", surface);
5449 
5450     hr = IDirect3DRMDevice2_GetDirect3DDevice2(device2, &d3drm_d3ddevice2);
5451     ok(hr == D3DRM_OK, "Cannot get IDirect3DDevice2 interface (hr = %x).\n", hr);
5452     ok(d3ddevice2 == d3drm_d3ddevice2, "Expected Immediate Mode device created == %p, got %p.\n", d3ddevice2, d3drm_d3ddevice2);
5453 
5454     /* Check properties of render target and depth surfaces */
5455     hr = IDirect3DDevice2_GetRenderTarget(d3drm_d3ddevice2, &surface);
5456     ok(hr == DD_OK, "Cannot get surface to the render target (hr = %x).\n", hr);
5457 
5458     memset(&desc, 0, sizeof(desc));
5459     desc.dwSize = sizeof(desc);
5460     hr = IDirectDrawSurface_GetSurfaceDesc(surface, &desc);
5461     ok(hr == DD_OK, "Cannot get surface desc structure (hr = %x).\n", hr);
5462 
5463     ok((desc.dwWidth == rc.right) && (desc.dwHeight == rc.bottom), "Expected surface dimensions = %u, %u, got %u, %u.\n",
5464             rc.right, rc.bottom, desc.dwWidth, desc.dwHeight);
5465     ok((desc.ddsCaps.dwCaps & (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE)) == (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE),
5466             "Expected caps containing %x, got %x.\n", DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE, desc.ddsCaps.dwCaps);
5467     expected_flags = DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH;
5468     ok(desc.dwFlags == expected_flags, "Expected %x for flags, got %x.\n", expected_flags, desc.dwFlags);
5469 
5470     hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &d3drm_ds);
5471     ok(hr == DD_OK, "Cannot get attached depth surface (hr = %x).\n", hr);
5472     ok(ds == d3drm_ds, "Expected depth surface (%p) == surface created internally (%p).\n", ds, d3drm_ds);
5473 
5474     desc.dwSize = sizeof(desc);
5475     hr = IDirectDrawSurface_GetSurfaceDesc(ds, &desc);
5476     ok(hr == DD_OK, "Cannot get z surface desc structure (hr = %x).\n", hr);
5477 
5478     ok((desc.dwWidth == rc.right) && (desc.dwHeight == rc.bottom), "Expected surface dimensions = %u, %u, got %u, %u.\n",
5479             rc.right, rc.bottom, desc.dwWidth, desc.dwHeight);
5480     ok((desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) == DDSCAPS_ZBUFFER, "Expected caps containing %x, got %x.\n", DDSCAPS_ZBUFFER, desc.ddsCaps.dwCaps);
5481     expected_flags = DDSD_ZBUFFERBITDEPTH | DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH;
5482     ok(desc.dwFlags == expected_flags, "Expected %x for flags, got %x.\n", expected_flags, desc.dwFlags);
5483 
5484     IDirectDrawSurface_Release(d3drm_ds);
5485     IDirectDrawSurface_Release(ds);
5486     IDirectDrawSurface_Release(surface);
5487     IDirect3DDevice2_Release(d3drm_d3ddevice2);
5488     IDirect3DRMDevice2_Release(device2);
5489     ref3 = get_refcount((IUnknown *)d3drm1);
5490     ok(ref1 == ref3, "expected ref1 == ref3, got ref1 = %u, ref3 = %u.\n", ref1, ref3);
5491     ref3 = get_refcount((IUnknown *)d3drm2);
5492     ok(ref3 == ref2, "expected ref3 == ref2, got ref2 = %u , ref3 = %u.\n", ref2, ref3);
5493     device_ref2 = get_refcount((IUnknown *)d3ddevice2);
5494     ok(device_ref2 == device_ref1, "Expected device_ref2 == device_ref1, got device_ref1 = %u, device_ref2 = %u.\n", device_ref1, device_ref2);
5495     d3d_ref2 = get_refcount((IUnknown *)d3d2);
5496     ok(d3d_ref2 == d3d_ref1, "Expected d3d_ref2 == d3d_ref1, got d3d_ref1 = %u, d3d_ref2 = %u.\n", d3d_ref1, d3d_ref2);
5497 
5498     /* InitFromD3D tests */
5499     hr = IDirect3DRM2_CreateObject(d3drm2, &CLSID_CDirect3DRMDevice, NULL, &IID_IDirect3DRMDevice2, (void **)&device2);
5500     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMDevice2 interface (hr = %#x).\n", hr);
5501 
5502     hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirect3D, (void **)&d3d1);
5503     ok(SUCCEEDED(hr), "Cannot get IDirect3D interface (hr = %x).\n", hr);
5504     if (SUCCEEDED(hr = IDirect3DDevice2_QueryInterface(d3ddevice2, &IID_IDirect3DDevice, (void **)&d3ddevice1)))
5505     {
5506         hr = IDirect3DRMDevice2_InitFromD3D(device2, d3d1, d3ddevice1);
5507         ok(hr == E_NOINTERFACE, "Expected hr == E_NOINTERFACE, got %#x.\n", hr);
5508         hr = IDirect3DRMDevice2_InitFromD3D(device2, NULL, d3ddevice1);
5509         ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
5510         hr = IDirect3DRMDevice2_InitFromD3D(device2, d3d1, NULL);
5511         ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
5512         hr = IDirect3DRMDevice2_QueryInterface(device2, &IID_IDirect3DRMDevice, (void **)&device1);
5513         ok(SUCCEEDED(hr), "Cannot obtain IDirect3DRMDevice interface (hr = %#x).\n", hr);
5514         hr = IDirect3DRMDevice_InitFromD3D(device1, d3d1, d3ddevice1);
5515         todo_wine ok(hr == E_NOINTERFACE, "Expected hr == E_NOINTERFACE, got %#x.\n", hr);
5516         IDirect3DRMDevice_Release(device1);
5517         if (SUCCEEDED(hr))
5518         {
5519             IDirect3DRMDevice_Release(device1);
5520             hr = IDirect3DRM2_CreateObject(d3drm2, &CLSID_CDirect3DRMDevice, NULL, &IID_IDirect3DRMDevice2,
5521                     (void **)&device2);
5522             ok(SUCCEEDED(hr), "Cannot get IDirect3DRMDevice2 interface (hr = %#x).\n", hr);
5523         }
5524     }
5525     IDirect3D_Release(d3d1);
5526     IDirect3DDevice_Release(d3ddevice1);
5527 
5528     hr = IDirect3DRMDevice2_InitFromD3D2(device2, NULL, d3ddevice2);
5529     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
5530     hr = IDirect3DRMDevice2_InitFromD3D2(device2, d3d2, NULL);
5531     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
5532 
5533     hr = IDirect3DRMDevice2_InitFromD3D2(device2, d3d2, d3ddevice2);
5534     ok(SUCCEEDED(hr), "Failed to initialise IDirect3DRMDevice2 interface (hr = %#x)\n", hr);
5535     ref4 = get_refcount((IUnknown *)d3drm1);
5536     ok(ref4 > ref1, "Expected ref4 > ref1, got ref1 = %u , ref4 = %u.\n", ref1, ref4);
5537     device_ref2 = get_refcount((IUnknown *)d3ddevice2);
5538     ok(device_ref2 > device_ref1, "Expected device_ref2 > device_ref1, got device_ref1 = %u, device_ref2 = %u.\n",
5539             device_ref1, device_ref2);
5540     d3d_ref2 = get_refcount((IUnknown *)d3d2);
5541     ok(d3d_ref2 > d3d_ref1, "Expected d3d_ref2 > d3d_ref1, got d3d_ref1 = %u, d3d_ref2 = %u.\n", d3d_ref1, d3d_ref2);
5542     ret_val = IDirect3DRMDevice2_GetWidth(device2);
5543     ok(ret_val == rc.right, "Expected device width = 300, got %u.\n", ret_val);
5544     ret_val = IDirect3DRMDevice2_GetHeight(device2);
5545     ok(ret_val == rc.bottom, "Expected device height == 200, got %u.\n", ret_val);
5546 
5547     hr = IDirect3DRMDevice2_InitFromD3D2(device2, d3d2, d3ddevice2);
5548     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
5549     ref3 = get_refcount((IUnknown *)d3drm1);
5550     ok(ref3 > ref1, "expected ref3 > ref1, got ref1 = %u , ref3 = %u.\n", ref1, ref3);
5551     ref3 = get_refcount((IUnknown *)d3ddevice2);
5552     ok(ref3 > device_ref2, "Expected ref3 > device_ref2, got ref3 = %u, device_ref2 = %u.\n", ref3, device_ref2);
5553     ref3 = get_refcount((IUnknown *)d3d2);
5554     ok(ref3 > d3d_ref2, "Expected ref3 > d3d_ref2, got ref3 = %u, d3d_ref2 = %u.\n", ref3, d3d_ref2);
5555     /* Release leaked references */
5556     while (IDirect3DRM_Release(d3drm1) > ref4);
5557     while (IDirect3DDevice2_Release(d3ddevice2) > device_ref2);
5558     while (IDirect3D2_Release(d3d2) > d3d_ref2);
5559 
5560     hr = DirectDrawCreate(NULL, &temp_ddraw1, NULL);
5561     ok(SUCCEEDED(hr), "Cannot get IDirectDraw interface (hr = %#x).\n", hr);
5562     hr = IDirectDraw_QueryInterface(temp_ddraw1, &IID_IDirect3D2, (void **)&temp_d3d2);
5563     ok(SUCCEEDED(hr), "Cannot get IDirect3D2 interface (hr = %#x).\n", hr);
5564     ref5 = get_refcount((IUnknown *)temp_d3d2);
5565 
5566     hr = IDirectDraw_QueryInterface(temp_ddraw1, &IID_IDirectDraw2, (void **)&temp_ddraw2);
5567     ok(SUCCEEDED(hr), "Cannot get IDirectDraw2 interface (hr = %#x).\n", hr);
5568 
5569     temp_d3ddevice2 = create_device2(temp_ddraw2, window, &surface);
5570     hr = IDirect3DRMDevice2_InitFromD3D2(device2, temp_d3d2, temp_d3ddevice2);
5571     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
5572     ref3 = get_refcount((IUnknown *)d3drm1);
5573     ok(ref3 > ref4, "expected ref3 > ref4, got ref3 = %u , ref4 = %u.\n", ref3, ref4);
5574     ref3 = get_refcount((IUnknown *)temp_d3ddevice2);
5575     ok(ref3 == device_ref2, "Expected ref3 == device_ref2, got ref3 = %u, device_ref2 = %u.\n", ref3, device_ref2);
5576     ref3 = get_refcount((IUnknown *)temp_d3d2);
5577     ok(ref3 == d3d_ref2, "Expected ref3 == d3d_ref2, got ref3 = %u, d3d_ref2 = %u.\n", ref3, d3d_ref2);
5578     /* Release leaked references */
5579     while (IDirect3DRM_Release(d3drm1) > ref4);
5580     while (IDirect3DDevice2_Release(temp_d3ddevice2) > 0);
5581     while (IDirect3D2_Release(temp_d3d2) >= ref5);
5582     IDirectDrawSurface_Release(surface);
5583     IDirectDraw2_Release(temp_ddraw2);
5584     IDirectDraw_Release(temp_ddraw1);
5585 
5586     surface = NULL;
5587     hr = IDirectDraw_EnumSurfaces(ddraw1, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
5588             NULL, &surface, surface_callback);
5589     ok(SUCCEEDED(hr), "Failed to enumerate surfaces (hr = %#x).\n", hr);
5590     ok(surface == NULL, "No primary surface should have enumerated (%p).\n", surface);
5591 
5592     hr = IDirect3DRMDevice2_GetDirect3DDevice2(device2, &d3drm_d3ddevice2);
5593     ok(SUCCEEDED(hr), "Cannot get IDirect3DDevice2 interface (hr = %#x).\n", hr);
5594     ok(d3ddevice2 == d3drm_d3ddevice2, "Expected Immediate Mode device created == %p, got %p.\n", d3ddevice2,
5595             d3drm_d3ddevice2);
5596 
5597     /* Check properties of render target and depth surfaces */
5598     hr = IDirect3DDevice2_GetRenderTarget(d3drm_d3ddevice2, &surface);
5599     ok(SUCCEEDED(hr), "Cannot get surface to the render target (hr = %#x).\n", hr);
5600 
5601     memset(&desc, 0, sizeof(desc));
5602     desc.dwSize = sizeof(desc);
5603     hr = IDirectDrawSurface_GetSurfaceDesc(surface, &desc);
5604     ok(SUCCEEDED(hr), "Cannot get surface desc structure (hr = %#x).\n", hr);
5605 
5606     ok((desc.dwWidth == rc.right) && (desc.dwHeight == rc.bottom), "Expected surface dimensions = %u, %u, got %u, %u.\n",
5607             rc.right, rc.bottom, desc.dwWidth, desc.dwHeight);
5608     ok((desc.ddsCaps.dwCaps & (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE)) == (DDSCAPS_OFFSCREENPLAIN|DDSCAPS_3DDEVICE),
5609             "Expected caps containing %#x, got %#x.\n", DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE, desc.ddsCaps.dwCaps);
5610     expected_flags = DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH;
5611     ok(desc.dwFlags == expected_flags, "Expected %#x for flags, got %#x.\n", expected_flags, desc.dwFlags);
5612 
5613     hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &d3drm_ds);
5614     ok(SUCCEEDED(hr), "Cannot get attached depth surface (hr = %x).\n", hr);
5615     ok(ds == d3drm_ds, "Expected depth surface (%p) == surface created internally (%p).\n", ds, d3drm_ds);
5616 
5617     desc.dwSize = sizeof(desc);
5618     hr = IDirectDrawSurface_GetSurfaceDesc(ds, &desc);
5619     ok(SUCCEEDED(hr), "Cannot get z surface desc structure (hr = %x).\n", hr);
5620 
5621     ok((desc.dwWidth == rc.right) && (desc.dwHeight == rc.bottom), "Expected surface dimensions = %u, %u, got %u, %u.\n",
5622             rc.right, rc.bottom, desc.dwWidth, desc.dwHeight);
5623     ok((desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) == DDSCAPS_ZBUFFER, "Expected caps containing %#x, got %#x.\n",
5624             DDSCAPS_ZBUFFER, desc.ddsCaps.dwCaps);
5625     expected_flags = DDSD_ZBUFFERBITDEPTH | DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH;
5626     ok(desc.dwFlags == expected_flags, "Expected %#x for flags, got %#x.\n", expected_flags, desc.dwFlags);
5627 
5628     IDirectDrawSurface_Release(d3drm_ds);
5629     IDirectDrawSurface_Release(ds);
5630     IDirectDrawSurface_Release(surface);
5631     IDirect3DDevice2_Release(d3drm_d3ddevice2);
5632     IDirect3DRMDevice2_Release(device2);
5633     ref3 = get_refcount((IUnknown *)d3drm1);
5634     ok(ref1 == ref3, "Expected ref1 == ref3, got ref1 = %u, ref3 = %u.\n", ref1, ref3);
5635     ref3 = get_refcount((IUnknown *)d3drm2);
5636     ok(ref3 == ref2, "Expected ref3 == ref2, got ref2 = %u , ref3 = %u.\n", ref2, ref3);
5637     device_ref2 = get_refcount((IUnknown *)d3ddevice2);
5638     ok(device_ref2 == device_ref1, "Expected device_ref2 == device_ref1, got device_ref1 = %u, device_ref2 = %u.\n",
5639             device_ref1, device_ref2);
5640     d3d_ref2 = get_refcount((IUnknown *)d3d2);
5641     ok(d3d_ref2 == d3d_ref1, "Expected d3d_ref2 == d3d_ref1, got d3d_ref1 = %u, d3d_ref2 = %u.\n", d3d_ref1, d3d_ref2);
5642 
5643     IDirect3DRM2_Release(d3drm2);
5644     IDirect3DRM_Release(d3drm1);
5645     IDirect3DDevice2_Release(d3ddevice2);
5646     IDirect3D2_Release(d3d2);
5647     IDirectDraw2_Release(ddraw2);
5648     IDirectDraw_Release(ddraw1);
5649     DestroyWindow(window);
5650 }
5651 
test_create_device_from_d3d3(void)5652 static void test_create_device_from_d3d3(void)
5653 {
5654     IDirectDraw *ddraw1 = NULL, *temp_ddraw1;
5655     IDirectDraw2 *ddraw2 = NULL, *temp_ddraw2;
5656     IDirect3D *d3d1;
5657     IDirect3D2 *d3d2 = NULL, *temp_d3d2;
5658     IDirect3DRM *d3drm1 = NULL;
5659     IDirect3DRM3 *d3drm3 = NULL;
5660     IDirect3DRMDevice *device1;
5661     IDirect3DRMDevice3 *device3 = (IDirect3DRMDevice3 *)0xdeadbeef;
5662     IDirect3DDevice *d3ddevice1;
5663     IDirect3DDevice2 *d3ddevice2 = NULL, *d3drm_d3ddevice2 = NULL, *temp_d3ddevice2;
5664     IDirectDrawSurface *surface = NULL, *ds = NULL, *d3drm_ds = NULL;
5665     DWORD expected_flags, ret_val;
5666     DDSCAPS caps = { DDSCAPS_ZBUFFER };
5667     DDSURFACEDESC desc;
5668     RECT rc;
5669     HWND window;
5670     ULONG ref1, ref2, ref3, ref4, ref5, device_ref1, device_ref2, d3d_ref1, d3d_ref2;
5671     HRESULT hr;
5672 
5673     hr = DirectDrawCreate(NULL, &ddraw1, NULL);
5674     ok(hr == DD_OK, "Cannot get IDirectDraw interface (hr = %x).\n", hr);
5675 
5676     window = create_window();
5677     GetClientRect(window, &rc);
5678 
5679     hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirect3D2, (void **)&d3d2);
5680     ok(hr == DD_OK, "Cannot get IDirect3D2 interface (hr = %x).\n", hr);
5681     hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw2, (void **)&ddraw2);
5682     ok(hr == DD_OK, "Cannot get IDirectDraw2 interface (hr = %x).\n", hr);
5683     d3d_ref1 = get_refcount((IUnknown *)d3d2);
5684 
5685     /* Create the immediate mode device */
5686     d3ddevice2 = create_device2(ddraw2, window, &ds);
5687     if (d3ddevice2 == NULL)
5688     {
5689         win_skip("Cannot create IM device, skipping tests.\n");
5690         IDirect3D2_Release(d3d2);
5691         IDirectDraw2_Release(ddraw2);
5692         IDirectDraw_Release(ddraw1);
5693         return;
5694     }
5695     device_ref1 = get_refcount((IUnknown *)d3ddevice2);
5696 
5697     hr = Direct3DRMCreate(&d3drm1);
5698     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x).\n", hr);
5699     ref1 = get_refcount((IUnknown *)d3drm1);
5700 
5701     hr = IDirect3DRM_QueryInterface(d3drm1, &IID_IDirect3DRM3, (void **)&d3drm3);
5702     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM3 interface (hr = %x).\n", hr);
5703     ref2 = get_refcount((IUnknown *)d3drm3);
5704 
5705     hr = IDirect3DRM3_CreateDeviceFromD3D(d3drm3, NULL, d3ddevice2, &device3);
5706     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %x.\n", hr);
5707     ok(device3 == NULL, "Expected device returned == NULL, got %p.\n", device3);
5708     hr = IDirect3DRM3_CreateDeviceFromD3D(d3drm3, d3d2, NULL, &device3);
5709     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %x.\n", hr);
5710     hr = IDirect3DRM3_CreateDeviceFromD3D(d3drm3, d3d2, d3ddevice2, NULL);
5711     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %x.\n", hr);
5712 
5713     hr = IDirect3DRM3_CreateDeviceFromD3D(d3drm3, d3d2, d3ddevice2, &device3);
5714     ok(hr == DD_OK, "Failed to create IDirect3DRMDevice3 interface (hr = %x)\n", hr);
5715     ref3 = get_refcount((IUnknown *)d3drm1);
5716     ok(ref3 > ref1, "expected ref3 > ref1, got ref1 = %u , ref3 = %u.\n", ref1, ref3);
5717     ref3 = get_refcount((IUnknown *)d3drm3);
5718     ok(ref3 == ref2, "expected ref3 == ref2, got ref2 = %u , ref3 = %u.\n", ref2, ref3);
5719     device_ref2 = get_refcount((IUnknown *)d3ddevice2);
5720     ok(device_ref2 > device_ref1, "Expected device_ref2 > device_ref1, got device_ref1 = %u, device_ref2 = %u.\n", device_ref1, device_ref2);
5721     ret_val = IDirect3DRMDevice3_GetWidth(device3);
5722     ok(ret_val == rc.right, "Expected device width = 300, got %u.\n", ret_val);
5723     ret_val = IDirect3DRMDevice3_GetHeight(device3);
5724     ok(ret_val == rc.bottom, "Expected device height == 200, got %u.\n", ret_val);
5725 
5726     hr = IDirectDraw_EnumSurfaces(ddraw1, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
5727             NULL, &surface, surface_callback);
5728     ok(hr == DD_OK, "Failed to enumerate surfaces (hr = %x).\n", hr);
5729     ok(surface == NULL, "No primary surface should have enumerated (%p).\n", surface);
5730 
5731     hr = IDirect3DRMDevice3_GetDirect3DDevice2(device3, &d3drm_d3ddevice2);
5732     ok(hr == D3DRM_OK, "Cannot get IDirect3DDevice2 interface (hr = %x).\n", hr);
5733     ok(d3ddevice2 == d3drm_d3ddevice2, "Expected Immediate Mode device created == %p, got %p.\n", d3ddevice2, d3drm_d3ddevice2);
5734 
5735     /* Check properties of render target and depth surfaces */
5736     hr = IDirect3DDevice2_GetRenderTarget(d3drm_d3ddevice2, &surface);
5737     ok(hr == DD_OK, "Cannot get surface to the render target (hr = %x).\n", hr);
5738 
5739     memset(&desc, 0, sizeof(desc));
5740     desc.dwSize = sizeof(desc);
5741     hr = IDirectDrawSurface_GetSurfaceDesc(surface, &desc);
5742     ok(hr == DD_OK, "Cannot get surface desc structure (hr = %x).\n", hr);
5743 
5744     ok((desc.dwWidth == rc.right) && (desc.dwHeight == rc.bottom), "Expected surface dimensions = %u, %u, got %u, %u.\n",
5745             rc.right, rc.bottom, desc.dwWidth, desc.dwHeight);
5746     ok((desc.ddsCaps.dwCaps & (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE)) == (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE),
5747             "Expected caps containing %x, got %x.\n", DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE, desc.ddsCaps.dwCaps);
5748     expected_flags = DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH;
5749     ok(desc.dwFlags == expected_flags, "Expected %x for flags, got %x.\n", expected_flags, desc.dwFlags);
5750 
5751     hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &d3drm_ds);
5752     ok(hr == DD_OK, "Cannot get attached depth surface (hr = %x).\n", hr);
5753     ok(ds == d3drm_ds, "Expected depth surface (%p) == surface created internally (%p).\n", ds, d3drm_ds);
5754 
5755     desc.dwSize = sizeof(desc);
5756     hr = IDirectDrawSurface_GetSurfaceDesc(ds, &desc);
5757     ok(hr == DD_OK, "Cannot get z surface desc structure (hr = %x).\n", hr);
5758 
5759     ok((desc.dwWidth == rc.right) && (desc.dwHeight == rc.bottom), "Expected surface dimensions = %u, %u, got %u, %u.\n",
5760             rc.right, rc.bottom, desc.dwWidth, desc.dwHeight);
5761     ok((desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) == DDSCAPS_ZBUFFER, "Expected caps containing %x, got %x.\n", DDSCAPS_ZBUFFER, desc.ddsCaps.dwCaps);
5762     expected_flags = DDSD_ZBUFFERBITDEPTH | DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH;
5763     ok(desc.dwFlags == expected_flags, "Expected %x for flags, got %x.\n", expected_flags, desc.dwFlags);
5764 
5765     IDirectDrawSurface_Release(d3drm_ds);
5766     IDirectDrawSurface_Release(ds);
5767     IDirectDrawSurface_Release(surface);
5768     IDirect3DDevice2_Release(d3drm_d3ddevice2);
5769     IDirect3DRMDevice3_Release(device3);
5770     ref3 = get_refcount((IUnknown *)d3drm1);
5771     ok(ref1 == ref3, "expected ref1 == ref3, got ref1 = %u, ref3 = %u.\n", ref1, ref3);
5772     ref3 = get_refcount((IUnknown *)d3drm3);
5773     ok(ref3 == ref2, "expected ref3 == ref2, got ref2 = %u , ref3 = %u.\n", ref2, ref3);
5774     device_ref2 = get_refcount((IUnknown *)d3ddevice2);
5775     ok(device_ref2 == device_ref1, "Expected device_ref2 == device_ref1, got device_ref1 = %u, device_ref2 = %u.\n", device_ref1, device_ref2);
5776     d3d_ref2 = get_refcount((IUnknown *)d3d2);
5777     ok(d3d_ref2 == d3d_ref1, "Expected d3d_ref2 == d3d_ref1, got d3d_ref1 = %u, d3d_ref2 = %u.\n", d3d_ref1, d3d_ref2);
5778 
5779     /* InitFromD3D tests */
5780     hr = IDirect3DRM3_CreateObject(d3drm3, &CLSID_CDirect3DRMDevice, NULL, &IID_IDirect3DRMDevice3, (void **)&device3);
5781     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMDevice3 interface (hr = %#x).\n", hr);
5782 
5783     hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirect3D, (void **)&d3d1);
5784     ok(SUCCEEDED(hr), "Cannot get IDirect3D interface (hr = %#x).\n", hr);
5785     if (SUCCEEDED(hr = IDirect3DDevice2_QueryInterface(d3ddevice2, &IID_IDirect3DDevice, (void **)&d3ddevice1)))
5786     {
5787         hr = IDirect3DRMDevice3_InitFromD3D(device3, d3d1, d3ddevice1);
5788         ok(hr == E_NOINTERFACE, "Expected hr == E_NOINTERFACE, got %#x.\n", hr);
5789         hr = IDirect3DRMDevice3_InitFromD3D(device3, NULL, d3ddevice1);
5790         ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
5791         hr = IDirect3DRMDevice3_InitFromD3D(device3, d3d1, NULL);
5792         ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
5793         hr = IDirect3DRMDevice3_QueryInterface(device3, &IID_IDirect3DRMDevice, (void **)&device1);
5794         ok(SUCCEEDED(hr), "Cannot obtain IDirect3DRMDevice interface (hr = %#x).\n", hr);
5795         hr = IDirect3DRMDevice_InitFromD3D(device1, d3d1, d3ddevice1);
5796         todo_wine ok(hr == E_NOINTERFACE, "Expected hr == E_NOINTERFACE, got %#x.\n", hr);
5797         IDirect3DRMDevice_Release(device1);
5798         if (SUCCEEDED(hr))
5799         {
5800             IDirect3DRMDevice_Release(device1);
5801             hr = IDirect3DRM3_CreateObject(d3drm3, &CLSID_CDirect3DRMDevice, NULL, &IID_IDirect3DRMDevice3,
5802                     (void **)&device3);
5803             ok(SUCCEEDED(hr), "Cannot get IDirect3DRMDevice3 interface (hr = %#x).\n", hr);
5804         }
5805     }
5806     IDirect3D_Release(d3d1);
5807     IDirect3DDevice_Release(d3ddevice1);
5808 
5809     hr = IDirect3DRMDevice3_InitFromD3D2(device3, NULL, d3ddevice2);
5810     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
5811     hr = IDirect3DRMDevice3_InitFromD3D2(device3, d3d2, NULL);
5812     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
5813 
5814     hr = IDirect3DRMDevice3_InitFromD3D2(device3, d3d2, d3ddevice2);
5815     ok(SUCCEEDED(hr), "Failed to initialise IDirect3DRMDevice2 interface (hr = %#x)\n", hr);
5816     ref4 = get_refcount((IUnknown *)d3drm1);
5817     ok(ref4 > ref1, "Expected ref4 > ref1, got ref1 = %u , ref4 = %u.\n", ref1, ref4);
5818     device_ref2 = get_refcount((IUnknown *)d3ddevice2);
5819     ok(device_ref2 > device_ref1, "Expected device_ref2 > device_ref1, got device_ref1 = %u, device_ref2 = %u.\n",
5820             device_ref1, device_ref2);
5821     d3d_ref2 = get_refcount((IUnknown *)d3d2);
5822     ok(d3d_ref2 > d3d_ref1, "Expected d3d_ref2 > d3d_ref1, got d3d_ref1 = %u, d3d_ref2 = %u.\n", d3d_ref1, d3d_ref2);
5823     ret_val = IDirect3DRMDevice3_GetWidth(device3);
5824     ok(ret_val == rc.right, "Expected device width = 300, got %u.\n", ret_val);
5825     ret_val = IDirect3DRMDevice3_GetHeight(device3);
5826     ok(ret_val == rc.bottom, "Expected device height == 200, got %u.\n", ret_val);
5827 
5828     hr = IDirect3DRMDevice3_InitFromD3D2(device3, d3d2, d3ddevice2);
5829     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
5830     ref3 = get_refcount((IUnknown *)d3drm1);
5831     ok(ref3 > ref1, "expected ref3 > ref1, got ref1 = %u , ref3 = %u.\n", ref1, ref3);
5832     ref3 = get_refcount((IUnknown *)d3ddevice2);
5833     ok(ref3 > device_ref2, "Expected ref3 > device_ref2, got ref3 = %u, device_ref2 = %u.\n", ref3, device_ref2);
5834     ref3 = get_refcount((IUnknown *)d3d2);
5835     ok(ref3 > d3d_ref2, "Expected ref3 > d3d_ref2, got ref3 = %u, d3d_ref2 = %u.\n", ref3, d3d_ref2);
5836     /* Release leaked references */
5837     while (IDirect3DRM_Release(d3drm1) > ref4);
5838     while (IDirect3DDevice2_Release(d3ddevice2) > device_ref2);
5839     while (IDirect3D2_Release(d3d2) > d3d_ref2);
5840 
5841     hr = DirectDrawCreate(NULL, &temp_ddraw1, NULL);
5842     ok(SUCCEEDED(hr), "Cannot get IDirectDraw interface (hr = %#x).\n", hr);
5843     hr = IDirectDraw_QueryInterface(temp_ddraw1, &IID_IDirect3D2, (void **)&temp_d3d2);
5844     ok(SUCCEEDED(hr), "Cannot get IDirect3D2 interface (hr = %#x).\n", hr);
5845     ref5 = get_refcount((IUnknown *)temp_d3d2);
5846 
5847     hr = IDirectDraw_QueryInterface(temp_ddraw1, &IID_IDirectDraw2, (void **)&temp_ddraw2);
5848     ok(SUCCEEDED(hr), "Cannot get IDirectDraw2 interface (hr = %#x).\n", hr);
5849 
5850     temp_d3ddevice2 = create_device2(temp_ddraw2, window, &surface);
5851     hr = IDirect3DRMDevice3_InitFromD3D2(device3, temp_d3d2, temp_d3ddevice2);
5852     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
5853     ref3 = get_refcount((IUnknown *)d3drm1);
5854     ok(ref3 > ref4, "expected ref3 > ref4, got ref3 = %u , ref4 = %u.\n", ref3, ref4);
5855     ref3 = get_refcount((IUnknown *)temp_d3ddevice2);
5856     ok(ref3 == device_ref2, "Expected ref3 == device_ref2, got ref3 = %u, device_ref2 = %u.\n", ref3, device_ref2);
5857     ref3 = get_refcount((IUnknown *)temp_d3d2);
5858     ok(ref3 == d3d_ref2, "Expected ref3 == d3d_ref2, got ref3 = %u, d3d_ref2 = %u.\n", ref3, d3d_ref2);
5859     /* Release leaked references */
5860     while (IDirect3DRM_Release(d3drm1) > ref4);
5861     while (IDirect3DDevice2_Release(temp_d3ddevice2) > 0);
5862     while (IDirect3D2_Release(temp_d3d2) >= ref5);
5863     IDirectDrawSurface_Release(surface);
5864     IDirectDraw2_Release(temp_ddraw2);
5865     IDirectDraw_Release(temp_ddraw1);
5866 
5867     surface = NULL;
5868     hr = IDirectDraw_EnumSurfaces(ddraw1, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
5869             NULL, &surface, surface_callback);
5870     ok(SUCCEEDED(hr), "Failed to enumerate surfaces (hr = %#x).\n", hr);
5871     ok(surface == NULL, "No primary surface should have enumerated (%p).\n", surface);
5872 
5873     hr = IDirect3DRMDevice3_GetDirect3DDevice2(device3, &d3drm_d3ddevice2);
5874     ok(SUCCEEDED(hr), "Cannot get IDirect3DDevice2 interface (hr = %#x).\n", hr);
5875     ok(d3ddevice2 == d3drm_d3ddevice2, "Expected Immediate Mode device created == %p, got %p.\n", d3ddevice2,
5876             d3drm_d3ddevice2);
5877 
5878     /* Check properties of render target and depth surfaces */
5879     hr = IDirect3DDevice2_GetRenderTarget(d3drm_d3ddevice2, &surface);
5880     ok(SUCCEEDED(hr), "Cannot get surface to the render target (hr = %#x).\n", hr);
5881 
5882     memset(&desc, 0, sizeof(desc));
5883     desc.dwSize = sizeof(desc);
5884     hr = IDirectDrawSurface_GetSurfaceDesc(surface, &desc);
5885     ok(SUCCEEDED(hr), "Cannot get surface desc structure (hr = %x).\n", hr);
5886 
5887     ok((desc.dwWidth == rc.right) && (desc.dwHeight == rc.bottom), "Expected surface dimensions = %u, %u, got %u, %u.\n",
5888             rc.right, rc.bottom, desc.dwWidth, desc.dwHeight);
5889     ok((desc.ddsCaps.dwCaps & (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE)) == (DDSCAPS_OFFSCREENPLAIN|DDSCAPS_3DDEVICE),
5890             "Expected caps containing %#x, got %#x.\n", DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE, desc.ddsCaps.dwCaps);
5891     expected_flags = DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH;
5892     ok(desc.dwFlags == expected_flags, "Expected %#x for flags, got %#x.\n", expected_flags, desc.dwFlags);
5893 
5894     hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &d3drm_ds);
5895     ok(SUCCEEDED(hr), "Cannot get attached depth surface (hr = %x).\n", hr);
5896     ok(ds == d3drm_ds, "Expected depth surface (%p) == surface created internally (%p).\n", ds, d3drm_ds);
5897 
5898     desc.dwSize = sizeof(desc);
5899     hr = IDirectDrawSurface_GetSurfaceDesc(ds, &desc);
5900     ok(SUCCEEDED(hr), "Cannot get z surface desc structure (hr = %x).\n", hr);
5901 
5902     ok((desc.dwWidth == rc.right) && (desc.dwHeight == rc.bottom), "Expected surface dimensions = %u, %u, got %u, %u.\n",
5903             rc.right, rc.bottom, desc.dwWidth, desc.dwHeight);
5904     ok((desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) == DDSCAPS_ZBUFFER, "Expected caps containing %x, got %#x.\n",
5905             DDSCAPS_ZBUFFER, desc.ddsCaps.dwCaps);
5906     expected_flags = DDSD_ZBUFFERBITDEPTH | DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH;
5907     ok(desc.dwFlags == expected_flags, "Expected %#x for flags, got %#x.\n", expected_flags, desc.dwFlags);
5908 
5909     IDirectDrawSurface_Release(d3drm_ds);
5910     IDirectDrawSurface_Release(ds);
5911     IDirectDrawSurface_Release(surface);
5912     IDirect3DDevice2_Release(d3drm_d3ddevice2);
5913     IDirect3DRMDevice3_Release(device3);
5914     ref3 = get_refcount((IUnknown *)d3drm1);
5915     ok(ref1 == ref3, "expected ref1 == ref3, got ref1 = %u, ref3 = %u.\n", ref1, ref3);
5916     ref3 = get_refcount((IUnknown *)d3drm3);
5917     ok(ref3 == ref2, "expected ref3 == ref2, got ref2 = %u , ref3 = %u.\n", ref2, ref3);
5918     device_ref2 = get_refcount((IUnknown *)d3ddevice2);
5919     ok(device_ref2 == device_ref1, "Expected device_ref2 == device_ref1, got device_ref1 = %u, device_ref2 = %u.\n",
5920             device_ref1, device_ref2);
5921     d3d_ref2 = get_refcount((IUnknown *)d3d2);
5922     ok(d3d_ref2 == d3d_ref1, "Expected d3d_ref2 == d3d_ref1, got d3d_ref1 = %u, d3d_ref2 = %u.\n", d3d_ref1, d3d_ref2);
5923 
5924     IDirect3DRM3_Release(d3drm3);
5925     IDirect3DRM_Release(d3drm1);
5926     IDirect3DDevice2_Release(d3ddevice2);
5927     IDirect3D2_Release(d3d2);
5928     IDirectDraw2_Release(ddraw2);
5929     IDirectDraw_Release(ddraw1);
5930     DestroyWindow(window);
5931 }
5932 
test_create_device_1(void)5933 static void test_create_device_1(void)
5934 {
5935     IDirect3DRM *d3drm = NULL;
5936     IDirect3DRMDevice *device = (IDirect3DRMDevice *)0xdeadbeef;
5937     HRESULT hr;
5938 
5939     hr = Direct3DRMCreate(&d3drm);
5940     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x).\n", hr);
5941 
5942     hr = IDirect3DRM_CreateDevice(d3drm, 640, 480, &device);
5943     ok(hr == D3DRMERR_BADDEVICE, "Expected hr == D3DRMERR_BADDEVICE, got %x.\n", hr);
5944     ok(device == NULL, "Expected device returned == NULL, got %p.\n", device);
5945     hr = IDirect3DRM_CreateDevice(d3drm, 640, 480, NULL);
5946     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %x.\n", hr);
5947 
5948     IDirect3DRM_Release(d3drm);
5949 }
5950 
test_create_device_2(void)5951 static void test_create_device_2(void)
5952 {
5953     IDirect3DRM *d3drm = NULL;
5954     IDirect3DRM2 *d3drm2 = NULL;
5955     IDirect3DRMDevice2 *device2 = (IDirect3DRMDevice2 *)0xdeadbeef;
5956     HRESULT hr;
5957 
5958     hr = Direct3DRMCreate(&d3drm);
5959     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x).\n", hr);
5960     hr = IDirect3DRM_QueryInterface(d3drm, &IID_IDirect3DRM2, (void **)&d3drm2);
5961     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM3 interface (hr = %x).\n", hr);
5962 
5963     hr = IDirect3DRM2_CreateDevice(d3drm2, 640, 480, &device2);
5964     ok(hr == D3DRMERR_BADDEVICE, "Expected hr == D3DRMERR_BADDEVICE, got %x.\n", hr);
5965     ok(device2 == NULL, "Expected device returned == NULL, got %p.\n", device2);
5966     hr = IDirect3DRM2_CreateDevice(d3drm2, 640, 480, NULL);
5967     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %x.\n", hr);
5968 
5969     IDirect3DRM2_Release(d3drm2);
5970     IDirect3DRM_Release(d3drm);
5971 }
5972 
test_create_device_3(void)5973 static void test_create_device_3(void)
5974 {
5975     IDirect3DRM *d3drm = NULL;
5976     IDirect3DRM3 *d3drm3 = NULL;
5977     IDirect3DRMDevice3 *device3 = (IDirect3DRMDevice3 *)0xdeadbeef;
5978     HRESULT hr;
5979 
5980     hr = Direct3DRMCreate(&d3drm);
5981     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x).\n", hr);
5982     hr = IDirect3DRM_QueryInterface(d3drm, &IID_IDirect3DRM3, (void **)&d3drm3);
5983     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM3 interface (hr = %x).\n", hr);
5984 
5985     hr = IDirect3DRM3_CreateDevice(d3drm3, 640, 480, &device3);
5986     ok(hr == D3DRMERR_BADDEVICE, "Expected hr == D3DRMERR_BADDEVICE, got %x.\n", hr);
5987     ok(device3 == NULL, "Expected device returned == NULL, got %p.\n", device3);
5988     hr = IDirect3DRM3_CreateDevice(d3drm3, 640, 480, NULL);
5989     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %x.\n", hr);
5990 
5991     IDirect3DRM3_Release(d3drm3);
5992     IDirect3DRM_Release(d3drm);
5993 }
5994 
create_bitmap(unsigned int w,unsigned int h,BOOL palettized)5995 static char *create_bitmap(unsigned int w, unsigned int h, BOOL palettized)
5996 {
5997     unsigned int bpp = palettized ? 8 : 24;
5998     BITMAPFILEHEADER file_header;
5999     DWORD written, size, ret;
6000     unsigned char *buffer;
6001     char path[MAX_PATH];
6002     unsigned int i, j;
6003     BITMAPINFO *info;
6004     char *filename;
6005     HANDLE file;
6006 
6007     ret = GetTempPathA(MAX_PATH, path);
6008     ok(ret, "Failed to get temporary file path.\n");
6009     filename = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
6010     ret = GetTempFileNameA(path, "d3d", 0, filename);
6011     ok(ret, "Failed to get filename.\n");
6012     file = CreateFileA(filename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
6013     ok(file != INVALID_HANDLE_VALUE, "Failed to open temporary file \"%s\".\n", filename);
6014 
6015     size = FIELD_OFFSET(BITMAPINFO, bmiColors[palettized ? 256 : 0]);
6016 
6017     memset(&file_header, 0, sizeof(file_header));
6018     file_header.bfType = 0x4d42; /* BM */
6019     file_header.bfOffBits = sizeof(file_header) + size;
6020     file_header.bfSize = file_header.bfOffBits + w * h * (bpp / 8);
6021     ret = WriteFile(file, &file_header, sizeof(file_header), &written, NULL);
6022     ok(ret && written == sizeof(file_header), "Failed to write file header.\n");
6023 
6024     info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
6025     info->bmiHeader.biSize = sizeof(info->bmiHeader);
6026     info->bmiHeader.biBitCount = bpp;
6027     info->bmiHeader.biPlanes = 1;
6028     info->bmiHeader.biWidth = w;
6029     info->bmiHeader.biHeight = h;
6030     info->bmiHeader.biCompression = BI_RGB;
6031     if (palettized)
6032     {
6033         for (i = 0; i < 256; ++i)
6034         {
6035             info->bmiColors[i].rgbBlue = i;
6036             info->bmiColors[i].rgbGreen = i;
6037             info->bmiColors[i].rgbRed = i;
6038         }
6039     }
6040     ret = WriteFile(file, info, size, &written, NULL);
6041     ok(ret && written == size, "Failed to write bitmap info.\n");
6042     HeapFree(GetProcessHeap(), 0, info);
6043 
6044     size = w * h * (bpp / 8);
6045     buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
6046     for (i = 0, j = 0; i < size;)
6047     {
6048         if (palettized)
6049         {
6050             buffer[i++] = j++;
6051             j %= 256;
6052         }
6053         else
6054         {
6055             buffer[i++] = j % 251;
6056             buffer[i++] = j % 239;
6057             buffer[i++] = j++ % 247;
6058         }
6059     }
6060     ret = WriteFile(file, buffer, size, &written, NULL);
6061     ok(ret && written == size, "Failed to write bitmap data.\n");
6062     HeapFree(GetProcessHeap(), 0, buffer);
6063 
6064     CloseHandle(file);
6065 
6066     return filename;
6067 }
6068 
test_bitmap_data(unsigned int test_idx,const D3DRMIMAGE * img,BOOL upside_down,unsigned int w,unsigned int h,BOOL palettized)6069 static void test_bitmap_data(unsigned int test_idx, const D3DRMIMAGE *img,
6070         BOOL upside_down, unsigned int w, unsigned int h, BOOL palettized)
6071 {
6072     const unsigned char *data = img->buffer1;
6073     unsigned int i, j;
6074 
6075     ok(img->width == w, "Test %u: Got unexpected image width %u, expected %u.\n", test_idx, img->width, w);
6076     ok(img->height == h, "Test %u: Got unexpected image height %u, expected %u.\n", test_idx, img->height, h);
6077     ok(img->aspectx == 1, "Test %u: Got unexpected image aspectx %u.\n", test_idx, img->aspectx);
6078     ok(img->aspecty == 1, "Test %u: Got unexpected image aspecty %u.\n", test_idx, img->aspecty);
6079     ok(!img->buffer2, "Test %u: Got unexpected image buffer2 %p.\n", test_idx, img->buffer2);
6080 
6081     /* The image is palettized if the total number of colors used is <= 256. */
6082     if (w * h > 256 && !palettized)
6083     {
6084         /* D3drm aligns the 24bpp texture to 4 bytes in the buffer, with one
6085          * byte padding from 24bpp texture. */
6086         ok(img->depth == 32, "Test %u: Got unexpected image depth %u.\n", test_idx, img->depth);
6087         ok(img->rgb == TRUE, "Test %u: Got unexpected image rgb %#x.\n", test_idx, img->rgb);
6088         ok(img->bytes_per_line == w * 4, "Test %u: Got unexpected image bytes per line %u, expected %u.\n",
6089                 test_idx, img->bytes_per_line, w * 4);
6090         ok(img->red_mask == 0xff0000, "Test %u: Got unexpected image red mask %#x.\n", test_idx, img->red_mask);
6091         ok(img->green_mask == 0x00ff00, "Test %u: Got unexpected image green mask %#x.\n", test_idx, img->green_mask);
6092         ok(img->blue_mask == 0x0000ff, "Test %u: Got unexpected image blue mask %#x.\n", test_idx, img->blue_mask);
6093         ok(!img->alpha_mask, "Test %u: Got unexpected image alpha mask %#x.\n", test_idx, img->alpha_mask);
6094         ok(!img->palette_size, "Test %u: Got unexpected palette size %u.\n", test_idx, img->palette_size);
6095         ok(!img->palette, "Test %u: Got unexpected image palette %p.\n", test_idx, img->palette);
6096         for (i = 0; i < h; ++i)
6097         {
6098             for (j = 0; j < w; ++j)
6099             {
6100                 const unsigned char *ptr = &data[i * img->bytes_per_line + j * 4];
6101                 unsigned int idx = upside_down ? (h - 1 - i) * w + j : i * w + j;
6102 
6103                 if (ptr[0] != idx % 251 || ptr[1] != idx % 239 || ptr[2] != idx % 247 || ptr[3] != 0xff)
6104                 {
6105                     ok(0, "Test %u: Got unexpected color 0x%02x%02x%02x%02x at position %u, %u, "
6106                             "expected 0x%02x%02x%02x%02x.\n", test_idx, ptr[0], ptr[1], ptr[2], ptr[3],
6107                             j, i, idx % 251, idx % 239, idx % 247, 0xff);
6108                     return;
6109                 }
6110             }
6111         }
6112         return;
6113     }
6114 
6115     ok(img->depth == 8, "Test %u: Got unexpected image depth %u.\n", test_idx, img->depth);
6116     ok(!img->rgb, "Test %u: Got unexpected image rgb %#x.\n", test_idx, img->rgb);
6117     ok(img->red_mask == 0xff, "Test %u: Got unexpected image red mask %#x.\n", test_idx, img->red_mask);
6118     ok(img->green_mask == 0xff, "Test %u: Got unexpected image green mask %#x.\n", test_idx, img->green_mask);
6119     ok(img->blue_mask == 0xff, "Test %u: Got unexpected image blue mask %#x.\n", test_idx, img->blue_mask);
6120     ok(!img->alpha_mask, "Test %u: Got unexpected image alpha mask %#x.\n", test_idx, img->alpha_mask);
6121     ok(!!img->palette, "Test %u: Got unexpected image palette %p.\n", test_idx, img->palette);
6122     if (!palettized)
6123     {
6124         /* In this case, bytes_per_line is aligned to the next multiple of
6125          * 4 from width. */
6126         ok(img->bytes_per_line == ((w + 3) & ~3), "Test %u: Got unexpected image bytes per line %u, expected %u.\n",
6127                 test_idx, img->bytes_per_line, (w + 3) & ~3);
6128         ok(img->palette_size == w * h, "Test %u: Got unexpected palette size %u, expected %u.\n",
6129                 test_idx, img->palette_size, w * h);
6130         for (i = 0; i < img->palette_size; ++i)
6131         {
6132             unsigned int idx = upside_down ? (h - 1) * w - i + (i % w) * 2 : i;
6133             ok(img->palette[i].red == idx % 251
6134                     && img->palette[i].green == idx % 239 && img->palette[i].blue == idx % 247,
6135                     "Test %u: Got unexpected palette entry (%u) color 0x%02x%02x%02x.\n",
6136                     test_idx, i, img->palette[i].red, img->palette[i].green, img->palette[i].blue);
6137             ok(img->palette[i].flags == D3DRMPALETTE_READONLY,
6138                     "Test %u: Got unexpected palette entry (%u) flags %#x.\n",
6139                     test_idx, i, img->palette[i].flags);
6140         }
6141         for (i = 0; i < h; ++i)
6142         {
6143             for (j = 0; j < w; ++j)
6144             {
6145                 if (data[i * img->bytes_per_line + j] != i * w + j)
6146                 {
6147                     ok(0, "Test %u: Got unexpected color 0x%02x at position %u, %u, expected 0x%02x.\n",
6148                             test_idx, data[i * img->bytes_per_line + j], j, i, i * w + j);
6149                     return;
6150                 }
6151             }
6152         }
6153         return;
6154     }
6155 
6156     /* bytes_per_line is not always aligned by d3drm depending on the
6157      * format. */
6158     ok(img->bytes_per_line == w, "Test %u: Got unexpected image bytes per line %u, expected %u.\n",
6159             test_idx, img->bytes_per_line, w);
6160     ok(img->palette_size == 256, "Test %u: Got unexpected palette size %u.\n", test_idx, img->palette_size);
6161     for (i = 0; i < 256; ++i)
6162     {
6163         ok(img->palette[i].red == i && img->palette[i].green == i && img->palette[i].blue == i,
6164                 "Test %u: Got unexpected palette entry (%u) color 0x%02x%02x%02x.\n",
6165                 test_idx, i, img->palette[i].red, img->palette[i].green, img->palette[i].blue);
6166         ok(img->palette[i].flags == D3DRMPALETTE_READONLY,
6167                 "Test %u: Got unexpected palette entry (%u) flags %#x.\n",
6168                 test_idx, i, img->palette[i].flags);
6169     }
6170     for (i = 0; i < h; ++i)
6171     {
6172         for (j = 0; j < w; ++j)
6173         {
6174             unsigned int idx = upside_down ? (h - 1 - i) * w + j : i * w + j;
6175             if (data[i * img->bytes_per_line + j] != idx % 256)
6176             {
6177                 ok(0, "Test %u: Got unexpected color 0x%02x at position %u, %u, expected 0x%02x.\n",
6178                         test_idx, data[i * img->bytes_per_line + j], j, i, idx % 256);
6179                 return;
6180             }
6181         }
6182     }
6183 }
6184 
test_load_texture(void)6185 static void test_load_texture(void)
6186 {
6187     IDirect3DRMTexture3 *texture3;
6188     IDirect3DRMTexture2 *texture2;
6189     IDirect3DRMTexture *texture1;
6190     D3DRMIMAGE *d3drm_img;
6191     IDirect3DRM3 *d3drm3;
6192     IDirect3DRM2 *d3drm2;
6193     IDirect3DRM *d3drm1;
6194     ULONG ref1, ref2;
6195     unsigned int i;
6196     char *filename;
6197     HRESULT hr;
6198     BOOL ret;
6199 
6200     static const struct
6201     {
6202         unsigned int w;
6203         unsigned int h;
6204         BOOL palettized;
6205     }
6206     tests[] =
6207     {
6208         {100, 100, TRUE },
6209         {99,  100, TRUE },
6210         {100, 100, FALSE},
6211         {99,  100, FALSE},
6212         {3,   39,  FALSE},
6213     };
6214 
6215     hr = Direct3DRMCreate(&d3drm1);
6216     ok(hr == D3DRM_OK, "Failed to create IDirect3DRM object, hr %#x.\n", hr);
6217     hr = IDirect3DRM_QueryInterface(d3drm1, &IID_IDirect3DRM2, (void **)&d3drm2);
6218     ok(SUCCEEDED(hr), "Failed to get IDirect3DRM2 interface, hr %#x.\n", hr);
6219     hr = IDirect3DRM_QueryInterface(d3drm1, &IID_IDirect3DRM3, (void **)&d3drm3);
6220     ok(SUCCEEDED(hr), "Failed to get IDirect3DRM3 interface, hr %#x.\n", hr);
6221     ref1 = get_refcount((IUnknown *)d3drm1);
6222 
6223     /* Test all failures together. */
6224     texture1 = (IDirect3DRMTexture *)0xdeadbeef;
6225     hr = IDirect3DRM_LoadTexture(d3drm1, NULL, &texture1);
6226     ok(hr == D3DRMERR_BADVALUE, "Got unexpected hr %#x.\n", hr);
6227     ok(!texture1, "Got unexpected texture %p.\n", texture1);
6228     texture1 = (IDirect3DRMTexture *)0xdeadbeef;
6229     hr = IDirect3DRM_LoadTexture(d3drm1, "", &texture1);
6230     ok(hr == D3DRMERR_FILENOTFOUND, "Got unexpected hr %#x.\n", hr);
6231     ok(!texture1, "Got unexpected texture %p.\n", texture1);
6232     hr = IDirect3DRM_LoadTexture(d3drm1, NULL, NULL);
6233     ok(hr == D3DRMERR_BADVALUE, "Got unexpected hr %#x.\n", hr);
6234 
6235     texture2 = (IDirect3DRMTexture2 *)0xdeadbeef;
6236     hr = IDirect3DRM2_LoadTexture(d3drm2, NULL, &texture2);
6237     ok(hr == D3DRMERR_FILENOTFOUND, "Got unexpected hr %#x.\n", hr);
6238     ok(!texture2, "Got unexpected texture %p.\n", texture2);
6239     texture2 = (IDirect3DRMTexture2 *)0xdeadbeef;
6240     hr = IDirect3DRM2_LoadTexture(d3drm2, "", &texture2);
6241     ok(hr == D3DRMERR_FILENOTFOUND, "Got unexpected hr %#x.\n", hr);
6242     ok(!texture2, "Got unexpected texture %p.\n", texture2);
6243     hr = IDirect3DRM2_LoadTexture(d3drm2, NULL, NULL);
6244     ok(hr == D3DRMERR_BADVALUE, "Got unexpected hr %#x.\n", hr);
6245 
6246     texture3 = (IDirect3DRMTexture3 *)0xdeadbeef;
6247     hr = IDirect3DRM3_LoadTexture(d3drm3, NULL, &texture3);
6248     ok(hr == D3DRMERR_FILENOTFOUND, "Got unexpected hr %#x.\n", hr);
6249     ok(!texture3, "Got unexpected texture %p.\n", texture3);
6250     texture3 = (IDirect3DRMTexture3 *)0xdeadbeef;
6251     hr = IDirect3DRM_LoadTexture(d3drm3, "", &texture3);
6252     ok(hr == D3DRMERR_FILENOTFOUND, "Got unexpected hr %#x.\n", hr);
6253     ok(!texture3, "Got unexpected texture %p.\n", texture3);
6254     hr = IDirect3DRM3_LoadTexture(d3drm3, NULL, NULL);
6255     ok(hr == D3DRMERR_BADVALUE, "Got unexpected hr %#x.\n", hr);
6256 
6257     for (i = 0; i < ARRAY_SIZE(tests); ++i)
6258     {
6259         filename = create_bitmap(tests[i].w, tests[i].h, tests[i].palettized);
6260 
6261         hr = IDirect3DRM_LoadTexture(d3drm1, filename, &texture1);
6262         ok(SUCCEEDED(hr), "Test %u: Failed to load texture, hr %#x.\n", i, hr);
6263         ref2 = get_refcount((IUnknown *)d3drm1);
6264         ok(ref2 > ref1, "Test %u: expected ref2 > ref1, got ref1 %u, ref2 %u.\n", i, ref1, ref2);
6265 
6266         hr = IDirect3DRMTexture_InitFromFile(texture1, filename);
6267         ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
6268         /* InitFromFile() seems to AddRef() IDirect3DRM even if it fails. */
6269         IDirect3DRM_Release(d3drm1);
6270         d3drm_img = IDirect3DRMTexture_GetImage(texture1);
6271         ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
6272         test_bitmap_data(i * 7, d3drm_img, FALSE, tests[i].w, tests[i].h, tests[i].palettized);
6273         IDirect3DRMTexture_Release(texture1);
6274         ref2 = get_refcount((IUnknown *)d3drm1);
6275         ok(ref1 == ref2, "Test %u: expected ref1 == ref2, got ref1 = %u, ref2 = %u.\n", i, ref1, ref2);
6276         hr = IDirect3DRM_CreateObject(d3drm1, &CLSID_CDirect3DRMTexture,
6277                 NULL, &IID_IDirect3DRMTexture, (void **)&texture1);
6278         ok(SUCCEEDED(hr), "Test %u: Failed to create texture, hr %#x.\n", i, hr);
6279         hr = IDirect3DRMTexture_InitFromFile(texture1, NULL);
6280         ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
6281         hr = IDirect3DRMTexture_InitFromFile(texture1, "");
6282         ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
6283         hr = IDirect3DRMTexture_InitFromFile(texture1, filename);
6284         ok(SUCCEEDED(hr), "Test %u: Failed to initialise texture from file, hr %#x.\n", i, hr);
6285         d3drm_img = IDirect3DRMTexture_GetImage(texture1);
6286         ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
6287         test_bitmap_data(i * 7 + 1, d3drm_img, FALSE, tests[i].w, tests[i].h, tests[i].palettized);
6288         IDirect3DRMTexture_Release(texture1);
6289 
6290         hr = IDirect3DRM2_LoadTexture(d3drm2, filename, &texture2);
6291         ok(SUCCEEDED(hr), "Test %u: Failed to load texture, hr %#x.\n", i, hr);
6292         ref2 = get_refcount((IUnknown *)d3drm1);
6293         ok(ref2 > ref1, "Test %u: expected ref2 > ref1, got ref1 %u, ref2 %u.\n", i, ref1, ref2);
6294 
6295         hr = IDirect3DRMTexture2_InitFromFile(texture2, filename);
6296         ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
6297         IDirect3DRM_Release(d3drm1);
6298         d3drm_img = IDirect3DRMTexture2_GetImage(texture2);
6299         ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
6300         test_bitmap_data(i * 7 + 2, d3drm_img, TRUE, tests[i].w, tests[i].h, tests[i].palettized);
6301         IDirect3DRMTexture2_Release(texture2);
6302         ref2 = get_refcount((IUnknown *)d3drm1);
6303         ok(ref1 == ref2, "Test %u: expected ref1 == ref2, got ref1 = %u, ref2 = %u.\n", i, ref1, ref2);
6304         hr = IDirect3DRM2_CreateObject(d3drm2, &CLSID_CDirect3DRMTexture,
6305                 NULL, &IID_IDirect3DRMTexture2, (void **)&texture2);
6306         ok(SUCCEEDED(hr), "Test %u: Failed to create texture, hr %#x.\n", i, hr);
6307         hr = IDirect3DRMTexture2_InitFromFile(texture2, NULL);
6308         ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
6309         hr = IDirect3DRMTexture2_InitFromFile(texture2, "");
6310         ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
6311         hr = IDirect3DRMTexture2_InitFromFile(texture2, filename);
6312         ok(SUCCEEDED(hr), "Test %u: Failed to initialise texture from file, hr %#x.\n", i, hr);
6313         d3drm_img = IDirect3DRMTexture2_GetImage(texture2);
6314         ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
6315         test_bitmap_data(i * 7 + 3, d3drm_img, TRUE, tests[i].w, tests[i].h, tests[i].palettized);
6316         IDirect3DRMTexture2_Release(texture2);
6317 
6318         hr = IDirect3DRM3_LoadTexture(d3drm3, filename, &texture3);
6319         ok(SUCCEEDED(hr), "Test %u: Failed to load texture, hr %#x.\n", i, hr);
6320         ref2 = get_refcount((IUnknown *)d3drm1);
6321         ok(ref2 > ref1, "Test %u: expected ref2 > ref1, got ref1 %u, ref2 %u.\n", i, ref1, ref2);
6322 
6323         hr = IDirect3DRMTexture3_InitFromFile(texture3, filename);
6324         ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
6325         IDirect3DRM_Release(d3drm1);
6326         d3drm_img = IDirect3DRMTexture3_GetImage(texture3);
6327         ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
6328         test_bitmap_data(i * 7 + 4, d3drm_img, TRUE, tests[i].w, tests[i].h, tests[i].palettized);
6329         /* Test whether querying a version 1 texture from version 3 causes a
6330          * change in the loading behavior. */
6331         hr = IDirect3DRMTexture3_QueryInterface(texture3, &IID_IDirect3DRMTexture, (void **)&texture1);
6332         ok(SUCCEEDED(hr), "Failed to get IDirect3DRMTexture interface, hr %#x.\n", hr);
6333         d3drm_img = IDirect3DRMTexture_GetImage(texture1);
6334         ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
6335         test_bitmap_data(i * 7 + 5, d3drm_img, TRUE, tests[i].w, tests[i].h, tests[i].palettized);
6336         IDirect3DRMTexture_Release(texture1);
6337         IDirect3DRMTexture3_Release(texture3);
6338         ref2 = get_refcount((IUnknown *)d3drm1);
6339         ok(ref1 == ref2, "Test %u: expected ref1 == ref2, got ref1 = %u, ref2 = %u.\n", i, ref1, ref2);
6340 
6341         hr = IDirect3DRM3_CreateObject(d3drm3, &CLSID_CDirect3DRMTexture,
6342                 NULL, &IID_IDirect3DRMTexture3, (void **)&texture3);
6343         ok(SUCCEEDED(hr), "Test %u: Failed to create texture, hr %#x.\n", i, hr);
6344         hr = IDirect3DRMTexture3_InitFromFile(texture3, NULL);
6345         ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
6346         hr = IDirect3DRMTexture3_InitFromFile(texture3, "");
6347         ok(hr == D3DRMERR_BADOBJECT, "Test %u: Got unexpected hr %#x.\n", i, hr);
6348         hr = IDirect3DRMTexture3_InitFromFile(texture3, filename);
6349         ok(SUCCEEDED(hr), "Test %u: Failed to initialize texture from file, hr %#x.\n", i, hr);
6350         d3drm_img = IDirect3DRMTexture3_GetImage(texture3);
6351         ok(!!d3drm_img, "Test %u: Failed to get image.\n", i);
6352         test_bitmap_data(i * 7 + 6, d3drm_img, TRUE, tests[i].w, tests[i].h, tests[i].palettized);
6353         IDirect3DRMTexture3_Release(texture3);
6354 
6355         ret = DeleteFileA(filename);
6356         ok(ret, "Test %u: Failed to delete bitmap \"%s\".\n", i, filename);
6357         HeapFree(GetProcessHeap(), 0, filename);
6358     }
6359 
6360     IDirect3DRM3_Release(d3drm3);
6361     IDirect3DRM2_Release(d3drm2);
6362     IDirect3DRM_Release(d3drm1);
6363 }
6364 
test_texture_qi(void)6365 static void test_texture_qi(void)
6366 {
6367     static const struct qi_test tests[] =
6368     {
6369         { &IID_IDirect3DRM3,               NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6370         { &IID_IDirect3DRM2,               NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6371         { &IID_IDirect3DRM,                NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6372         { &IID_IDirect3DRMDevice,          NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6373         { &IID_IDirect3DRMDevice2,         NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6374         { &IID_IDirect3DRMDevice3,         NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6375         { &IID_IDirect3DRMWinDevice,       NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6376         { &IID_IDirect3DRMObject,          &IID_IUnknown, &IID_IDirect3DRMTexture,  S_OK                      },
6377         { &IID_IDirect3DRMViewport,        NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6378         { &IID_IDirect3DRMViewport2,       NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6379         { &IID_IDirect3DRMFrame,           NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6380         { &IID_IDirect3DRMFrame2,          NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6381         { &IID_IDirect3DRMFrame3,          NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6382         { &IID_IDirect3DRMVisual,          &IID_IUnknown, &IID_IDirect3DRMTexture,  S_OK                      },
6383         { &IID_IDirect3DRMMesh,            NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6384         { &IID_IDirect3DRMMeshBuilder,     NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6385         { &IID_IDirect3DRMMeshBuilder2,    NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6386         { &IID_IDirect3DRMMeshBuilder3,    NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6387         { &IID_IDirect3DRMFace,            NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6388         { &IID_IDirect3DRMFace2,           NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6389         { &IID_IDirect3DRMLight,           NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6390         { &IID_IDirect3DRMTexture,         &IID_IUnknown, &IID_IDirect3DRMTexture,  S_OK                      },
6391         { &IID_IDirect3DRMTexture2,        &IID_IUnknown, &IID_IDirect3DRMTexture2, S_OK                      },
6392         { &IID_IDirect3DRMTexture3,        &IID_IUnknown, &IID_IDirect3DRMTexture3, S_OK                      },
6393         { &IID_IDirect3DRMWrap,            NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6394         { &IID_IDirect3DRMMaterial,        NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6395         { &IID_IDirect3DRMMaterial2,       NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6396         { &IID_IDirect3DRMAnimation,       NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6397         { &IID_IDirect3DRMAnimation2,      NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6398         { &IID_IDirect3DRMAnimationSet,    NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6399         { &IID_IDirect3DRMAnimationSet2,   NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6400         { &IID_IDirect3DRMObjectArray,     NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6401         { &IID_IDirect3DRMDeviceArray,     NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6402         { &IID_IDirect3DRMViewportArray,   NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6403         { &IID_IDirect3DRMFrameArray,      NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6404         { &IID_IDirect3DRMVisualArray,     NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6405         { &IID_IDirect3DRMLightArray,      NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6406         { &IID_IDirect3DRMPickedArray,     NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6407         { &IID_IDirect3DRMFaceArray,       NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6408         { &IID_IDirect3DRMAnimationArray,  NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6409         { &IID_IDirect3DRMUserVisual,      NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6410         { &IID_IDirect3DRMShadow,          NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6411         { &IID_IDirect3DRMShadow2,         NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6412         { &IID_IDirect3DRMInterpolator,    NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6413         { &IID_IDirect3DRMProgressiveMesh, NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6414         { &IID_IDirect3DRMPicked2Array,    NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6415         { &IID_IDirect3DRMClippedVisual,   NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6416         { &IID_IDirectDrawClipper,         NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6417         { &IID_IDirectDrawSurface7,        NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6418         { &IID_IDirectDrawSurface4,        NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6419         { &IID_IDirectDrawSurface3,        NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6420         { &IID_IDirectDrawSurface2,        NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6421         { &IID_IDirectDrawSurface,         NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6422         { &IID_IDirect3DDevice7,           NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6423         { &IID_IDirect3DDevice3,           NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6424         { &IID_IDirect3DDevice2,           NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6425         { &IID_IDirect3DDevice,            NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6426         { &IID_IDirect3D7,                 NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6427         { &IID_IDirect3D3,                 NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6428         { &IID_IDirect3D2,                 NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6429         { &IID_IDirect3D,                  NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6430         { &IID_IDirectDraw7,               NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6431         { &IID_IDirectDraw4,               NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6432         { &IID_IDirectDraw3,               NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6433         { &IID_IDirectDraw2,               NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6434         { &IID_IDirectDraw,                NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6435         { &IID_IDirect3DLight,             NULL,          NULL,                     CLASS_E_CLASSNOTAVAILABLE },
6436         { &IID_IUnknown,                   &IID_IUnknown, NULL,                     S_OK,                     },
6437     };
6438     HRESULT hr;
6439     IDirect3DRM *d3drm1;
6440     IDirect3DRM2 *d3drm2;
6441     IDirect3DRM3 *d3drm3;
6442     IDirect3DRMTexture *texture1;
6443     IDirect3DRMTexture2 *texture2;
6444     IDirect3DRMTexture3 *texture3;
6445     IUnknown *unknown;
6446     char *filename;
6447     BOOL check;
6448 
6449     hr = Direct3DRMCreate(&d3drm1);
6450     ok(SUCCEEDED(hr), "Cannot get IDirect3DRM interface (hr = %#x)\n", hr);
6451     filename = create_bitmap(1, 1, TRUE);
6452     hr = IDirect3DRM_LoadTexture(d3drm1, filename, &texture1);
6453     ok(SUCCEEDED(hr), "Failed to load texture (hr = %#x).\n", hr);
6454     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMTexture interface (hr = %#x)\n", hr);
6455     hr = IDirect3DRMTexture_QueryInterface(texture1, &IID_IUnknown, (void **)&unknown);
6456     ok(SUCCEEDED(hr), "Cannot get IUnknown interface from IDirect3DRMTexture (hr = %#x)\n", hr);
6457     IDirect3DRMTexture_Release(texture1);
6458     test_qi("texture1_qi", unknown, &IID_IUnknown, tests, ARRAY_SIZE(tests));
6459     IUnknown_Release(unknown);
6460 
6461     hr = IDirect3DRM_QueryInterface(d3drm1, &IID_IDirect3DRM2, (void **)&d3drm2);
6462     ok(SUCCEEDED(hr), "Cannot get IDirect3DRM2 interface (hr = %#x).\n", hr);
6463     hr = IDirect3DRM2_LoadTexture(d3drm2, filename, &texture2);
6464     ok(SUCCEEDED(hr), "Failed to load texture (hr = %#x).\n", hr);
6465     hr = IDirect3DRMTexture2_QueryInterface(texture2, &IID_IUnknown, (void **)&unknown);
6466     ok(SUCCEEDED(hr), "Cannot get IUnknown interface from IDirect3DRMTexture2 (hr = %#x)\n", hr);
6467     IDirect3DRMTexture2_Release(texture2);
6468     test_qi("texture2_qi", unknown, &IID_IUnknown, tests, ARRAY_SIZE(tests));
6469     IUnknown_Release(unknown);
6470 
6471     hr = IDirect3DRM_QueryInterface(d3drm1, &IID_IDirect3DRM3, (void **)&d3drm3);
6472     ok(SUCCEEDED(hr), "Cannot get IDirect3DRM3 interface (hr = %#x).\n", hr);
6473     hr = IDirect3DRM3_LoadTexture(d3drm3, filename, &texture3);
6474     ok(SUCCEEDED(hr), "Failed to load texture (hr = %#x).\n", hr);
6475     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMTexture3 interface (hr = %#x)\n", hr);
6476     hr = IDirect3DRMTexture3_QueryInterface(texture3, &IID_IUnknown, (void **)&unknown);
6477     ok(SUCCEEDED(hr), "Cannot get IUnknown interface from IDirect3DRMTexture3 (hr = %#x)\n", hr);
6478     IDirect3DRMTexture3_Release(texture3);
6479     test_qi("texture3_qi", unknown, &IID_IUnknown, tests, ARRAY_SIZE(tests));
6480     IUnknown_Release(unknown);
6481 
6482     IDirect3DRM3_Release(d3drm3);
6483     IDirect3DRM2_Release(d3drm2);
6484     IDirect3DRM_Release(d3drm1);
6485     check = DeleteFileA(filename);
6486     ok(check, "Cannot delete image stored in %s (error = %d).\n", filename, GetLastError());
6487     HeapFree(GetProcessHeap(), 0, filename);
6488 }
6489 
test_viewport_qi(void)6490 static void test_viewport_qi(void)
6491 {
6492     IDirect3DRM *d3drm1;
6493     IDirect3DRM2 *d3drm2;
6494     IDirect3DRM3 *d3drm3;
6495     IDirect3DRMFrame *frame1, *camera1;
6496     IDirect3DRMFrame3 *frame3, *camera3;
6497     IDirect3DRMDevice *device1;
6498     IDirect3DRMDevice3 *device3;
6499     IDirectDrawClipper *clipper;
6500     IDirect3DRMViewport *viewport1;
6501     IDirect3DRMViewport2 *viewport2;
6502     IUnknown *unknown;
6503     GUID driver = IID_IDirect3DRGBDevice;
6504     HRESULT hr;
6505 
6506     static const struct qi_test tests[] =
6507     {
6508         { &IID_IDirect3DRM3,               NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6509         { &IID_IDirect3DRM2,               NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6510         { &IID_IDirect3DRM,                NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6511         { &IID_IDirect3DRMDevice,          NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6512         { &IID_IDirect3DRMDevice2,         NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6513         { &IID_IDirect3DRMDevice3,         NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6514         { &IID_IDirect3DRMWinDevice,       NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6515         { &IID_IDirect3DRMObject,          &IID_IUnknown, &IID_IDirect3DRMViewport,  S_OK                      },
6516         { &IID_IDirect3DRMViewport,        &IID_IUnknown, &IID_IDirect3DRMViewport,  S_OK                      },
6517         { &IID_IDirect3DRMViewport2,       &IID_IUnknown, &IID_IDirect3DRMViewport2, S_OK                      },
6518         { &IID_IDirect3DRMFrame,           NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6519         { &IID_IDirect3DRMFrame2,          NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6520         { &IID_IDirect3DRMFrame3,          NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6521         { &IID_IDirect3DRMVisual,          NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6522         { &IID_IDirect3DRMMesh,            NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6523         { &IID_IDirect3DRMMeshBuilder,     NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6524         { &IID_IDirect3DRMMeshBuilder2,    NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6525         { &IID_IDirect3DRMMeshBuilder3,    NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6526         { &IID_IDirect3DRMFace,            NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6527         { &IID_IDirect3DRMFace2,           NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6528         { &IID_IDirect3DRMLight,           NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6529         { &IID_IDirect3DRMTexture,         NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6530         { &IID_IDirect3DRMTexture2,        NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6531         { &IID_IDirect3DRMTexture3,        NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6532         { &IID_IDirect3DRMWrap,            NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6533         { &IID_IDirect3DRMMaterial,        NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6534         { &IID_IDirect3DRMMaterial2,       NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6535         { &IID_IDirect3DRMAnimation,       NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6536         { &IID_IDirect3DRMAnimation2,      NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6537         { &IID_IDirect3DRMAnimationSet,    NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6538         { &IID_IDirect3DRMAnimationSet2,   NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6539         { &IID_IDirect3DRMObjectArray,     NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6540         { &IID_IDirect3DRMDeviceArray,     NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6541         { &IID_IDirect3DRMViewportArray,   NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6542         { &IID_IDirect3DRMFrameArray,      NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6543         { &IID_IDirect3DRMVisualArray,     NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6544         { &IID_IDirect3DRMLightArray,      NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6545         { &IID_IDirect3DRMPickedArray,     NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6546         { &IID_IDirect3DRMFaceArray,       NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6547         { &IID_IDirect3DRMAnimationArray,  NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6548         { &IID_IDirect3DRMUserVisual,      NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6549         { &IID_IDirect3DRMShadow,          NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6550         { &IID_IDirect3DRMShadow2,         NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6551         { &IID_IDirect3DRMInterpolator,    NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6552         { &IID_IDirect3DRMProgressiveMesh, NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6553         { &IID_IDirect3DRMPicked2Array,    NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6554         { &IID_IDirect3DRMClippedVisual,   NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6555         { &IID_IDirectDrawClipper,         NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6556         { &IID_IDirectDrawSurface7,        NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6557         { &IID_IDirectDrawSurface4,        NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6558         { &IID_IDirectDrawSurface3,        NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6559         { &IID_IDirectDrawSurface2,        NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6560         { &IID_IDirectDrawSurface,         NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6561         { &IID_IDirect3DDevice7,           NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6562         { &IID_IDirect3DDevice3,           NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6563         { &IID_IDirect3DDevice2,           NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6564         { &IID_IDirect3DDevice,            NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6565         { &IID_IDirect3D7,                 NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6566         { &IID_IDirect3D3,                 NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6567         { &IID_IDirect3D2,                 NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6568         { &IID_IDirect3D,                  NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6569         { &IID_IDirectDraw7,               NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6570         { &IID_IDirectDraw4,               NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6571         { &IID_IDirectDraw3,               NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6572         { &IID_IDirectDraw2,               NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6573         { &IID_IDirectDraw,                NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6574         { &IID_IDirect3DLight,             NULL,          NULL,                      CLASS_E_CLASSNOTAVAILABLE },
6575         { &IID_IUnknown,                   &IID_IUnknown, NULL,                      S_OK,                     },
6576     };
6577 
6578     hr = DirectDrawCreateClipper(0, &clipper, NULL);
6579     ok(SUCCEEDED(hr), "Cannot get IDirectDrawClipper interface (hr = %#x).\n", hr);
6580 
6581     hr = Direct3DRMCreate(&d3drm1);
6582     ok(SUCCEEDED(hr), "Cannot get IDirect3DRM interface (hr = %#x).\n", hr);
6583 
6584     hr = IDirect3DRM_CreateDeviceFromClipper(d3drm1, clipper, &driver, 640, 480, &device1);
6585     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMDevice interface (hr = %#x).\n", hr);
6586     hr = IDirect3DRM_CreateFrame(d3drm1, NULL, &frame1);
6587     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMFrame interface (hr = %#x)\n", hr);
6588     hr = IDirect3DRM_CreateFrame(d3drm1, frame1, &camera1);
6589     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMFrame interface (hr = %#x)\n", hr);
6590     hr = IDirect3DRM_CreateViewport(d3drm1, device1, camera1, 0, 0, 640, 480, &viewport1);
6591     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMViewport interface (hr = %#x)\n", hr);
6592     hr = IDirect3DRMViewport_QueryInterface(viewport1, &IID_IUnknown, (void **)&unknown);
6593     ok(SUCCEEDED(hr), "Cannot get IUnknown interface (hr = %#x).\n", hr);
6594     IDirect3DRMViewport_Release(viewport1);
6595     test_qi("viewport1_qi", unknown, &IID_IUnknown, tests, ARRAY_SIZE(tests));
6596     IUnknown_Release(unknown);
6597 
6598     hr = IDirect3DRM_QueryInterface(d3drm1, &IID_IDirect3DRM2, (void **)&d3drm2);
6599     ok(SUCCEEDED(hr), "Cannot get IDirect3DRM2 interface (hr = %#x).\n", hr);
6600     hr = IDirect3DRM2_CreateViewport(d3drm2, device1, camera1, 0, 0, 640, 480, &viewport1);
6601     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMViewport interface (hr = %#x)\n", hr);
6602     hr = IDirect3DRMViewport_QueryInterface(viewport1, &IID_IUnknown, (void **)&unknown);
6603     ok(SUCCEEDED(hr), "Cannot get IUnknown interface (hr = %#x).\n", hr);
6604     IDirect3DRMViewport_Release(viewport1);
6605     test_qi("viewport1_qi", unknown, &IID_IUnknown, tests, ARRAY_SIZE(tests));
6606     IUnknown_Release(unknown);
6607     IDirect3DRMDevice_Release(device1);
6608     IDirect3DRMFrame_Release(camera1);
6609     IDirect3DRMFrame_Release(frame1);
6610 
6611     hr = IDirect3DRM_QueryInterface(d3drm1, &IID_IDirect3DRM3, (void **)&d3drm3);
6612     ok(SUCCEEDED(hr), "Cannot get IDirect3DRM3 interface (hr = %#x).\n", hr);
6613     hr = IDirect3DRM3_CreateDeviceFromClipper(d3drm3, clipper, &driver, 640, 480, &device3);
6614     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMDevice3 interface (hr = %#x).\n", hr);
6615     hr = IDirect3DRM3_CreateFrame(d3drm3, NULL, &frame3);
6616     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMFrame3 interface (hr = %#x)\n", hr);
6617     hr = IDirect3DRM3_CreateFrame(d3drm3, frame3, &camera3);
6618     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMFrame3 interface (hr = %#x)\n", hr);
6619     hr = IDirect3DRM3_CreateViewport(d3drm3, device3, camera3, 0, 0, 640, 480, &viewport2);
6620     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMViewport2 interface (hr = %#x)\n", hr);
6621     hr = IDirect3DRMViewport2_QueryInterface(viewport2, &IID_IUnknown, (void **)&unknown);
6622     ok(SUCCEEDED(hr), "Cannot get IUnknown interface (hr = %#x).\n", hr);
6623     IDirect3DRMViewport_Release(viewport2);
6624     test_qi("viewport2_qi", unknown, &IID_IUnknown, tests, ARRAY_SIZE(tests));
6625     IUnknown_Release(unknown);
6626     IDirect3DRMDevice3_Release(device3);
6627     IDirect3DRMFrame3_Release(camera3);
6628     IDirect3DRMFrame3_Release(frame3);
6629 
6630     IDirectDrawClipper_Release(clipper);
6631     IDirect3DRM3_Release(d3drm3);
6632     IDirect3DRM2_Release(d3drm2);
6633     IDirect3DRM_Release(d3drm1);
6634 }
6635 
get_surface_color(IDirectDrawSurface * surface,UINT x,UINT y)6636 static D3DCOLOR get_surface_color(IDirectDrawSurface *surface, UINT x, UINT y)
6637 {
6638     RECT rect = { x, y, x + 1, y + 1 };
6639     DDSURFACEDESC surface_desc;
6640     D3DCOLOR color;
6641     HRESULT hr;
6642 
6643     memset(&surface_desc, 0, sizeof(surface_desc));
6644     surface_desc.dwSize = sizeof(surface_desc);
6645 
6646     hr = IDirectDrawSurface_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
6647     ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6648     if (FAILED(hr))
6649         return 0xdeadbeef;
6650 
6651     color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
6652 
6653     hr = IDirectDrawSurface_Unlock(surface, NULL);
6654     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6655 
6656     return color;
6657 }
6658 
create_device2_without_ds(IDirectDraw2 * ddraw,HWND window)6659 static IDirect3DDevice2 *create_device2_without_ds(IDirectDraw2 *ddraw, HWND window)
6660 {
6661     IDirectDrawSurface *surface;
6662     IDirect3DDevice2 *device = NULL;
6663     DDSURFACEDESC surface_desc;
6664     IDirect3D2 *d3d;
6665     HRESULT hr;
6666     RECT rc;
6667 
6668     GetClientRect(window, &rc);
6669     hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6670     ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6671 
6672     memset(&surface_desc, 0, sizeof(surface_desc));
6673     surface_desc.dwSize = sizeof(surface_desc);
6674     surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6675     surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
6676     surface_desc.dwWidth = rc.right;
6677     surface_desc.dwHeight = rc.bottom;
6678 
6679     hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6680     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6681 
6682     hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d);
6683     if (FAILED(hr))
6684     {
6685         IDirectDrawSurface_Release(surface);
6686         return NULL;
6687     }
6688 
6689     IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device);
6690 
6691     IDirect3D2_Release(d3d);
6692     IDirectDrawSurface_Release(surface);
6693     return device;
6694 }
6695 
compare_color(D3DCOLOR c1,D3DCOLOR c2,BYTE max_diff)6696 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
6697 {
6698     if ((c1 & 0xff) - (c2 & 0xff) > max_diff) return FALSE;
6699     c1 >>= 8; c2 >>= 8;
6700     if ((c1 & 0xff) - (c2 & 0xff) > max_diff) return FALSE;
6701     c1 >>= 8; c2 >>= 8;
6702     if ((c1 & 0xff) - (c2 & 0xff) > max_diff) return FALSE;
6703     c1 >>= 8; c2 >>= 8;
6704     if ((c1 & 0xff) - (c2 & 0xff) > max_diff) return FALSE;
6705     return TRUE;
6706 }
6707 
clear_depth_surface(IDirectDrawSurface * surface,DWORD value)6708 static void clear_depth_surface(IDirectDrawSurface *surface, DWORD value)
6709 {
6710     HRESULT hr;
6711     DDBLTFX fx;
6712 
6713     memset(&fx, 0, sizeof(fx));
6714     fx.dwSize = sizeof(fx);
6715     U5(fx).dwFillDepth = value;
6716 
6717     hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
6718     ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
6719 }
6720 
set_execute_data(IDirect3DExecuteBuffer * execute_buffer,UINT vertex_count,UINT offset,UINT len)6721 static void set_execute_data(IDirect3DExecuteBuffer *execute_buffer, UINT vertex_count, UINT offset, UINT len)
6722 {
6723     D3DEXECUTEDATA exec_data;
6724     HRESULT hr;
6725 
6726     memset(&exec_data, 0, sizeof(exec_data));
6727     exec_data.dwSize = sizeof(exec_data);
6728     exec_data.dwVertexCount = vertex_count;
6729     exec_data.dwInstructionOffset = offset;
6730     exec_data.dwInstructionLength = len;
6731     hr = IDirect3DExecuteBuffer_SetExecuteData(execute_buffer, &exec_data);
6732     ok(SUCCEEDED(hr), "Failed to set execute data, hr %#x.\n", hr);
6733 }
6734 
emit_set_ts(void ** ptr,D3DTRANSFORMSTATETYPE state,DWORD value)6735 static void emit_set_ts(void **ptr, D3DTRANSFORMSTATETYPE state, DWORD value)
6736 {
6737     D3DINSTRUCTION *inst = *ptr;
6738     D3DSTATE *ts = (D3DSTATE *)(inst + 1);
6739 
6740     inst->bOpcode = D3DOP_STATETRANSFORM;
6741     inst->bSize = sizeof(*ts);
6742     inst->wCount = 1;
6743 
6744     U1(*ts).dtstTransformStateType = state;
6745     U2(*ts).dwArg[0] = value;
6746 
6747     *ptr = ts + 1;
6748 }
6749 
emit_set_rs(void ** ptr,D3DRENDERSTATETYPE state,DWORD value)6750 static void emit_set_rs(void **ptr, D3DRENDERSTATETYPE state, DWORD value)
6751 {
6752     D3DINSTRUCTION *inst = *ptr;
6753     D3DSTATE *rs = (D3DSTATE *)(inst + 1);
6754 
6755     inst->bOpcode = D3DOP_STATERENDER;
6756     inst->bSize = sizeof(*rs);
6757     inst->wCount = 1;
6758 
6759     U1(*rs).drstRenderStateType = state;
6760     U2(*rs).dwArg[0] = value;
6761 
6762     *ptr = rs + 1;
6763 }
6764 
emit_process_vertices(void ** ptr,DWORD flags,WORD base_idx,DWORD vertex_count)6765 static void emit_process_vertices(void **ptr, DWORD flags, WORD base_idx, DWORD vertex_count)
6766 {
6767     D3DINSTRUCTION *inst = *ptr;
6768     D3DPROCESSVERTICES *pv = (D3DPROCESSVERTICES *)(inst + 1);
6769 
6770     inst->bOpcode = D3DOP_PROCESSVERTICES;
6771     inst->bSize = sizeof(*pv);
6772     inst->wCount = 1;
6773 
6774     pv->dwFlags = flags;
6775     pv->wStart = base_idx;
6776     pv->wDest = 0;
6777     pv->dwCount = vertex_count;
6778     pv->dwReserved = 0;
6779 
6780     *ptr = pv + 1;
6781 }
6782 
emit_tquad(void ** ptr,WORD base_idx)6783 static void emit_tquad(void **ptr, WORD base_idx)
6784 {
6785     D3DINSTRUCTION *inst = *ptr;
6786     D3DTRIANGLE *tri = (D3DTRIANGLE *)(inst + 1);
6787 
6788     inst->bOpcode = D3DOP_TRIANGLE;
6789     inst->bSize = sizeof(*tri);
6790     inst->wCount = 2;
6791 
6792     U1(*tri).v1 = base_idx;
6793     U2(*tri).v2 = base_idx + 1;
6794     U3(*tri).v3 = base_idx + 2;
6795     tri->wFlags = D3DTRIFLAG_START;
6796     ++tri;
6797 
6798     U1(*tri).v1 = base_idx + 2;
6799     U2(*tri).v2 = base_idx + 1;
6800     U3(*tri).v3 = base_idx + 3;
6801     tri->wFlags = D3DTRIFLAG_ODD;
6802     ++tri;
6803 
6804     *ptr = tri;
6805 }
6806 
emit_end(void ** ptr)6807 static void emit_end(void **ptr)
6808 {
6809     D3DINSTRUCTION *inst = *ptr;
6810 
6811     inst->bOpcode = D3DOP_EXIT;
6812     inst->bSize = 0;
6813     inst->wCount = 0;
6814 
6815     *ptr = inst + 1;
6816 }
6817 
d3d_draw_quad1(IDirect3DDevice * device,IDirect3DViewport * viewport)6818 static void d3d_draw_quad1(IDirect3DDevice *device, IDirect3DViewport *viewport)
6819 {
6820     IDirect3DExecuteBuffer *execute_buffer;
6821     D3DEXECUTEBUFFERDESC exec_desc;
6822     HRESULT hr;
6823     void *ptr;
6824     UINT inst_length;
6825     D3DMATRIXHANDLE world_handle, view_handle, proj_handle;
6826     static D3DMATRIX mat =
6827     {
6828         1.0f, 0.0f, 0.0f, 0.0f,
6829         0.0f, 1.0f, 0.0f, 0.0f,
6830         0.0f, 0.0f, 1.0f, 0.0f,
6831         0.0f, 0.0f, 0.0f, 1.0f,
6832     };
6833     static const D3DLVERTEX quad_strip[] =
6834     {
6835         {{-1.0f}, {-1.0f}, {0.00f}, 0, {0xffbada55}, {0}, {0.0f}, {0.0f}},
6836         {{-1.0f}, { 1.0f}, {0.00f}, 0, {0xffbada55}, {0}, {0.0f}, {0.0f}},
6837         {{ 1.0f}, {-1.0f}, {1.00f}, 0, {0xffbada55}, {0}, {0.0f}, {0.0f}},
6838         {{ 1.0f}, { 1.0f}, {1.00f}, 0, {0xffbada55}, {0}, {0.0f}, {0.0f}},
6839     };
6840 
6841     hr = IDirect3DDevice_CreateMatrix(device, &world_handle);
6842     ok(hr == D3D_OK, "Creating a matrix object failed, hr %#x.\n", hr);
6843     hr = IDirect3DDevice_SetMatrix(device, world_handle, &mat);
6844     ok(hr == D3D_OK, "Setting a matrix object failed, hr %#x.\n", hr);
6845     hr = IDirect3DDevice_CreateMatrix(device, &view_handle);
6846     ok(hr == D3D_OK, "Creating a matrix object failed, hr %#x.\n", hr);
6847     hr = IDirect3DDevice_SetMatrix(device, view_handle, &mat);
6848     ok(hr == D3D_OK, "Setting a matrix object failed, hr %#x.\n", hr);
6849     hr = IDirect3DDevice_CreateMatrix(device, &proj_handle);
6850     ok(hr == D3D_OK, "Creating a matrix object failed, hr %#x.\n", hr);
6851     hr = IDirect3DDevice_SetMatrix(device, proj_handle, &mat);
6852     ok(hr == D3D_OK, "Setting a matrix object failed, hr %#x.\n", hr);
6853 
6854     memset(&exec_desc, 0, sizeof(exec_desc));
6855     exec_desc.dwSize = sizeof(exec_desc);
6856     exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
6857     exec_desc.dwBufferSize = 1024;
6858     exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
6859 
6860     hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
6861     ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
6862 
6863     hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
6864     ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
6865 
6866     memcpy(exec_desc.lpData, quad_strip, sizeof(quad_strip));
6867     ptr = ((BYTE *)exec_desc.lpData) + sizeof(quad_strip);
6868     emit_set_ts(&ptr, D3DTRANSFORMSTATE_WORLD, world_handle);
6869     emit_set_ts(&ptr, D3DTRANSFORMSTATE_VIEW, view_handle);
6870     emit_set_ts(&ptr, D3DTRANSFORMSTATE_PROJECTION, proj_handle);
6871     emit_set_rs(&ptr, D3DRENDERSTATE_CLIPPING, FALSE);
6872     emit_set_rs(&ptr, D3DRENDERSTATE_ZENABLE, TRUE);
6873     emit_set_rs(&ptr, D3DRENDERSTATE_FOGENABLE, FALSE);
6874     emit_set_rs(&ptr, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
6875     emit_set_rs(&ptr, D3DRENDERSTATE_SHADEMODE, D3DSHADE_FLAT);
6876 
6877     emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORM, 0, 4);
6878     emit_tquad(&ptr, 0);
6879 
6880     emit_end(&ptr);
6881     inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
6882     inst_length -= sizeof(quad_strip);
6883 
6884     hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
6885     ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
6886 
6887     hr = IDirect3DDevice_BeginScene(device);
6888     set_execute_data(execute_buffer, 4, sizeof(quad_strip), inst_length);
6889     hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
6890     ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
6891     hr = IDirect3DDevice_EndScene(device);
6892     ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6893 
6894     IDirect3DExecuteBuffer_Release(execute_buffer);
6895 }
6896 
test_viewport_clear1(void)6897 static void test_viewport_clear1(void)
6898 {
6899     DDSCAPS caps = { DDSCAPS_ZBUFFER };
6900     IDirectDraw *ddraw;
6901     IDirectDrawClipper *clipper;
6902     IDirect3DRM *d3drm1;
6903     IDirect3DRMFrame *frame1, *camera1;
6904     IDirect3DRMDevice *device1;
6905     IDirect3DViewport *d3d_viewport;
6906     IDirect3DRMViewport *viewport1;
6907     IDirect3DDevice *d3d_device1;
6908     IDirectDrawSurface *surface, *ds, *d3drm_ds;
6909     HWND window;
6910     GUID driver = IID_IDirect3DRGBDevice;
6911     HRESULT hr;
6912     D3DCOLOR ret_color;
6913     RECT rc;
6914 
6915     window = create_window();
6916     GetClientRect(window, &rc);
6917 
6918     hr = DirectDrawCreate(NULL, &ddraw, NULL);
6919     ok(SUCCEEDED(hr), "Cannot create IDirectDraw interface (hr = %#x).\n", hr);
6920 
6921     hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6922     ok(SUCCEEDED(hr), "Failed to set cooperative level (hr = %#x).\n", hr);
6923 
6924     hr = IDirectDraw_CreateClipper(ddraw, 0, &clipper, NULL);
6925     ok(SUCCEEDED(hr), "Cannot create clipper (hr = %#x).\n", hr);
6926 
6927     hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
6928     ok(SUCCEEDED(hr), "Cannot set HWnd to Clipper (hr = %#x)\n", hr);
6929 
6930     hr = Direct3DRMCreate(&d3drm1);
6931     ok(SUCCEEDED(hr), "Cannot get IDirect3DRM interface (hr = %#x).\n", hr);
6932 
6933     hr = IDirect3DRM_CreateDeviceFromClipper(d3drm1, clipper, &driver, rc.right, rc.bottom, &device1);
6934     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMDevice interface (hr = %#x)\n", hr);
6935 
6936     hr = IDirect3DRM_CreateFrame(d3drm1, NULL, &frame1);
6937     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMFrame interface (hr = %#x)\n", hr);
6938     hr = IDirect3DRM_CreateFrame(d3drm1, frame1, &camera1);
6939     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMFrame interface (hr = %#x)\n", hr);
6940 
6941     hr = IDirect3DRM_CreateViewport(d3drm1, device1, camera1, 0, 0, rc.right,
6942             rc.bottom, &viewport1);
6943     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMViewport2 interface (hr = %#x)\n", hr);
6944 
6945     /* Fetch immediate mode device and viewport */
6946     hr = IDirect3DRMDevice_GetDirect3DDevice(device1, &d3d_device1);
6947     ok(SUCCEEDED(hr), "Cannot get IDirect3DDevice interface (hr = %#x).\n", hr);
6948     hr = IDirect3DRMViewport_GetDirect3DViewport(viewport1, &d3d_viewport);
6949     ok(SUCCEEDED(hr), "Cannot get IDirect3DViewport interface (hr = %#x).\n", hr);
6950 
6951     hr = IDirect3DDevice_QueryInterface(d3d_device1, &IID_IDirectDrawSurface, (void **)&surface);
6952     ok(SUCCEEDED(hr), "Cannot get surface to the render target (hr = %#x).\n", hr);
6953 
6954     ret_color = get_surface_color(surface, 320, 240);
6955     ok(compare_color(ret_color, 0, 1), "Got unexpected color 0x%08x.\n", ret_color);
6956 
6957     /* Clear uses the scene frame's background color. */
6958     hr = IDirect3DRMFrame_SetSceneBackgroundRGB(frame1, 1.0f, 1.0f, 1.0f);
6959     ok(SUCCEEDED(hr), "Cannot set scene background RGB (hr = %#x)\n", hr);
6960     ret_color = IDirect3DRMFrame_GetSceneBackground(frame1);
6961     ok(ret_color == 0xffffffff, "Expected scene color returned == 0xffffffff, got %#x.\n", ret_color);
6962     hr = IDirect3DRMFrame_SetSceneBackgroundRGB(camera1, 0.0f, 1.0f, 0.0f);
6963     ok(SUCCEEDED(hr), "Cannot set scene background RGB (hr = %#x)\n", hr);
6964     ret_color = IDirect3DRMFrame_GetSceneBackground(camera1);
6965     ok(ret_color == 0xff00ff00, "Expected scene color returned == 0xff00ff00, got %#x.\n", ret_color);
6966 
6967     CHECK_REFCOUNT(frame1, 1);
6968     hr = IDirect3DRMViewport_Clear(viewport1);
6969     ok(SUCCEEDED(hr), "Cannot clear viewport (hr = %#x).\n", hr);
6970     ret_color = get_surface_color(surface, 320, 240);
6971     ok(compare_color(ret_color, 0x00ffffff, 1), "Got unexpected color 0x%08x.\n", ret_color);
6972     CHECK_REFCOUNT(frame1, 1);
6973 
6974     hr = IDirect3DRMFrame_SetSceneBackgroundRGB(frame1, 0.0f, 0.0f, 1.0f);
6975     ok(SUCCEEDED(hr), "Cannot set scene background RGB (hr = %#x)\n", hr);
6976     ret_color = IDirect3DRMFrame_GetSceneBackground(frame1);
6977     ok(ret_color == 0xff0000ff, "Expected scene color returned == 0xff00ff00, got %#x.\n", ret_color);
6978 
6979     hr = IDirect3DRMViewport_Configure(viewport1, 0, 0, rc.right, rc.bottom);
6980     todo_wine ok(SUCCEEDED(hr), "Cannot configure viewport (hr = %#x).\n", hr);
6981     hr = IDirect3DRMViewport_Clear(viewport1);
6982     ok(SUCCEEDED(hr), "Cannot clear viewport (hr = %#x).\n", hr);
6983     ret_color = get_surface_color(surface, 100, 200);
6984     ok(compare_color(ret_color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", ret_color);
6985 
6986     d3d_draw_quad1(d3d_device1, d3d_viewport);
6987 
6988     ret_color = get_surface_color(surface, 100, 200);
6989     ok(compare_color(ret_color, 0x00bada55, 1), "Got unexpected color 0x%08x.\n", ret_color);
6990 
6991     hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &ds);
6992     ok(SUCCEEDED(hr), "Cannot get attached depth surface (hr = %x).\n", hr);
6993 
6994     hr = IDirect3DRMViewport_Configure(viewport1, 0, 0, rc.right, rc.bottom);
6995     todo_wine ok(SUCCEEDED(hr), "Cannot configure viewport (hr = %#x).\n", hr);
6996     hr = IDirect3DRMViewport_Clear(viewport1);
6997     ok(SUCCEEDED(hr), "Cannot clear viewport (hr = %#x).\n", hr);
6998     ret_color = get_surface_color(surface, 100, 200);
6999     ok(compare_color(ret_color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", ret_color);
7000 
7001     /* Fill the depth surface with a value lower than the quad's depth value. */
7002     clear_depth_surface(ds, 0x7fff);
7003 
7004     /* Depth test passes here */
7005     d3d_draw_quad1(d3d_device1, d3d_viewport);
7006     ret_color = get_surface_color(surface, 100, 200);
7007     ok(compare_color(ret_color, 0x00bada55, 1), "Got unexpected color 0x%08x.\n", ret_color);
7008     /* Depth test fails here */
7009     ret_color = get_surface_color(surface, 500, 400);
7010     ok(compare_color(ret_color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", ret_color);
7011 
7012     /* Check what happens if we release the depth surface that d3drm created, and clear the viewport */
7013     hr = IDirectDrawSurface_DeleteAttachedSurface(surface, 0, ds);
7014     ok(SUCCEEDED(hr), "Cannot delete attached surface (hr = %#x).\n", hr);
7015     d3drm_ds = (IDirectDrawSurface *)0xdeadbeef;
7016     hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &d3drm_ds);
7017     ok(hr == DDERR_NOTFOUND, "Expected hr == DDERR_NOTFOUND, got %#x.\n", hr);
7018     ok(d3drm_ds == NULL, "Expected NULL z-surface, got %p.\n", d3drm_ds);
7019 
7020     clear_depth_surface(ds, 0x7fff);
7021     hr = IDirect3DRMViewport_Configure(viewport1, 0, 0, rc.right, rc.bottom);
7022     todo_wine ok(SUCCEEDED(hr), "Cannot configure viewport (hr = %#x).\n", hr);
7023     hr = IDirect3DRMViewport_Clear(viewport1);
7024     ok(SUCCEEDED(hr), "Cannot clear viewport (hr = %#x).\n", hr);
7025 
7026     ret_color = get_surface_color(surface, 100, 200);
7027     ok(compare_color(ret_color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", ret_color);
7028 
7029     hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
7030     ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
7031     IDirectDrawSurface_Release(ds);
7032 
7033     d3d_draw_quad1(d3d_device1, d3d_viewport);
7034 
7035     ret_color = get_surface_color(surface, 100, 200);
7036     ok(compare_color(ret_color, 0x00bada55, 1), "Got unexpected color 0x%08x.\n", ret_color);
7037     ret_color = get_surface_color(surface, 500, 400);
7038     ok(compare_color(ret_color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", ret_color);
7039 
7040     IDirect3DViewport_Release(d3d_viewport);
7041     IDirectDrawSurface_Release(surface);
7042     IDirect3DDevice_Release(d3d_device1);
7043     IDirect3DRMViewport_Release(viewport1);
7044     IDirect3DRMFrame_Release(frame1);
7045     IDirect3DRMFrame_Release(camera1);
7046     IDirect3DRMDevice_Release(device1);
7047     IDirect3DRM_Release(d3drm1);
7048     IDirectDrawClipper_Release(clipper);
7049     IDirectDraw_Release(ddraw);
7050     DestroyWindow(window);
7051 }
7052 
draw_quad2(IDirect3DDevice2 * device,IDirect3DViewport * viewport)7053 static void draw_quad2(IDirect3DDevice2 *device, IDirect3DViewport *viewport)
7054 {
7055     static D3DLVERTEX tquad[] =
7056     {
7057         {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffbada55}, {0}, {0.0f}, {0.0f}},
7058         {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xffbada55}, {0}, {0.0f}, {1.0f}},
7059         {{ 1.0f}, {-1.0f}, {1.0f}, 0, {0xffbada55}, {0}, {1.0f}, {0.0f}},
7060         {{ 1.0f}, { 1.0f}, {1.0f}, 0, {0xffbada55}, {0}, {1.0f}, {1.0f}},
7061     };
7062     static D3DMATRIX mat =
7063     {
7064         1.0f, 0.0f, 0.0f, 0.0f,
7065         0.0f, 1.0f, 0.0f, 0.0f,
7066         0.0f, 0.0f, 1.0f, 0.0f,
7067         0.0f, 0.0f, 0.0f, 1.0f,
7068     };
7069     IDirect3DViewport2 *viewport2;
7070     HRESULT hr;
7071 
7072     hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
7073     ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
7074     hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
7075     ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
7076     hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
7077     ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
7078 
7079     hr = IDirect3DViewport_QueryInterface(viewport, &IID_IDirect3DViewport2, (void **)&viewport2);
7080     ok(SUCCEEDED(hr), "Cannot get IDirect3DViewport2 interface (hr = %#x).\n", hr);
7081     hr = IDirect3DDevice2_SetCurrentViewport(device, viewport2);
7082     ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
7083     IDirect3DViewport2_Release(viewport2);
7084 
7085     hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_TRUE);
7086     ok(SUCCEEDED(hr), "Failed to enable z testing, hr %#x.\n", hr);
7087     hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
7088     ok(SUCCEEDED(hr), "Failed to set the z function, hr %#x.\n", hr);
7089 
7090     hr = IDirect3DDevice2_BeginScene(device);
7091     ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
7092     hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, tquad, 4, 0);
7093     ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7094     hr = IDirect3DDevice2_EndScene(device);
7095     ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
7096 }
7097 
test_viewport_clear2(void)7098 static void test_viewport_clear2(void)
7099 {
7100     DDSCAPS caps = { DDSCAPS_ZBUFFER };
7101     IDirect3D2 *d3d2;
7102     IDirectDraw *ddraw1;
7103     IDirectDraw2 *ddraw2;
7104     IDirectDrawClipper *clipper;
7105     IDirect3DRM *d3drm1;
7106     IDirect3DRM3 *d3drm3;
7107     IDirect3DRMFrame3 *frame3, *camera3;
7108     IDirect3DRMDevice3 *device3;
7109     IDirect3DViewport *d3d_viewport;
7110     IDirect3DRMViewport2 *viewport2;
7111     IDirect3DDevice2 *d3d_device2;
7112     IDirectDrawSurface *surface, *ds, *d3drm_ds;
7113     HWND window;
7114     GUID driver = IID_IDirect3DRGBDevice;
7115     HRESULT hr;
7116     D3DCOLOR ret_color;
7117     RECT rc;
7118 
7119     window = create_window();
7120     GetClientRect(window, &rc);
7121 
7122     hr = DirectDrawCreate(NULL, &ddraw1, NULL);
7123     ok(SUCCEEDED(hr), "Cannot create IDirectDraw interface (hr = %#x).\n", hr);
7124 
7125     hr = IDirectDraw_SetCooperativeLevel(ddraw1, window, DDSCL_NORMAL);
7126     ok(SUCCEEDED(hr), "Failed to set cooperative level (hr = %#x).\n", hr);
7127 
7128     hr = IDirectDraw_CreateClipper(ddraw1, 0, &clipper, NULL);
7129     ok(SUCCEEDED(hr), "Cannot create clipper (hr = %#x).\n", hr);
7130 
7131     hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
7132     ok(SUCCEEDED(hr), "Cannot set HWnd to Clipper (hr = %#x)\n", hr);
7133 
7134     hr = Direct3DRMCreate(&d3drm1);
7135     ok(SUCCEEDED(hr), "Cannot get IDirect3DRM interface (hr = %#x).\n", hr);
7136 
7137     hr = IDirect3DRM_QueryInterface(d3drm1, &IID_IDirect3DRM3, (void **)&d3drm3);
7138     ok(SUCCEEDED(hr), "Cannot get IDirect3DRM3 interface (hr = %#x).\n", hr);
7139 
7140     hr = IDirect3DRM3_CreateDeviceFromClipper(d3drm3, clipper, &driver, rc.right, rc.bottom, &device3);
7141     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMDevice3 interface (hr = %#x)\n", hr);
7142 
7143     hr = IDirect3DRM3_CreateFrame(d3drm3, NULL, &frame3);
7144     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMFrame3 interface (hr = %#x)\n", hr);
7145     hr = IDirect3DRM3_CreateFrame(d3drm3, frame3, &camera3);
7146     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMFrame3 interface (hr = %#x)\n", hr);
7147 
7148     hr = IDirect3DRM3_CreateViewport(d3drm3, device3, camera3, 0, 0, rc.right,
7149             rc.bottom, &viewport2);
7150     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMViewport2 interface (hr = %#x)\n", hr);
7151 
7152     /* Fetch immediate mode device in order to access render target and test its color. */
7153     hr = IDirect3DRMDevice3_GetDirect3DDevice2(device3, &d3d_device2);
7154     ok(SUCCEEDED(hr), "Cannot get IDirect3DDevice2 interface (hr = %#x).\n", hr);
7155 
7156     hr = IDirect3DDevice2_GetRenderTarget(d3d_device2, &surface);
7157     ok(SUCCEEDED(hr), "Cannot get surface to the render target (hr = %#x).\n", hr);
7158 
7159     ret_color = get_surface_color(surface, 320, 240);
7160     ok(compare_color(ret_color, 0, 1), "Got unexpected color 0x%08x.\n", ret_color);
7161 
7162     /* Clear uses the scene frame's background color. */
7163     hr = IDirect3DRMFrame3_SetSceneBackgroundRGB(frame3, 1.0f, 1.0f, 1.0f);
7164     ok(SUCCEEDED(hr), "Cannot set scene background RGB (hr = %#x)\n", hr);
7165     ret_color = IDirect3DRMFrame3_GetSceneBackground(frame3);
7166     ok(ret_color == 0xffffffff, "Expected scene color returned == 0xffffffff, got %#x.\n", ret_color);
7167     hr = IDirect3DRMFrame3_SetSceneBackgroundRGB(camera3, 0.0f, 1.0f, 0.0f);
7168     ok(SUCCEEDED(hr), "Cannot set scene background RGB (hr = %#x)\n", hr);
7169     ret_color = IDirect3DRMFrame3_GetSceneBackground(camera3);
7170     ok(ret_color == 0xff00ff00, "Expected scene color returned == 0xff00ff00, got %#x.\n", ret_color);
7171 
7172     CHECK_REFCOUNT(frame3, 1);
7173     hr = IDirect3DRMViewport2_Clear(viewport2, D3DRMCLEAR_ALL);
7174     ok(SUCCEEDED(hr), "Cannot clear viewport (hr = %#x).\n", hr);
7175     ret_color = get_surface_color(surface, 320, 240);
7176     ok(compare_color(ret_color, 0x00ffffff, 1), "Got unexpected color 0x%08x.\n", ret_color);
7177     CHECK_REFCOUNT(frame3, 1);
7178 
7179     hr = IDirect3DRMViewport2_GetDirect3DViewport(viewport2, &d3d_viewport);
7180     ok(SUCCEEDED(hr), "Cannot get IDirect3DViewport interface (hr = %#x).\n", hr);
7181 
7182     hr = IDirect3DRMViewport2_Clear(viewport2, D3DRMCLEAR_ALL);
7183     ok(SUCCEEDED(hr), "Cannot clear viewport (hr = %#x).\n", hr);
7184 
7185     /* d3drm seems to be calling BeginScene when Clear is called. */
7186     hr = IDirect3DDevice2_BeginScene(d3d_device2);
7187     todo_wine ok(hr == D3DERR_SCENE_IN_SCENE, "Expected hr == D3DERR_SCENE_IN_SCENE, got %#x.\n", hr);
7188     hr = IDirect3DDevice2_EndScene(d3d_device2);
7189     ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
7190 
7191     ret_color = get_surface_color(surface, 320, 240);
7192     ok(compare_color(ret_color, 0x00ffffff, 1), "Got unexpected color 0x%08x.\n", ret_color);
7193 
7194     /* We're using d3d to draw using IDirect3DDevice2 created from d3drm. */
7195     draw_quad2(d3d_device2, d3d_viewport);
7196     ret_color = get_surface_color(surface, 320, 240);
7197     ok(compare_color(ret_color, 0x00bada55, 1), "Got unexpected color 0x%08x.\n", ret_color);
7198 
7199     /* Without calling Configure, Clear doesn't work. */
7200     hr = IDirect3DRMViewport2_Clear(viewport2, D3DRMCLEAR_ALL);
7201     ok(SUCCEEDED(hr), "Cannot clear viewport (hr = %#x).\n", hr);
7202     ret_color = get_surface_color(surface, 320, 240);
7203     todo_wine ok(compare_color(ret_color, 0x00bada55, 1), "Got unexpected color 0x%08x.\n", ret_color);
7204 
7205     hr = IDirect3DRMViewport2_Configure(viewport2, 0, 0, rc.right, rc.bottom);
7206     todo_wine ok(SUCCEEDED(hr), "Cannot configure viewport (hr = %#x).\n", hr);
7207     hr = IDirect3DRMViewport2_Clear(viewport2, D3DRMCLEAR_ALL);
7208     ok(SUCCEEDED(hr), "Cannot clear viewport (hr = %#x).\n", hr);
7209 
7210     ret_color = get_surface_color(surface, 320, 240);
7211     ok(compare_color(ret_color, 0x00ffffff, 1), "Got unexpected color 0x%08x.\n", ret_color);
7212 
7213     /* Fetch attached depth surface and see if viewport clears it if it's detached from the render target. */
7214     hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &ds);
7215     ok(SUCCEEDED(hr), "Cannot get attached depth surface (hr = %x).\n", hr);
7216 
7217     clear_depth_surface(ds, 0x39);
7218     draw_quad2(d3d_device2, d3d_viewport);
7219 
7220     ret_color = get_surface_color(surface, 320, 240);
7221     ok(compare_color(ret_color, 0x00ffffff, 1), "Got unexpected color 0x%08x.\n", ret_color);
7222 
7223     hr = IDirectDrawSurface_DeleteAttachedSurface(surface, 0, ds);
7224     ok(SUCCEEDED(hr), "Cannot delete attached surface (hr = %#x).\n", hr);
7225     d3drm_ds = (IDirectDrawSurface *)0xdeadbeef;
7226     hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &d3drm_ds);
7227     ok(hr == DDERR_NOTFOUND, "Expected hr == DDERR_NOTFOUND, got %#x.\n", hr);
7228     ok(d3drm_ds == NULL, "Expected NULL z-surface, got %p.\n", d3drm_ds);
7229 
7230     clear_depth_surface(ds, 0x7fff);
7231 
7232     /* This version of Clear still clears the depth surface even if it's deleted from the render target. */
7233     hr = IDirect3DRMViewport2_Configure(viewport2, 0, 0, rc.right, rc.bottom);
7234     todo_wine ok(SUCCEEDED(hr), "Cannot configure viewport (hr = %#x).\n", hr);
7235     hr = IDirect3DRMViewport2_Clear(viewport2, D3DRMCLEAR_ALL);
7236     ok(SUCCEEDED(hr), "Cannot clear viewport (hr = %#x).\n", hr);
7237 
7238     hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
7239     ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
7240     ret_color = get_surface_color(surface, 320, 240);
7241     ok(compare_color(ret_color, 0x00ffffff, 1), "Got unexpected color 0x%08x.\n", ret_color);
7242 
7243     draw_quad2(d3d_device2, d3d_viewport);
7244     ret_color = get_surface_color(surface, 100, 200);
7245     ok(compare_color(ret_color, 0x00bada55, 1), "Got unexpected color 0x%08x.\n", ret_color);
7246     ret_color = get_surface_color(surface, 500, 400);
7247     todo_wine ok(compare_color(ret_color, 0x00bada55, 1), "Got unexpected color 0x%08x.\n", ret_color);
7248 
7249     /* Clear with no flags */
7250     hr = IDirect3DRMViewport2_Configure(viewport2, 0, 0, rc.right, rc.bottom);
7251     todo_wine ok(SUCCEEDED(hr), "Cannot configure viewport (hr = %#x).\n", hr);
7252     hr = IDirect3DRMViewport2_Clear(viewport2, 0);
7253     ok(SUCCEEDED(hr), "Cannot clear viewport (hr = %#x).\n", hr);
7254     ret_color = get_surface_color(surface, 320, 240);
7255     todo_wine ok(compare_color(ret_color, 0x00bada55, 1), "Got unexpected color 0x%08x.\n", ret_color);
7256 
7257     hr = IDirect3DRMViewport2_Configure(viewport2, 0, 0, rc.right, rc.bottom);
7258     todo_wine ok(SUCCEEDED(hr), "Cannot configure viewport (hr = %#x).\n", hr);
7259     hr = IDirect3DRMViewport2_Clear(viewport2, D3DRMCLEAR_ALL);
7260     ok(SUCCEEDED(hr), "Cannot clear viewport (hr = %#x).\n", hr);
7261     ret_color = get_surface_color(surface, 320, 240);
7262     ok(compare_color(ret_color, 0x00ffffff, 1), "Got unexpected color 0x%08x.\n", ret_color);
7263 
7264     IDirect3DViewport_Release(d3d_viewport);
7265     IDirectDrawSurface_Release(surface);
7266     IDirectDrawSurface_Release(ds);
7267     IDirect3DDevice2_Release(d3d_device2);
7268     IDirect3DRMViewport2_Release(viewport2);
7269     IDirect3DRMDevice3_Release(device3);
7270 
7271     /* Create device without depth surface attached */
7272     hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw2, (void **)&ddraw2);
7273     ok(SUCCEEDED(hr), "Cannot get IDirectDraw2 interface (hr = %#x).\n", hr);
7274     hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirect3D2, (void **)&d3d2);
7275     ok(SUCCEEDED(hr), "Cannot get IDirect3D2 interface (hr = %x).\n", hr);
7276     d3d_device2 = create_device2_without_ds(ddraw2, window);
7277     if (!d3d_device2)
7278         goto cleanup;
7279 
7280     hr = IDirect3DRM3_CreateDeviceFromD3D(d3drm3, d3d2, d3d_device2, &device3);
7281     ok(SUCCEEDED(hr), "Failed to create IDirect3DRMDevice interface (hr = %#x)\n", hr);
7282     hr = IDirect3DRM3_CreateViewport(d3drm3, device3, camera3, 0, 0, rc.right,
7283             rc.bottom, &viewport2);
7284     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMViewport2 interface (hr = %#x)\n", hr);
7285     hr = IDirect3DDevice2_GetRenderTarget(d3d_device2, &surface);
7286     ok(SUCCEEDED(hr), "Cannot get surface to the render target (hr = %#x).\n", hr);
7287 
7288     hr = IDirect3DRMViewport2_Clear(viewport2, D3DRMCLEAR_ALL);
7289     ok(SUCCEEDED(hr), "Cannot clear viewport (hr = %#x).\n", hr);
7290     ret_color = get_surface_color(surface, 320, 240);
7291     ok(compare_color(ret_color, 0x00ffffff, 1), "Got unexpected color 0x%08x.\n", ret_color);
7292 
7293     hr = IDirect3DRMViewport2_Clear(viewport2, D3DRMCLEAR_ZBUFFER);
7294     ok(SUCCEEDED(hr), "Cannot clear viewport (hr = %#x).\n", hr);
7295 
7296     IDirectDrawSurface_Release(surface);
7297     IDirect3DRMViewport2_Release(viewport2);
7298     IDirect3DRMDevice3_Release(device3);
7299     IDirect3DDevice2_Release(d3d_device2);
7300 
7301 cleanup:
7302     IDirect3DRMFrame3_Release(camera3);
7303     IDirect3DRMFrame3_Release(frame3);
7304     IDirect3DRM3_Release(d3drm3);
7305     IDirect3DRM_Release(d3drm1);
7306     IDirectDrawClipper_Release(clipper);
7307     IDirect3D2_Release(d3d2);
7308     IDirectDraw2_Release(ddraw2);
7309     IDirectDraw_Release(ddraw1);
7310     DestroyWindow(window);
7311 }
7312 
test_create_texture_from_surface(void)7313 static void test_create_texture_from_surface(void)
7314 {
7315     D3DRMIMAGE testimg =
7316     {
7317         0, 0, 0, 0, 0,
7318         TRUE, 0, (void *)0xcafebabe, NULL,
7319         0x000000ff, 0x0000ff00, 0x00ff0000, 0, 0, NULL
7320     };
7321     IDirectDrawSurface *surface = NULL, *surface2 = NULL, *ds = NULL;
7322     IDirect3DRMTexture *texture1;
7323     IDirect3DRMTexture2 *texture2;
7324     IDirect3DRMTexture3 *texture3;
7325     IDirectDraw *ddraw = NULL;
7326     IDirect3DRM *d3drm1 = NULL;
7327     IDirect3DRM2 *d3drm2 = NULL;
7328     IDirect3DRM3 *d3drm3 = NULL;
7329     ULONG ref1, ref2, ref3;
7330     D3DRMIMAGE *image;
7331     DDSURFACEDESC desc;
7332     HWND window;
7333     HRESULT hr;
7334     RECT rc;
7335 
7336     hr = DirectDrawCreate(NULL, &ddraw, NULL);
7337     ok(hr == DD_OK, "Cannot get IDirectDraw interface (hr = %x).\n", hr);
7338 
7339     window = create_window();
7340     GetClientRect(window, &rc);
7341 
7342     hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7343     ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7344 
7345     hr = Direct3DRMCreate(&d3drm1);
7346     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x).\n", hr);
7347 
7348     hr = IDirect3DRM_QueryInterface(d3drm1, &IID_IDirect3DRM2, (void **)&d3drm2);
7349     ok(SUCCEEDED(hr), "Cannot get IDirect3DRM2 interface (hr = %x).\n", hr);
7350 
7351     hr = IDirect3DRM_QueryInterface(d3drm1, &IID_IDirect3DRM3, (void **)&d3drm3);
7352     ok(SUCCEEDED(hr), "Cannot get IDirect3DRM3 interface (hr = %x).\n", hr);
7353 
7354     /* Create a surface and use it to create a texture. */
7355     memset(&desc, 0, sizeof(desc));
7356     desc.dwSize = sizeof(desc);
7357     desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7358     desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7359     desc.dwWidth = rc.right;
7360     desc.dwHeight = rc.bottom;
7361 
7362     hr = IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL);
7363     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7364 
7365     hr = IDirectDraw_CreateSurface(ddraw, &desc, &surface2, NULL);
7366     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7367 
7368     /* Test NULL params */
7369     texture1 = (IDirect3DRMTexture *)0xdeadbeef;
7370     hr = IDirect3DRM_CreateTextureFromSurface(d3drm1, NULL, &texture1);
7371     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
7372     ok(!texture1, "Expected texture returned == NULL, got %p.\n", texture1);
7373 
7374     hr = IDirect3DRM_CreateTextureFromSurface(d3drm1, NULL, NULL);
7375     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
7376 
7377     texture2 = (IDirect3DRMTexture2 *)0xdeadbeef;
7378     hr = IDirect3DRM2_CreateTextureFromSurface(d3drm2, NULL, &texture2);
7379     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
7380     ok(!texture2, "Expected texture returned == NULL, got %p.\n", texture2);
7381 
7382     hr = IDirect3DRM2_CreateTextureFromSurface(d3drm2, NULL, NULL);
7383     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
7384 
7385     texture3 = (IDirect3DRMTexture3 *)0xdeadbeef;
7386     hr = IDirect3DRM3_CreateTextureFromSurface(d3drm3, NULL, &texture3);
7387     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
7388     ok(!texture3, "Expected texture returned == NULL, got %p.\n", texture3);
7389 
7390     hr = IDirect3DRM3_CreateTextureFromSurface(d3drm3, NULL, NULL);
7391     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
7392 
7393     ok(get_refcount((IUnknown *)surface) == 1, "Unexpected surface refcount.\n");
7394     hr = IDirect3DRM_CreateTextureFromSurface(d3drm1, surface, &texture1);
7395     ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7396 
7397     ok(get_refcount((IUnknown *)surface) == 2, "Unexpected surface refcount.\n");
7398     image = IDirect3DRMTexture_GetImage(texture1);
7399     ok(image == NULL, "Unexpected image, %p.\n", image);
7400     hr = IDirect3DRMTexture_InitFromSurface(texture1, NULL);
7401     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
7402     IDirect3DRMTexture_Release(texture1);
7403 
7404     ok(get_refcount((IUnknown *)surface) == 1, "Unexpected surface refcount.\n");
7405     hr = IDirect3DRM2_CreateTextureFromSurface(d3drm2, surface, &texture2);
7406     ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7407     ok(get_refcount((IUnknown *)surface) == 2, "Unexpected surface refcount.\n");
7408     image = IDirect3DRMTexture2_GetImage(texture2);
7409     ok(image == NULL, "Unexpected image, %p.\n", image);
7410     hr = IDirect3DRMTexture2_InitFromSurface(texture2, NULL);
7411     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
7412     IDirect3DRMTexture_Release(texture2);
7413 
7414     ok(get_refcount((IUnknown *)surface) == 1, "Unexpected surface refcount.\n");
7415     hr = IDirect3DRM3_CreateTextureFromSurface(d3drm3, surface, &texture3);
7416     ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7417     ok(get_refcount((IUnknown *)surface) == 2, "Unexpected surface refcount.\n");
7418     image = IDirect3DRMTexture3_GetImage(texture3);
7419     ok(image == NULL, "Unexpected image, %p.\n", image);
7420     hr = IDirect3DRMTexture3_InitFromSurface(texture3, NULL);
7421     ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
7422     hr = IDirect3DRMTexture3_GetSurface(texture3, 0, NULL);
7423     ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr);
7424     hr = IDirect3DRMTexture3_GetSurface(texture3, 0, &ds);
7425     ok(SUCCEEDED(hr), "Failed to get surface, hr %#x.\n", hr);
7426     ok(ds == surface, "Expected same surface back.\n");
7427     IDirectDrawSurface_Release(ds);
7428 
7429     /* Init already initialized texture with same surface. */
7430     hr = IDirect3DRMTexture3_InitFromSurface(texture3, surface);
7431     ok(hr == D3DRMERR_BADOBJECT, "Expected a failure, hr %#x.\n", hr);
7432 
7433     /* Init already initialized texture with different surface. */
7434     hr = IDirect3DRMTexture3_InitFromSurface(texture3, surface2);
7435     ok(hr == D3DRMERR_BADOBJECT, "Expected a failure, hr %#x.\n", hr);
7436 
7437     hr = IDirect3DRMTexture3_GetSurface(texture3, 0, &ds);
7438     ok(SUCCEEDED(hr), "Failed to get surface, hr %#x.\n", hr);
7439     ok(ds == surface, "Expected same surface back.\n");
7440     IDirectDrawSurface_Release(ds);
7441 
7442     ref1 = get_refcount((IUnknown *)d3drm1);
7443     ref2 = get_refcount((IUnknown *)d3drm2);
7444     ref3 = get_refcount((IUnknown *)d3drm3);
7445     hr = IDirect3DRMTexture3_InitFromImage(texture3, &testimg);
7446     ok(hr == D3DRMERR_BADOBJECT, "Expected a failure, hr %#x.\n", hr);
7447     ok(ref1 < get_refcount((IUnknown *)d3drm1), "Expected d3drm1 reference taken.\n");
7448     ok(ref2 == get_refcount((IUnknown *)d3drm2), "Expected d3drm2 reference unchanged.\n");
7449     ok(ref3 == get_refcount((IUnknown *)d3drm3), "Expected d3drm3 reference unchanged.\n");
7450     /* Release leaked reference to d3drm1 */
7451     IDirect3DRM_Release(d3drm1);
7452 
7453     IDirect3DRMTexture_Release(texture3);
7454 
7455     /* Create from image, initialize from surface. */
7456     hr = IDirect3DRM3_CreateTexture(d3drm3, &testimg, &texture3);
7457     ok(SUCCEEDED(hr), "Cannot get IDirect3DRMTexture3 interface (hr = %#x)\n", hr);
7458 
7459     ref1 = get_refcount((IUnknown *)d3drm1);
7460     ref2 = get_refcount((IUnknown *)d3drm2);
7461     ref3 = get_refcount((IUnknown *)d3drm3);
7462     hr = IDirect3DRMTexture3_InitFromSurface(texture3, surface);
7463     ok(hr == D3DRMERR_BADOBJECT, "Expected a failure, hr %#x.\n", hr);
7464     ok(ref1 < get_refcount((IUnknown *)d3drm1), "Expected d3drm1 reference taken.\n");
7465     ok(ref2 == get_refcount((IUnknown *)d3drm2), "Expected d3drm2 reference unchanged.\n");
7466     ok(ref3 == get_refcount((IUnknown *)d3drm3), "Expected d3drm3 reference unchanged.\n");
7467     /* Release leaked reference to d3drm1 */
7468     IDirect3DRM_Release(d3drm1);
7469     IDirect3DRMTexture3_Release(texture3);
7470 
7471     IDirectDrawSurface_Release(surface2);
7472     IDirectDrawSurface_Release(surface);
7473     IDirect3DRM3_Release(d3drm3);
7474     IDirect3DRM2_Release(d3drm2);
7475     IDirect3DRM_Release(d3drm1);
7476     IDirectDraw_Release(ddraw);
7477 }
7478 
test_animation(void)7479 static void test_animation(void)
7480 {
7481     IDirect3DRMAnimation2 *animation2;
7482     IDirect3DRMAnimation *animation;
7483     D3DRMANIMATIONOPTIONS options;
7484     IDirect3DRMObject *obj, *obj2;
7485     D3DRMANIMATIONKEY keys[10];
7486     IDirect3DRMFrame3 *frame3;
7487     IDirect3DRMFrame *frame;
7488     D3DRMANIMATIONKEY key;
7489     IDirect3DRM *d3drm1;
7490     D3DRMQUATERNION q;
7491     DWORD count, i;
7492     HRESULT hr;
7493     D3DVECTOR v;
7494 
7495     hr = Direct3DRMCreate(&d3drm1);
7496     ok(SUCCEEDED(hr), "Failed to create IDirect3DRM instance, hr 0x%08x.\n", hr);
7497 
7498     hr = IDirect3DRM_CreateAnimation(d3drm1, NULL);
7499     ok(hr == D3DRMERR_BADVALUE, "Unexpected hr 0x%08x.\n", hr);
7500 
7501     CHECK_REFCOUNT(d3drm1, 1);
7502     hr = IDirect3DRM_CreateAnimation(d3drm1, &animation);
7503     ok(SUCCEEDED(hr), "Failed to create animation hr 0x%08x.\n", hr);
7504     CHECK_REFCOUNT(d3drm1, 2);
7505 
7506     test_class_name((IDirect3DRMObject *)animation, "Animation");
7507 
7508     hr = IDirect3DRMAnimation_QueryInterface(animation, &IID_IDirect3DRMAnimation2, (void **)&animation2);
7509     ok(SUCCEEDED(hr), "Failed to get IDirect3DRMAnimation2, hr 0x%08x.\n", hr);
7510     ok(animation != (void *)animation2, "Expected different interface pointer.\n");
7511 
7512     hr = IDirect3DRMAnimation_QueryInterface(animation, &IID_IDirect3DRMObject, (void **)&obj);
7513     ok(SUCCEEDED(hr), "Failed to get IDirect3DRMObject, hr 0x%08x.\n", hr);
7514 
7515     hr = IDirect3DRMAnimation2_QueryInterface(animation2, &IID_IDirect3DRMObject, (void **)&obj2);
7516     ok(SUCCEEDED(hr), "Failed to get IDirect3DRMObject, hr 0x%08x.\n", hr);
7517 
7518     ok(obj == obj2 && obj == (IDirect3DRMObject *)animation, "Unexpected object pointer.\n");
7519 
7520     IDirect3DRMObject_Release(obj);
7521     IDirect3DRMObject_Release(obj2);
7522 
7523     /* Set animated frame, get it back. */
7524     hr = IDirect3DRM_CreateFrame(d3drm1, NULL, &frame);
7525     ok(SUCCEEDED(hr), "Failed to create a frame, hr %#x.\n", hr);
7526 
7527     hr = IDirect3DRMAnimation_SetFrame(animation, NULL);
7528     ok(SUCCEEDED(hr), "Failed to reset frame, hr %#x.\n", hr);
7529 
7530     CHECK_REFCOUNT(frame, 1);
7531     hr = IDirect3DRMAnimation_SetFrame(animation, frame);
7532     ok(SUCCEEDED(hr), "Failed to set a frame, hr %#x.\n", hr);
7533     CHECK_REFCOUNT(frame, 1);
7534 
7535     hr = IDirect3DRMAnimation2_GetFrame(animation2, NULL);
7536     ok(hr == D3DRMERR_BADVALUE, "Unexpected hr %#x.\n", hr);
7537 
7538     hr = IDirect3DRMAnimation2_GetFrame(animation2, &frame3);
7539     ok(SUCCEEDED(hr), "Failed to get the frame, %#x.\n", hr);
7540     ok(frame3 != (void *)frame, "Unexpected interface pointer.\n");
7541     CHECK_REFCOUNT(frame, 2);
7542 
7543     IDirect3DRMFrame3_Release(frame3);
7544 
7545     hr = IDirect3DRMAnimation_SetFrame(animation, NULL);
7546     ok(SUCCEEDED(hr), "Failed to reset frame, hr %#x.\n", hr);
7547 
7548     hr = IDirect3DRMFrame_QueryInterface(frame, &IID_IDirect3DRMFrame3, (void **)&frame3);
7549     ok(SUCCEEDED(hr), "Failed to get IDirect3DRMFrame3, hr %#x.\n", hr);
7550 
7551     CHECK_REFCOUNT(frame3, 2);
7552     hr = IDirect3DRMAnimation2_SetFrame(animation2, frame3);
7553     ok(SUCCEEDED(hr), "Failed to set a frame, hr %#x.\n", hr);
7554     CHECK_REFCOUNT(frame3, 2);
7555 
7556     IDirect3DRMFrame3_Release(frame3);
7557     IDirect3DRMFrame_Release(frame);
7558 
7559     /* Animation options. */
7560     options = IDirect3DRMAnimation_GetOptions(animation);
7561     ok(options == (D3DRMANIMATION_CLOSED | D3DRMANIMATION_LINEARPOSITION),
7562             "Unexpected default options %#x.\n", options);
7563 
7564     /* Undefined mask value */
7565     hr = IDirect3DRMAnimation_SetOptions(animation, 0xf0000000);
7566     ok(hr == D3DRMERR_BADVALUE, "Unexpected hr %#x.\n", hr);
7567 
7568     options = IDirect3DRMAnimation_GetOptions(animation);
7569     ok(options == (D3DRMANIMATION_CLOSED | D3DRMANIMATION_LINEARPOSITION),
7570             "Unexpected default options %#x.\n", options);
7571 
7572     /* Ambiguous mask */
7573     hr = IDirect3DRMAnimation_SetOptions(animation, D3DRMANIMATION_OPEN | D3DRMANIMATION_CLOSED);
7574     ok(hr == D3DRMERR_BADVALUE, "Unexpected hr %#x.\n", hr);
7575 
7576     hr = IDirect3DRMAnimation_SetOptions(animation, D3DRMANIMATION_LINEARPOSITION | D3DRMANIMATION_SPLINEPOSITION);
7577     ok(hr == D3DRMERR_BADVALUE, "Unexpected hr %#x.\n", hr);
7578 
7579     hr = IDirect3DRMAnimation_SetOptions(animation, D3DRMANIMATION_SCALEANDROTATION | D3DRMANIMATION_POSITION);
7580     ok(hr == D3DRMERR_BADVALUE, "Unexpected hr %#x.\n", hr);
7581 
7582     options = IDirect3DRMAnimation_GetOptions(animation);
7583     ok(options == (D3DRMANIMATION_CLOSED | D3DRMANIMATION_LINEARPOSITION),
7584             "Unexpected default options %#x.\n", options);
7585 
7586     /* Mask contains undefined bits together with valid one. */
7587     hr = IDirect3DRMAnimation_SetOptions(animation, 0xf0000000 | D3DRMANIMATION_OPEN);
7588     ok(SUCCEEDED(hr), "Failed to set animation options, hr %#x.\n", hr);
7589 
7590     options = IDirect3DRMAnimation_GetOptions(animation);
7591     ok(options == (0xf0000000 | D3DRMANIMATION_OPEN), "Unexpected animation options %#x.\n", options);
7592 
7593     hr = IDirect3DRMAnimation_SetOptions(animation, D3DRMANIMATION_SCALEANDROTATION);
7594     ok(SUCCEEDED(hr), "Failed to set animation options, hr %#x.\n", hr);
7595 
7596     options = IDirect3DRMAnimation_GetOptions(animation);
7597     ok(options == D3DRMANIMATION_SCALEANDROTATION, "Unexpected options %#x.\n", options);
7598 
7599     hr = IDirect3DRMAnimation_SetOptions(animation, D3DRMANIMATION_OPEN);
7600     ok(SUCCEEDED(hr), "Failed to set animation options, hr %#x.\n", hr);
7601 
7602     options = IDirect3DRMAnimation_GetOptions(animation);
7603     ok(options == D3DRMANIMATION_OPEN, "Unexpected options %#x.\n", options);
7604 
7605     hr = IDirect3DRMAnimation_SetOptions(animation, 0);
7606     ok(hr == D3DRMERR_BADVALUE, "Unexpected hr %#x.\n", hr);
7607 
7608     options = IDirect3DRMAnimation_GetOptions(animation);
7609     ok(options == D3DRMANIMATION_OPEN, "Unexpected options %#x.\n", options);
7610 
7611     /* Key management. */
7612     hr = IDirect3DRMAnimation_AddPositionKey(animation, 0.0f, 1.0f, 0.0f, 0.0f);
7613     ok(SUCCEEDED(hr), "Failed to add position key, hr %#x.\n", hr);
7614 
7615     hr = IDirect3DRMAnimation_AddScaleKey(animation, 0.0f, 1.0f, 2.0f, 1.0f);
7616     ok(SUCCEEDED(hr), "Failed to add scale key, hr %#x.\n", hr);
7617 
7618     hr = IDirect3DRMAnimation_AddPositionKey(animation, 0.0f, 2.0f, 0.0f, 0.0f);
7619     ok(SUCCEEDED(hr), "Failed to add position key, hr %#x.\n", hr);
7620 
7621     hr = IDirect3DRMAnimation_AddPositionKey(animation, 99.0f, 3.0f, 1.0f, 0.0f);
7622     ok(SUCCEEDED(hr), "Failed to add position key, hr %#x.\n", hr);
7623 
7624     hr = IDirect3DRMAnimation_AddPositionKey(animation, 80.0f, 4.0f, 1.0f, 0.0f);
7625     ok(SUCCEEDED(hr), "Failed to add position key, hr %#x.\n", hr);
7626 
7627     v.x = 1.0f;
7628     v.y = 0.0f;
7629     v.z = 0.0f;
7630     D3DRMQuaternionFromRotation(&q, &v, 1.0f);
7631 
7632     /* NULL quaternion pointer leads to a crash on Windows. */
7633     hr = IDirect3DRMAnimation_AddRotateKey(animation, 0.0f, &q);
7634     ok(SUCCEEDED(hr), "Failed to add rotation key, hr %#.x\n", hr);
7635 
7636     count = 0;
7637     memset(keys, 0, sizeof(keys));
7638     hr = IDirect3DRMAnimation2_GetKeys(animation2, 0.0f, 99.0f, &count, keys);
7639     ok(SUCCEEDED(hr), "Failed to get animation keys, hr %#x.\n", hr);
7640     ok(count == 6, "Unexpected key count %u.\n", count);
7641 
7642     ok(keys[0].dwKeyType == D3DRMANIMATION_ROTATEKEY, "Unexpected key type %u.\n", keys[0].dwKeyType);
7643     ok(keys[1].dwKeyType == D3DRMANIMATION_POSITIONKEY, "Unexpected key type %u.\n", keys[1].dwKeyType);
7644     ok(keys[2].dwKeyType == D3DRMANIMATION_POSITIONKEY, "Unexpected key type %u.\n", keys[2].dwKeyType);
7645     ok(keys[3].dwKeyType == D3DRMANIMATION_POSITIONKEY, "Unexpected key type %u.\n", keys[3].dwKeyType);
7646     ok(keys[4].dwKeyType == D3DRMANIMATION_POSITIONKEY, "Unexpected key type %u.\n", keys[4].dwKeyType);
7647     ok(keys[5].dwKeyType == D3DRMANIMATION_SCALEKEY, "Unexpected key type %u.\n", keys[5].dwKeyType);
7648 
7649     /* Relative order, keys are returned sorted by time. */
7650     ok(keys[1].dvTime == 0.0f, "Unexpected key time %.8e.\n", keys[1].dvTime);
7651     ok(keys[2].dvTime == 0.0f, "Unexpected key time %.8e.\n", keys[2].dvTime);
7652     ok(keys[3].dvTime == 80.0f, "Unexpected key time %.8e.\n", keys[3].dvTime);
7653     ok(keys[4].dvTime == 99.0f, "Unexpected key time %.8e.\n", keys[4].dvTime);
7654 
7655     /* For keys with same time, order they were added in is kept. */
7656     ok(keys[1].dvPositionKey.x == 1.0f, "Unexpected key position x %.8e.\n", keys[1].dvPositionKey.x);
7657     ok(keys[2].dvPositionKey.x == 2.0f, "Unexpected key position x %.8e.\n", keys[2].dvPositionKey.x);
7658     ok(keys[3].dvPositionKey.x == 4.0f, "Unexpected key position x %.8e.\n", keys[3].dvPositionKey.x);
7659     ok(keys[4].dvPositionKey.x == 3.0f, "Unexpected key position x %.8e.\n", keys[4].dvPositionKey.x);
7660 
7661     for (i = 0; i < count; i++)
7662     {
7663         ok(keys[i].dwSize == sizeof(*keys), "%u: unexpected dwSize value %u.\n", i, keys[i].dwSize);
7664 
7665     todo_wine
7666     {
7667         switch (keys[i].dwKeyType)
7668         {
7669         case D3DRMANIMATION_ROTATEKEY:
7670             ok((keys[i].dwID & 0xf0000000) == 0x40000000, "%u: unexpected id mask %#x.\n", i, keys[i].dwID);
7671             break;
7672         case D3DRMANIMATION_POSITIONKEY:
7673             ok((keys[i].dwID & 0xf0000000) == 0x80000000, "%u: unexpected id mask %#x.\n", i, keys[i].dwID);
7674             break;
7675         case D3DRMANIMATION_SCALEKEY:
7676             ok((keys[i].dwID & 0xf0000000) == 0xc0000000, "%u: unexpected id mask %#x.\n", i, keys[i].dwID);
7677             break;
7678         default:
7679             ok(0, "%u: unknown key type %d.\n", i, keys[i].dwKeyType);
7680         }
7681     }
7682     }
7683 
7684     /* No keys in this range. */
7685     count = 10;
7686     hr = IDirect3DRMAnimation2_GetKeys(animation2, 100.0f, 200.0f, &count, NULL);
7687     ok(hr == D3DRMERR_NOSUCHKEY, "Unexpected hr %#x.\n", hr);
7688     ok(count == 0, "Unexpected key count %u.\n", count);
7689 
7690     count = 10;
7691     hr = IDirect3DRMAnimation2_GetKeys(animation2, 100.0f, 200.0f, &count, keys);
7692     ok(hr == D3DRMERR_NOSUCHKEY, "Unexpected hr %#x.\n", hr);
7693     ok(count == 0, "Unexpected key count %u.\n", count);
7694 
7695     count = 10;
7696     hr = IDirect3DRMAnimation2_GetKeys(animation2, 0.0f, 0.0f, &count, NULL);
7697     ok(SUCCEEDED(hr), "Failed to get animation keys, hr %#x.\n", hr);
7698     ok(count == 4, "Unexpected key count %u.\n", count);
7699 
7700     hr = IDirect3DRMAnimation2_GetKeys(animation2, 0.0f, 100.0f, NULL, NULL);
7701     ok(hr == D3DRMERR_BADVALUE, "Unexpected hr %#x.\n", hr);
7702 
7703     /* Time is 0-based. */
7704     hr = IDirect3DRMAnimation2_GetKeys(animation2, -100.0f, -50.0f, NULL, NULL);
7705     ok(hr == D3DRMERR_BADVALUE, "Unexpected hr %#x.\n", hr);
7706 
7707     count = 10;
7708     hr = IDirect3DRMAnimation2_GetKeys(animation2, -100.0f, -50.0f, &count, NULL);
7709     ok(hr == D3DRMERR_NOSUCHKEY, "Unexpected hr %#x.\n", hr);
7710     ok(count == 0, "Unexpected key count %u.\n", count);
7711 
7712     count = 10;
7713     hr = IDirect3DRMAnimation2_GetKeys(animation2, -100.0f, 100.0f, &count, NULL);
7714     ok(SUCCEEDED(hr), "Failed to get animation keys, hr %#x.\n", hr);
7715     ok(count == 6, "Unexpected key count %u.\n", count);
7716 
7717     /* AddKey() tests. */
7718     hr = IDirect3DRMAnimation2_AddKey(animation2, NULL);
7719     ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
7720 
7721     memset(&key, 0, sizeof(key));
7722     key.dwKeyType = D3DRMANIMATION_POSITIONKEY;
7723     hr = IDirect3DRMAnimation2_AddKey(animation2, &key);
7724     ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
7725 
7726     memset(&key, 0, sizeof(key));
7727     key.dwSize = sizeof(key) - 1;
7728     key.dwKeyType = D3DRMANIMATION_POSITIONKEY;
7729     hr = IDirect3DRMAnimation2_AddKey(animation2, &key);
7730     ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
7731 
7732     memset(&key, 0, sizeof(key));
7733     key.dwSize = sizeof(key) + 1;
7734     key.dwKeyType = D3DRMANIMATION_POSITIONKEY;
7735     hr = IDirect3DRMAnimation2_AddKey(animation2, &key);
7736     ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
7737 
7738     memset(&key, 0, sizeof(key));
7739     key.dwSize = sizeof(key);
7740     key.dwKeyType = D3DRMANIMATION_POSITIONKEY;
7741     key.dvPositionKey.x = 8.0f;
7742     hr = IDirect3DRMAnimation2_AddKey(animation2, &key);
7743     ok(SUCCEEDED(hr), "Failed to add key, hr %#x.\n", hr);
7744 
7745     /* Delete tests. */
7746     hr = IDirect3DRMAnimation_AddRotateKey(animation, 0.0f, &q);
7747     ok(SUCCEEDED(hr), "Failed to add rotation key, hr %#.x\n", hr);
7748 
7749     hr = IDirect3DRMAnimation_AddScaleKey(animation, 0.0f, 1.0f, 2.0f, 1.0f);
7750     ok(SUCCEEDED(hr), "Failed to add scale key, hr %#x.\n", hr);
7751 
7752     count = 0;
7753     memset(keys, 0, sizeof(keys));
7754     hr = IDirect3DRMAnimation2_GetKeys(animation2, -1000.0f, 1000.0f, &count, keys);
7755     ok(SUCCEEDED(hr), "Failed to get key count, hr %#x.\n", hr);
7756     ok(count == 9, "Unexpected key count %u.\n", count);
7757 
7758     ok(keys[0].dwKeyType == D3DRMANIMATION_ROTATEKEY, "Unexpected key type %u.\n", keys[0].dwKeyType);
7759     ok(keys[1].dwKeyType == D3DRMANIMATION_ROTATEKEY, "Unexpected key type %u.\n", keys[1].dwKeyType);
7760     ok(keys[2].dwKeyType == D3DRMANIMATION_POSITIONKEY, "Unexpected key type %u.\n", keys[2].dwKeyType);
7761     ok(keys[3].dwKeyType == D3DRMANIMATION_POSITIONKEY, "Unexpected key type %u.\n", keys[3].dwKeyType);
7762     ok(keys[4].dwKeyType == D3DRMANIMATION_POSITIONKEY, "Unexpected key type %u.\n", keys[4].dwKeyType);
7763     ok(keys[5].dwKeyType == D3DRMANIMATION_POSITIONKEY, "Unexpected key type %u.\n", keys[5].dwKeyType);
7764     ok(keys[6].dwKeyType == D3DRMANIMATION_POSITIONKEY, "Unexpected key type %u.\n", keys[6].dwKeyType);
7765     ok(keys[7].dwKeyType == D3DRMANIMATION_SCALEKEY, "Unexpected key type %u.\n", keys[7].dwKeyType);
7766     ok(keys[8].dwKeyType == D3DRMANIMATION_SCALEKEY, "Unexpected key type %u.\n", keys[8].dwKeyType);
7767 
7768     ok(keys[0].dvTime == 0.0f, "Unexpected key time %.8e.\n", keys[0].dvTime);
7769     ok(keys[1].dvTime == 0.0f, "Unexpected key time %.8e.\n", keys[1].dvTime);
7770     ok(keys[2].dvTime == 0.0f, "Unexpected key time %.8e.\n", keys[2].dvTime);
7771     ok(keys[3].dvTime == 0.0f, "Unexpected key time %.8e.\n", keys[3].dvTime);
7772     ok(keys[4].dvTime == 0.0f, "Unexpected key time %.8e.\n", keys[4].dvTime);
7773     ok(keys[5].dvTime == 80.0f, "Unexpected key time %.8e.\n", keys[5].dvTime);
7774     ok(keys[6].dvTime == 99.0f, "Unexpected key time %.8e.\n", keys[6].dvTime);
7775     ok(keys[7].dvTime == 0.0f, "Unexpected key time %.8e.\n", keys[7].dvTime);
7776     ok(keys[8].dvTime == 0.0f, "Unexpected key time %.8e.\n", keys[8].dvTime);
7777 
7778     hr = IDirect3DRMAnimation_DeleteKey(animation, -100.0f);
7779     ok(SUCCEEDED(hr), "Failed to delete keys, hr %#x.\n", hr);
7780 
7781     hr = IDirect3DRMAnimation_DeleteKey(animation, 100.0f);
7782     ok(SUCCEEDED(hr), "Failed to delete keys, hr %#x.\n", hr);
7783 
7784     /* Only first Position keys are not removed. */
7785     hr = IDirect3DRMAnimation_DeleteKey(animation, 0.0f);
7786     ok(SUCCEEDED(hr), "Failed to delete keys, hr %#x.\n", hr);
7787 
7788     count = 0;
7789     memset(keys, 0, sizeof(keys));
7790     hr = IDirect3DRMAnimation2_GetKeys(animation2, 0.0f, 100.0f, &count, keys);
7791     ok(SUCCEEDED(hr), "Failed to get key count, hr %#x.\n", hr);
7792     ok(count == 6, "Unexpected key count %u.\n", count);
7793 
7794     ok(keys[0].dwKeyType == D3DRMANIMATION_ROTATEKEY, "Unexpected key type %u.\n", keys[0].dwKeyType);
7795     ok(keys[1].dwKeyType == D3DRMANIMATION_POSITIONKEY, "Unexpected key type %u.\n", keys[1].dwKeyType);
7796     ok(keys[2].dwKeyType == D3DRMANIMATION_POSITIONKEY, "Unexpected key type %u.\n", keys[2].dwKeyType);
7797     ok(keys[3].dwKeyType == D3DRMANIMATION_POSITIONKEY, "Unexpected key type %u.\n", keys[3].dwKeyType);
7798     ok(keys[4].dwKeyType == D3DRMANIMATION_POSITIONKEY, "Unexpected key type %u.\n", keys[4].dwKeyType);
7799     ok(keys[5].dwKeyType == D3DRMANIMATION_SCALEKEY, "Unexpected key type %u.\n", keys[5].dwKeyType);
7800 
7801     ok(keys[0].dvTime == 0.0f, "Unexpected key time %.8e.\n", keys[0].dvTime);
7802     ok(keys[1].dvTime == 0.0f, "Unexpected key time %.8e.\n", keys[1].dvTime);
7803     ok(keys[2].dvTime == 0.0f, "Unexpected key time %.8e.\n", keys[2].dvTime);
7804     ok(keys[3].dvTime == 80.0f, "Unexpected key time %.8e.\n", keys[3].dvTime);
7805     ok(keys[4].dvTime == 99.0f, "Unexpected key time %.8e.\n", keys[4].dvTime);
7806     ok(keys[5].dvTime == 0.0f, "Unexpected key time %.8e.\n", keys[5].dvTime);
7807 
7808     hr = IDirect3DRMAnimation_DeleteKey(animation, 0.0f);
7809     ok(SUCCEEDED(hr), "Failed to delete keys, hr %#x.\n", hr);
7810 
7811     count = 0;
7812     hr = IDirect3DRMAnimation2_GetKeys(animation2, 0.0f, 100.0f, &count, NULL);
7813     ok(SUCCEEDED(hr), "Failed to get key count, hr %#x.\n", hr);
7814     ok(count == 3, "Unexpected key count %u.\n", count);
7815 
7816     IDirect3DRMAnimation2_Release(animation2);
7817     IDirect3DRMAnimation_Release(animation);
7818 
7819     IDirect3DRM_Release(d3drm1);
7820 }
7821 
test_animation_qi(void)7822 static void test_animation_qi(void)
7823 {
7824     static const struct qi_test tests[] =
7825     {
7826         { &IID_IDirect3DRMAnimation2,      &IID_IUnknown, &IID_IDirect3DRMAnimation2, S_OK                      },
7827         { &IID_IDirect3DRMAnimation,       &IID_IUnknown, &IID_IDirect3DRMAnimation,  S_OK                      },
7828         { &IID_IDirect3DRM,                NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7829         { &IID_IDirect3DRMDevice,          NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7830         { &IID_IDirect3DRMObject,          &IID_IUnknown, &IID_IDirect3DRMAnimation,  S_OK                      },
7831         { &IID_IDirect3DRMDevice2,         NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7832         { &IID_IDirect3DRMDevice3,         NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7833         { &IID_IDirect3DRMViewport,        NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7834         { &IID_IDirect3DRMViewport2,       NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7835         { &IID_IDirect3DRM3,               NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7836         { &IID_IDirect3DRM2,               NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7837         { &IID_IDirect3DRMVisual,          NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7838         { &IID_IDirect3DRMMesh,            NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7839         { &IID_IDirect3DRMMeshBuilder,     NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7840         { &IID_IDirect3DRMMeshBuilder2,    NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7841         { &IID_IDirect3DRMMeshBuilder3,    NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7842         { &IID_IDirect3DRMFace,            NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7843         { &IID_IDirect3DRMFace2,           NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7844         { &IID_IDirect3DRMLight,           NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7845         { &IID_IDirect3DRMTexture,         NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7846         { &IID_IDirect3DRMTexture2,        NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7847         { &IID_IDirect3DRMTexture3,        NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7848         { &IID_IDirect3DRMMaterial,        NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7849         { &IID_IDirect3DRMMaterial2,       NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7850         { &IID_IDirect3DRMAnimationSet,    NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7851         { &IID_IDirect3DRMAnimationSet2,   NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7852         { &IID_IDirect3DRMObjectArray,     NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7853         { &IID_IDirect3DRMDeviceArray,     NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7854         { &IID_IDirect3DRMViewportArray,   NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7855         { &IID_IDirect3DRMFrameArray,      NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7856         { &IID_IDirect3DRMVisualArray,     NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7857         { &IID_IDirect3DRMLightArray,      NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7858         { &IID_IDirect3DRMPickedArray,     NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7859         { &IID_IDirect3DRMFaceArray,       NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7860         { &IID_IDirect3DRMAnimationArray,  NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7861         { &IID_IDirect3DRMUserVisual,      NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7862         { &IID_IDirect3DRMShadow,          NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7863         { &IID_IDirect3DRMShadow2,         NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7864         { &IID_IDirect3DRMInterpolator,    NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7865         { &IID_IDirect3DRMProgressiveMesh, NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7866         { &IID_IDirect3DRMPicked2Array,    NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7867         { &IID_IDirect3DRMClippedVisual,   NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7868         { &IID_IDirectDrawClipper,         NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7869         { &IID_IDirectDrawSurface7,        NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7870         { &IID_IDirectDrawSurface4,        NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7871         { &IID_IDirectDrawSurface3,        NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7872         { &IID_IDirectDrawSurface2,        NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7873         { &IID_IDirectDrawSurface,         NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7874         { &IID_IDirect3DDevice7,           NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7875         { &IID_IDirect3DDevice3,           NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7876         { &IID_IDirect3DDevice2,           NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7877         { &IID_IDirect3DDevice,            NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7878         { &IID_IDirect3D7,                 NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7879         { &IID_IDirect3D3,                 NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7880         { &IID_IDirect3D2,                 NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7881         { &IID_IDirect3D,                  NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7882         { &IID_IDirectDraw7,               NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7883         { &IID_IDirectDraw4,               NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7884         { &IID_IDirectDraw3,               NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7885         { &IID_IDirectDraw2,               NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7886         { &IID_IDirectDraw,                NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7887         { &IID_IDirect3DLight,             NULL,          NULL,                       CLASS_E_CLASSNOTAVAILABLE },
7888         { &IID_IUnknown,                   &IID_IUnknown, NULL,                       S_OK                      },
7889     };
7890     IDirect3DRMAnimation2 *animation2;
7891     IDirect3DRMAnimation *animation;
7892     IDirect3DRM3 *d3drm3;
7893     IDirect3DRM *d3drm1;
7894     IUnknown *unknown;
7895     HRESULT hr;
7896 
7897     hr = Direct3DRMCreate(&d3drm1);
7898     ok(SUCCEEDED(hr), "Failed to create d3drm instance, hr %#x.\n", hr);
7899 
7900     hr = IDirect3DRM_CreateAnimation(d3drm1, &animation);
7901     ok(SUCCEEDED(hr), "Failed to create animation hr %#x.\n", hr);
7902 
7903     hr = IDirect3DRMAnimation_QueryInterface(animation, &IID_IUnknown, (void **)&unknown);
7904     ok(SUCCEEDED(hr), "Failed to get IUnknown from animation, hr %#x.\n", hr);
7905     IDirect3DRMAnimation_Release(animation);
7906 
7907     test_qi("animation_qi", unknown, &IID_IUnknown, tests, ARRAY_SIZE(tests));
7908     IUnknown_Release(unknown);
7909 
7910     hr = IDirect3DRM_QueryInterface(d3drm1, &IID_IDirect3DRM3, (void **)&d3drm3);
7911     ok(SUCCEEDED(hr), "Failed to get IDirect3DRM3, hr %#x.\n", hr);
7912 
7913     hr = IDirect3DRM3_CreateAnimation(d3drm3, &animation2);
7914     ok(SUCCEEDED(hr), "Failed to create animation hr %#x.\n", hr);
7915 
7916     hr = IDirect3DRMAnimation2_QueryInterface(animation2, &IID_IUnknown, (void **)&unknown);
7917     ok(SUCCEEDED(hr), "Failed to get IUnknown from animation, hr %#x.\n", hr);
7918     IDirect3DRMAnimation2_Release(animation2);
7919 
7920     test_qi("animation2_qi", unknown, &IID_IUnknown, tests, ARRAY_SIZE(tests));
7921     IUnknown_Release(unknown);
7922 
7923     IDirect3DRM3_Release(d3drm3);
7924     IDirect3DRM_Release(d3drm1);
7925 }
7926 
test_wrap(void)7927 static void test_wrap(void)
7928 {
7929     IDirect3DRMWrap *wrap;
7930     IDirect3DRM *d3drm1;
7931     HRESULT hr;
7932 
7933     hr = Direct3DRMCreate(&d3drm1);
7934     ok(SUCCEEDED(hr), "Failed to create IDirect3DRM instance, hr %#x.\n", hr);
7935 
7936     hr = IDirect3DRM_CreateObject(d3drm1, &CLSID_CDirect3DRMWrap, NULL, &IID_IDirect3DRMWrap, (void **)&wrap);
7937     ok(SUCCEEDED(hr), "Failed to create wrap instance, hr %#x.\n", hr);
7938 
7939     test_class_name((IDirect3DRMObject *)wrap, "");
7940 
7941     IDirect3DRMWrap_Release(wrap);
7942     IDirect3DRM_Release(d3drm1);
7943 }
7944 
test_wrap_qi(void)7945 static void test_wrap_qi(void)
7946 {
7947     static const struct qi_test tests[] =
7948     {
7949         { &IID_IDirect3DRMWrap,            &IID_IUnknown, &IID_IDirect3DRMWrap,   S_OK                      },
7950         { &IID_IDirect3DRM,                NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7951         { &IID_IDirect3DRMDevice,          NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7952         { &IID_IDirect3DRMObject,          &IID_IUnknown, &IID_IDirect3DRMWrap,   S_OK                      },
7953         { &IID_IDirect3DRMDevice2,         NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7954         { &IID_IDirect3DRMDevice3,         NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7955         { &IID_IDirect3DRMViewport,        NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7956         { &IID_IDirect3DRMViewport2,       NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7957         { &IID_IDirect3DRM3,               NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7958         { &IID_IDirect3DRM2,               NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7959         { &IID_IDirect3DRMVisual,          NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7960         { &IID_IDirect3DRMMesh,            NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7961         { &IID_IDirect3DRMMeshBuilder,     NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7962         { &IID_IDirect3DRMMeshBuilder2,    NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7963         { &IID_IDirect3DRMMeshBuilder3,    NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7964         { &IID_IDirect3DRMFace,            NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7965         { &IID_IDirect3DRMFace2,           NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7966         { &IID_IDirect3DRMLight,           NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7967         { &IID_IDirect3DRMTexture,         NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7968         { &IID_IDirect3DRMTexture2,        NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7969         { &IID_IDirect3DRMTexture3,        NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7970         { &IID_IDirect3DRMMaterial,        NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7971         { &IID_IDirect3DRMMaterial2,       NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7972         { &IID_IDirect3DRMAnimation,       NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7973         { &IID_IDirect3DRMAnimation2,      NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7974         { &IID_IDirect3DRMAnimationSet,    NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7975         { &IID_IDirect3DRMAnimationSet2,   NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7976         { &IID_IDirect3DRMObjectArray,     NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7977         { &IID_IDirect3DRMDeviceArray,     NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7978         { &IID_IDirect3DRMViewportArray,   NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7979         { &IID_IDirect3DRMFrameArray,      NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7980         { &IID_IDirect3DRMVisualArray,     NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7981         { &IID_IDirect3DRMLightArray,      NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7982         { &IID_IDirect3DRMPickedArray,     NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7983         { &IID_IDirect3DRMFaceArray,       NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7984         { &IID_IDirect3DRMAnimationArray,  NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7985         { &IID_IDirect3DRMUserVisual,      NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7986         { &IID_IDirect3DRMShadow,          NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7987         { &IID_IDirect3DRMShadow2,         NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7988         { &IID_IDirect3DRMInterpolator,    NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7989         { &IID_IDirect3DRMProgressiveMesh, NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7990         { &IID_IDirect3DRMPicked2Array,    NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7991         { &IID_IDirect3DRMClippedVisual,   NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7992         { &IID_IDirectDrawClipper,         NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7993         { &IID_IDirectDrawSurface7,        NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7994         { &IID_IDirectDrawSurface4,        NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7995         { &IID_IDirectDrawSurface3,        NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7996         { &IID_IDirectDrawSurface2,        NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7997         { &IID_IDirectDrawSurface,         NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7998         { &IID_IDirect3DDevice7,           NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
7999         { &IID_IDirect3DDevice3,           NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
8000         { &IID_IDirect3DDevice2,           NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
8001         { &IID_IDirect3DDevice,            NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
8002         { &IID_IDirect3D7,                 NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
8003         { &IID_IDirect3D3,                 NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
8004         { &IID_IDirect3D2,                 NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
8005         { &IID_IDirect3D,                  NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
8006         { &IID_IDirectDraw7,               NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
8007         { &IID_IDirectDraw4,               NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
8008         { &IID_IDirectDraw3,               NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
8009         { &IID_IDirectDraw2,               NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
8010         { &IID_IDirectDraw,                NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
8011         { &IID_IDirect3DLight,             NULL,          NULL,                   CLASS_E_CLASSNOTAVAILABLE },
8012         { &IID_IUnknown,                   &IID_IUnknown, NULL,                   S_OK                      },
8013     };
8014     IDirect3DRMWrap *wrap;
8015     IDirect3DRM *d3drm1;
8016     IUnknown *unknown;
8017     HRESULT hr;
8018 
8019     hr = Direct3DRMCreate(&d3drm1);
8020     ok(SUCCEEDED(hr), "Failed to create d3drm instance, hr %#x.\n", hr);
8021 
8022     hr = IDirect3DRM_CreateObject(d3drm1, &CLSID_CDirect3DRMWrap, NULL, &IID_IDirect3DRMWrap, (void **)&wrap);
8023     ok(SUCCEEDED(hr), "Failed to create wrap instance, hr %#x.\n", hr);
8024 
8025     hr = IDirect3DRMWrap_QueryInterface(wrap, &IID_IUnknown, (void **)&unknown);
8026     ok(SUCCEEDED(hr), "Failed to get IUnknown from wrap (hr = %#x)\n", hr);
8027     IDirect3DRMWrap_Release(wrap);
8028     test_qi("wrap_qi", unknown, &IID_IUnknown, tests, ARRAY_SIZE(tests));
8029     IUnknown_Release(unknown);
8030 
8031     IDirect3DRM_Release(d3drm1);
8032 }
START_TEST(d3drm)8033 START_TEST(d3drm)
8034 {
8035     test_MeshBuilder();
8036     test_MeshBuilder3();
8037     test_Mesh();
8038     test_Face();
8039     test_Frame();
8040     test_Device();
8041     test_object();
8042     test_Viewport();
8043     test_Light();
8044     test_Material2();
8045     test_Texture();
8046     test_frame_transform();
8047     test_d3drm_load();
8048     test_frame_mesh_materials();
8049     test_d3drm_qi();
8050     test_frame_qi();
8051     test_device_qi();
8052     test_create_device_from_clipper1();
8053     test_create_device_from_clipper2();
8054     test_create_device_from_clipper3();
8055     test_create_device_from_surface1();
8056     test_create_device_from_surface2();
8057     test_create_device_from_surface3();
8058     test_create_device_from_d3d1();
8059     test_create_device_from_d3d2();
8060     test_create_device_from_d3d3();
8061     test_create_device_1();
8062     test_create_device_2();
8063     test_create_device_3();
8064     test_load_texture();
8065     test_texture_qi();
8066     test_viewport_qi();
8067     test_viewport_clear1();
8068     test_viewport_clear2();
8069     test_create_texture_from_surface();
8070     test_animation();
8071     test_animation_qi();
8072     test_wrap();
8073     test_wrap_qi();
8074 }
8075