xref: /reactos/dll/directx/wine/d3drm/frame.c (revision 1734f297)
1 /*
2  * Implementation of IDirect3DRMFrame Interface
3  *
4  * Copyright 2011, 2012 André Hentschel
5  * Copyright 2012 Christian Costa
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 "d3drm_private.h"
23 
24 WINE_DEFAULT_DEBUG_CHANNEL(d3drm);
25 
26 static const struct d3drm_matrix identity =
27 {
28     1.0f, 0.0f, 0.0f, 0.0f,
29     0.0f, 1.0f, 0.0f, 0.0f,
30     0.0f, 0.0f, 1.0f, 0.0f,
31     0.0f, 0.0f, 0.0f, 1.0f,
32 };
33 
34 struct d3drm_frame_array
35 {
36     IDirect3DRMFrameArray IDirect3DRMFrameArray_iface;
37     LONG ref;
38     ULONG size;
39     IDirect3DRMFrame **frames;
40 };
41 
42 struct d3drm_visual_array
43 {
44     IDirect3DRMVisualArray IDirect3DRMVisualArray_iface;
45     LONG ref;
46     ULONG size;
47     IDirect3DRMVisual **visuals;
48 };
49 
50 struct d3drm_light_array
51 {
52     IDirect3DRMLightArray IDirect3DRMLightArray_iface;
53     LONG ref;
54     ULONG size;
55     IDirect3DRMLight **lights;
56 };
57 
58 static inline struct d3drm_frame *impl_from_IDirect3DRMFrame(IDirect3DRMFrame *iface)
59 {
60     return CONTAINING_RECORD(iface, struct d3drm_frame, IDirect3DRMFrame_iface);
61 }
62 
63 static inline struct d3drm_frame *impl_from_IDirect3DRMFrame2(IDirect3DRMFrame2 *iface)
64 {
65     return CONTAINING_RECORD(iface, struct d3drm_frame, IDirect3DRMFrame2_iface);
66 }
67 
68 static inline struct d3drm_frame *impl_from_IDirect3DRMFrame3(IDirect3DRMFrame3 *iface)
69 {
70     return CONTAINING_RECORD(iface, struct d3drm_frame, IDirect3DRMFrame3_iface);
71 }
72 
73 static inline struct d3drm_frame_array *impl_from_IDirect3DRMFrameArray(IDirect3DRMFrameArray *iface)
74 {
75     return CONTAINING_RECORD(iface, struct d3drm_frame_array, IDirect3DRMFrameArray_iface);
76 }
77 
78 static inline struct d3drm_visual_array *impl_from_IDirect3DRMVisualArray(IDirect3DRMVisualArray *iface)
79 {
80     return CONTAINING_RECORD(iface, struct d3drm_visual_array, IDirect3DRMVisualArray_iface);
81 }
82 
83 static inline struct d3drm_light_array *impl_from_IDirect3DRMLightArray(IDirect3DRMLightArray *iface)
84 {
85     return CONTAINING_RECORD(iface, struct d3drm_light_array, IDirect3DRMLightArray_iface);
86 }
87 
88 static inline struct d3drm_animation *impl_from_IDirect3DRMAnimation(IDirect3DRMAnimation *iface)
89 {
90     return CONTAINING_RECORD(iface, struct d3drm_animation, IDirect3DRMAnimation_iface);
91 }
92 
93 static inline struct d3drm_animation *impl_from_IDirect3DRMAnimation2(IDirect3DRMAnimation2 *iface)
94 {
95     return CONTAINING_RECORD(iface, struct d3drm_animation, IDirect3DRMAnimation2_iface);
96 }
97 
98 static void d3drm_matrix_multiply_affine(struct d3drm_matrix *dst,
99         const struct d3drm_matrix *src1, const struct d3drm_matrix *src2)
100 {
101     struct d3drm_matrix tmp;
102 
103     tmp._11 = src1->_11 * src2->_11 + src1->_12 * src2->_21 + src1->_13 * src2->_31;
104     tmp._12 = src1->_11 * src2->_12 + src1->_12 * src2->_22 + src1->_13 * src2->_32;
105     tmp._13 = src1->_11 * src2->_13 + src1->_12 * src2->_23 + src1->_13 * src2->_33;
106     tmp._14 = 0.0f;
107 
108     tmp._21 = src1->_21 * src2->_11 + src1->_22 * src2->_21 + src1->_23 * src2->_31;
109     tmp._22 = src1->_21 * src2->_12 + src1->_22 * src2->_22 + src1->_23 * src2->_32;
110     tmp._23 = src1->_21 * src2->_13 + src1->_22 * src2->_23 + src1->_23 * src2->_33;
111     tmp._24 = 0.0f;
112 
113     tmp._31 = src1->_31 * src2->_11 + src1->_32 * src2->_21 + src1->_33 * src2->_31;
114     tmp._32 = src1->_31 * src2->_12 + src1->_32 * src2->_22 + src1->_33 * src2->_32;
115     tmp._33 = src1->_31 * src2->_13 + src1->_32 * src2->_23 + src1->_33 * src2->_33;
116     tmp._34 = 0.0f;
117 
118     tmp._41 = src1->_41 * src2->_11 + src1->_42 * src2->_21 + src1->_43 * src2->_31 + src2->_41;
119     tmp._42 = src1->_41 * src2->_12 + src1->_42 * src2->_22 + src1->_43 * src2->_32 + src2->_42;
120     tmp._43 = src1->_41 * src2->_13 + src1->_42 * src2->_23 + src1->_43 * src2->_33 + src2->_43;
121     tmp._44 = 1.0f;
122 
123     *dst = tmp;
124 }
125 
126 static void d3drm_matrix_set_rotation(struct d3drm_matrix *matrix, D3DVECTOR *axis, float theta)
127 {
128     float sin_theta, cos_theta, vers_theta;
129 
130     D3DRMVectorNormalize(axis);
131     sin_theta = sinf(theta);
132     cos_theta = cosf(theta);
133     vers_theta = 1.0f - cos_theta;
134 
135     matrix->_11 = vers_theta * axis->u1.x * axis->u1.x + cos_theta;
136     matrix->_21 = vers_theta * axis->u1.x * axis->u2.y - sin_theta * axis->u3.z;
137     matrix->_31 = vers_theta * axis->u1.x * axis->u3.z + sin_theta * axis->u2.y;
138     matrix->_41 = 0.0f;
139 
140     matrix->_12 = vers_theta * axis->u2.y * axis->u1.x + sin_theta * axis->u3.z;
141     matrix->_22 = vers_theta * axis->u2.y * axis->u2.y + cos_theta;
142     matrix->_32 = vers_theta * axis->u2.y * axis->u3.z - sin_theta * axis->u1.x;
143     matrix->_42 = 0.0f;
144 
145     matrix->_13 = vers_theta * axis->u3.z * axis->u1.x - sin_theta * axis->u2.y;
146     matrix->_23 = vers_theta * axis->u3.z * axis->u2.y + sin_theta * axis->u1.x;
147     matrix->_33 = vers_theta * axis->u3.z * axis->u3.z + cos_theta;
148     matrix->_43 = 0.0f;
149 
150     matrix->_14 = 0.0f;
151     matrix->_24 = 0.0f;
152     matrix->_34 = 0.0f;
153     matrix->_44 = 1.0f;
154 }
155 
156 static void d3drm_vector_transform_affine(D3DVECTOR *dst, const D3DVECTOR *v, const struct d3drm_matrix *m)
157 {
158     D3DVECTOR tmp;
159 
160     tmp.u1.x = v->u1.x * m->_11 + v->u2.y * m->_21 + v->u3.z * m->_31 + m->_41;
161     tmp.u2.y = v->u1.x * m->_12 + v->u2.y * m->_22 + v->u3.z * m->_32 + m->_42;
162     tmp.u3.z = v->u1.x * m->_13 + v->u2.y * m->_23 + v->u3.z * m->_33 + m->_43;
163 
164     *dst = tmp;
165 }
166 
167 static HRESULT WINAPI d3drm_frame_array_QueryInterface(IDirect3DRMFrameArray *iface, REFIID riid, void **out)
168 {
169     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
170 
171     if (IsEqualGUID(riid, &IID_IDirect3DRMFrameArray)
172             || IsEqualGUID(riid, &IID_IUnknown))
173     {
174         IDirect3DRMFrameArray_AddRef(iface);
175         *out = iface;
176         return S_OK;
177     }
178 
179     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
180 
181     *out = NULL;
182     return E_NOINTERFACE;
183 }
184 
185 static ULONG WINAPI d3drm_frame_array_AddRef(IDirect3DRMFrameArray *iface)
186 {
187     struct d3drm_frame_array *array = impl_from_IDirect3DRMFrameArray(iface);
188     ULONG refcount = InterlockedIncrement(&array->ref);
189 
190     TRACE("%p increasing refcount to %u.\n", iface, refcount);
191 
192     return refcount;
193 }
194 
195 static ULONG WINAPI d3drm_frame_array_Release(IDirect3DRMFrameArray *iface)
196 {
197     struct d3drm_frame_array *array = impl_from_IDirect3DRMFrameArray(iface);
198     ULONG refcount = InterlockedDecrement(&array->ref);
199     ULONG i;
200 
201     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
202 
203     if (!refcount)
204     {
205         for (i = 0; i < array->size; ++i)
206         {
207             IDirect3DRMFrame_Release(array->frames[i]);
208         }
209         heap_free(array->frames);
210         heap_free(array);
211     }
212 
213     return refcount;
214 }
215 
216 static DWORD WINAPI d3drm_frame_array_GetSize(IDirect3DRMFrameArray *iface)
217 {
218     struct d3drm_frame_array *array = impl_from_IDirect3DRMFrameArray(iface);
219 
220     TRACE("iface %p.\n", iface);
221 
222     return array->size;
223 }
224 
225 static HRESULT WINAPI d3drm_frame_array_GetElement(IDirect3DRMFrameArray *iface,
226         DWORD index, IDirect3DRMFrame **frame)
227 {
228     struct d3drm_frame_array *array = impl_from_IDirect3DRMFrameArray(iface);
229 
230     TRACE("iface %p, index %u, frame %p.\n", iface, index, frame);
231 
232     if (!frame)
233         return D3DRMERR_BADVALUE;
234 
235     if (index >= array->size)
236     {
237         *frame = NULL;
238         return D3DRMERR_BADVALUE;
239     }
240 
241     IDirect3DRMFrame_AddRef(array->frames[index]);
242     *frame = array->frames[index];
243 
244     return D3DRM_OK;
245 }
246 
247 static const struct IDirect3DRMFrameArrayVtbl d3drm_frame_array_vtbl =
248 {
249     d3drm_frame_array_QueryInterface,
250     d3drm_frame_array_AddRef,
251     d3drm_frame_array_Release,
252     d3drm_frame_array_GetSize,
253     d3drm_frame_array_GetElement,
254 };
255 
256 static struct d3drm_frame_array *d3drm_frame_array_create(unsigned int frame_count, IDirect3DRMFrame3 **frames)
257 {
258     struct d3drm_frame_array *array;
259     unsigned int i;
260 
261     if (!(array = heap_alloc_zero(sizeof(*array))))
262         return NULL;
263 
264     array->IDirect3DRMFrameArray_iface.lpVtbl = &d3drm_frame_array_vtbl;
265     array->ref = 1;
266     array->size = frame_count;
267 
268     if (frame_count)
269     {
270         if (!(array->frames = heap_calloc(frame_count, sizeof(*array->frames))))
271         {
272             heap_free(array);
273             return NULL;
274         }
275 
276         for (i = 0; i < frame_count; ++i)
277         {
278             IDirect3DRMFrame3_QueryInterface(frames[i], &IID_IDirect3DRMFrame, (void **)&array->frames[i]);
279         }
280     }
281 
282     return array;
283 }
284 
285 static HRESULT WINAPI d3drm_visual_array_QueryInterface(IDirect3DRMVisualArray *iface, REFIID riid, void **out)
286 {
287     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
288 
289     if (IsEqualGUID(riid, &IID_IDirect3DRMVisualArray)
290             || IsEqualGUID(riid, &IID_IUnknown))
291     {
292         IDirect3DRMVisualArray_AddRef(iface);
293         *out = iface;
294         return S_OK;
295     }
296 
297     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
298 
299     *out = NULL;
300     return E_NOINTERFACE;
301 }
302 
303 static ULONG WINAPI d3drm_visual_array_AddRef(IDirect3DRMVisualArray *iface)
304 {
305     struct d3drm_visual_array *array = impl_from_IDirect3DRMVisualArray(iface);
306     ULONG refcount = InterlockedIncrement(&array->ref);
307 
308     TRACE("%p increasing refcount to %u.\n", iface, refcount);
309 
310     return refcount;
311 }
312 
313 static ULONG WINAPI d3drm_visual_array_Release(IDirect3DRMVisualArray *iface)
314 {
315     struct d3drm_visual_array *array = impl_from_IDirect3DRMVisualArray(iface);
316     ULONG refcount = InterlockedDecrement(&array->ref);
317     ULONG i;
318 
319     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
320 
321     if (!refcount)
322     {
323         for (i = 0; i < array->size; ++i)
324         {
325             IDirect3DRMVisual_Release(array->visuals[i]);
326         }
327         heap_free(array->visuals);
328         heap_free(array);
329     }
330 
331     return refcount;
332 }
333 
334 static DWORD WINAPI d3drm_visual_array_GetSize(IDirect3DRMVisualArray *iface)
335 {
336     struct d3drm_visual_array *array = impl_from_IDirect3DRMVisualArray(iface);
337 
338     TRACE("iface %p.\n", iface);
339 
340     return array->size;
341 }
342 
343 static HRESULT WINAPI d3drm_visual_array_GetElement(IDirect3DRMVisualArray *iface,
344         DWORD index, IDirect3DRMVisual **visual)
345 {
346     struct d3drm_visual_array *array = impl_from_IDirect3DRMVisualArray(iface);
347 
348     TRACE("iface %p, index %u, visual %p.\n", iface, index, visual);
349 
350     if (!visual)
351         return D3DRMERR_BADVALUE;
352 
353     if (index >= array->size)
354     {
355         *visual = NULL;
356         return D3DRMERR_BADVALUE;
357     }
358 
359     IDirect3DRMVisual_AddRef(array->visuals[index]);
360     *visual = array->visuals[index];
361 
362     return D3DRM_OK;
363 }
364 
365 static const struct IDirect3DRMVisualArrayVtbl d3drm_visual_array_vtbl =
366 {
367     d3drm_visual_array_QueryInterface,
368     d3drm_visual_array_AddRef,
369     d3drm_visual_array_Release,
370     d3drm_visual_array_GetSize,
371     d3drm_visual_array_GetElement,
372 };
373 
374 static struct d3drm_visual_array *d3drm_visual_array_create(unsigned int visual_count, IDirect3DRMVisual **visuals)
375 {
376     struct d3drm_visual_array *array;
377     unsigned int i;
378 
379     if (!(array = heap_alloc_zero(sizeof(*array))))
380         return NULL;
381 
382     array->IDirect3DRMVisualArray_iface.lpVtbl = &d3drm_visual_array_vtbl;
383     array->ref = 1;
384     array->size = visual_count;
385 
386     if (visual_count)
387     {
388         if (!(array->visuals = heap_calloc(visual_count, sizeof(*array->visuals))))
389         {
390             heap_free(array);
391             return NULL;
392         }
393 
394         for (i = 0; i < visual_count; ++i)
395         {
396             array->visuals[i] = visuals[i];
397             IDirect3DRMVisual_AddRef(array->visuals[i]);
398         }
399     }
400 
401     return array;
402 }
403 
404 static HRESULT WINAPI d3drm_light_array_QueryInterface(IDirect3DRMLightArray *iface, REFIID riid, void **out)
405 {
406     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
407 
408     if (IsEqualGUID(riid, &IID_IDirect3DRMLightArray)
409             || IsEqualGUID(riid, &IID_IUnknown))
410     {
411         IDirect3DRMLightArray_AddRef(iface);
412         *out = iface;
413         return S_OK;
414     }
415 
416     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
417 
418     *out = NULL;
419     return E_NOINTERFACE;
420 }
421 
422 static ULONG WINAPI d3drm_light_array_AddRef(IDirect3DRMLightArray *iface)
423 {
424     struct d3drm_light_array *array = impl_from_IDirect3DRMLightArray(iface);
425     ULONG refcount = InterlockedIncrement(&array->ref);
426 
427     TRACE("%p increasing refcount to %u.\n", iface, refcount);
428 
429     return refcount;
430 }
431 
432 static ULONG WINAPI d3drm_light_array_Release(IDirect3DRMLightArray *iface)
433 {
434     struct d3drm_light_array *array = impl_from_IDirect3DRMLightArray(iface);
435     ULONG refcount = InterlockedDecrement(&array->ref);
436     ULONG i;
437 
438     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
439 
440     if (!refcount)
441     {
442         for (i = 0; i < array->size; ++i)
443         {
444             IDirect3DRMLight_Release(array->lights[i]);
445         }
446         heap_free(array->lights);
447         heap_free(array);
448     }
449 
450     return refcount;
451 }
452 
453 static DWORD WINAPI d3drm_light_array_GetSize(IDirect3DRMLightArray *iface)
454 {
455     struct d3drm_light_array *array = impl_from_IDirect3DRMLightArray(iface);
456 
457     TRACE("iface %p.\n", iface);
458 
459     return array->size;
460 }
461 
462 static HRESULT WINAPI d3drm_light_array_GetElement(IDirect3DRMLightArray *iface,
463         DWORD index, IDirect3DRMLight **light)
464 {
465     struct d3drm_light_array *array = impl_from_IDirect3DRMLightArray(iface);
466 
467     TRACE("iface %p, index %u, light %p.\n", iface, index, light);
468 
469     if (!light)
470         return D3DRMERR_BADVALUE;
471 
472     if (index >= array->size)
473     {
474         *light = NULL;
475         return D3DRMERR_BADVALUE;
476     }
477 
478     IDirect3DRMLight_AddRef(array->lights[index]);
479     *light = array->lights[index];
480 
481     return D3DRM_OK;
482 }
483 
484 static const struct IDirect3DRMLightArrayVtbl d3drm_light_array_vtbl =
485 {
486     d3drm_light_array_QueryInterface,
487     d3drm_light_array_AddRef,
488     d3drm_light_array_Release,
489     d3drm_light_array_GetSize,
490     d3drm_light_array_GetElement,
491 };
492 
493 static struct d3drm_light_array *d3drm_light_array_create(unsigned int light_count, IDirect3DRMLight **lights)
494 {
495     struct d3drm_light_array *array;
496     unsigned int i;
497 
498     if (!(array = heap_alloc_zero(sizeof(*array))))
499         return NULL;
500 
501     array->IDirect3DRMLightArray_iface.lpVtbl = &d3drm_light_array_vtbl;
502     array->ref = 1;
503     array->size = light_count;
504 
505     if (light_count)
506     {
507         if (!(array->lights = heap_calloc(light_count, sizeof(*array->lights))))
508         {
509             heap_free(array);
510             return NULL;
511         }
512 
513         for (i = 0; i < light_count; ++i)
514         {
515             array->lights[i] = lights[i];
516             IDirect3DRMLight_AddRef(array->lights[i]);
517         }
518     }
519 
520     return array;
521 }
522 
523 static HRESULT WINAPI d3drm_frame3_QueryInterface(IDirect3DRMFrame3 *iface, REFIID riid, void **out)
524 {
525     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
526 
527     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
528 
529     if (IsEqualGUID(riid, &IID_IDirect3DRMFrame)
530             || IsEqualGUID(riid, &IID_IDirect3DRMObject)
531             || IsEqualGUID(riid, &IID_IDirect3DRMVisual)
532             || IsEqualGUID(riid, &IID_IUnknown))
533     {
534         *out = &frame->IDirect3DRMFrame_iface;
535     }
536     else if (IsEqualGUID(riid, &IID_IDirect3DRMFrame2))
537     {
538         *out = &frame->IDirect3DRMFrame2_iface;
539     }
540     else if (IsEqualGUID(riid, &IID_IDirect3DRMFrame3))
541     {
542         *out = &frame->IDirect3DRMFrame3_iface;
543     }
544     else
545     {
546         *out = NULL;
547         WARN("%s not implemented, returning CLASS_E_CLASSNOTAVAILABLE.\n", debugstr_guid(riid));
548         return CLASS_E_CLASSNOTAVAILABLE;
549     }
550 
551     IUnknown_AddRef((IUnknown *)*out);
552     return S_OK;
553 }
554 
555 static HRESULT WINAPI d3drm_frame2_QueryInterface(IDirect3DRMFrame2 *iface, REFIID riid, void **out)
556 {
557     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
558 
559     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
560 
561     return d3drm_frame3_QueryInterface(&frame->IDirect3DRMFrame3_iface, riid, out);
562 }
563 
564 static HRESULT WINAPI d3drm_frame1_QueryInterface(IDirect3DRMFrame *iface, REFIID riid, void **out)
565 {
566     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
567 
568     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
569 
570     return d3drm_frame3_QueryInterface(&frame->IDirect3DRMFrame3_iface, riid, out);
571 }
572 
573 static ULONG WINAPI d3drm_frame3_AddRef(IDirect3DRMFrame3 *iface)
574 {
575     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
576     ULONG refcount = InterlockedIncrement(&frame->ref);
577 
578     TRACE("%p increasing refcount to %u.\n", iface, refcount);
579 
580     return refcount;
581 }
582 
583 static ULONG WINAPI d3drm_frame2_AddRef(IDirect3DRMFrame2 *iface)
584 {
585     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
586 
587     TRACE("iface %p.\n", iface);
588 
589     return d3drm_frame3_AddRef(&frame->IDirect3DRMFrame3_iface);
590 }
591 
592 static ULONG WINAPI d3drm_frame1_AddRef(IDirect3DRMFrame *iface)
593 {
594     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
595 
596     TRACE("iface %p.\n", iface);
597 
598     return d3drm_frame3_AddRef(&frame->IDirect3DRMFrame3_iface);
599 }
600 
601 static ULONG WINAPI d3drm_frame3_Release(IDirect3DRMFrame3 *iface)
602 {
603     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
604     ULONG refcount = InterlockedDecrement(&frame->ref);
605     ULONG i;
606 
607     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
608 
609     if (!refcount)
610     {
611         d3drm_object_cleanup((IDirect3DRMObject *)&frame->IDirect3DRMFrame_iface, &frame->obj);
612         for (i = 0; i < frame->nb_children; ++i)
613         {
614             IDirect3DRMFrame3_Release(frame->children[i]);
615         }
616         heap_free(frame->children);
617         for (i = 0; i < frame->nb_visuals; ++i)
618         {
619             IDirect3DRMVisual_Release(frame->visuals[i]);
620         }
621         heap_free(frame->visuals);
622         for (i = 0; i < frame->nb_lights; ++i)
623         {
624             IDirect3DRMLight_Release(frame->lights[i]);
625         }
626         heap_free(frame->lights);
627         IDirect3DRM_Release(frame->d3drm);
628         heap_free(frame);
629     }
630 
631     return refcount;
632 }
633 
634 static ULONG WINAPI d3drm_frame2_Release(IDirect3DRMFrame2 *iface)
635 {
636     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
637 
638     TRACE("iface %p.\n", iface);
639 
640     return d3drm_frame3_Release(&frame->IDirect3DRMFrame3_iface);
641 }
642 
643 static ULONG WINAPI d3drm_frame1_Release(IDirect3DRMFrame *iface)
644 {
645     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
646 
647     TRACE("iface %p.\n", iface);
648 
649     return d3drm_frame3_Release(&frame->IDirect3DRMFrame3_iface);
650 }
651 
652 static HRESULT WINAPI d3drm_frame3_Clone(IDirect3DRMFrame3 *iface,
653         IUnknown *outer, REFIID iid, void **out)
654 {
655     FIXME("iface %p, outer %p, iid %s, out %p stub!\n", iface, outer, debugstr_guid(iid), out);
656 
657     return E_NOTIMPL;
658 }
659 
660 static HRESULT WINAPI d3drm_frame2_Clone(IDirect3DRMFrame2 *iface,
661         IUnknown *outer, REFIID iid, void **out)
662 {
663     FIXME("iface %p, outer %p, iid %s, out %p stub!\n", iface, outer, debugstr_guid(iid), out);
664 
665     return E_NOTIMPL;
666 }
667 
668 static HRESULT WINAPI d3drm_frame1_Clone(IDirect3DRMFrame *iface,
669         IUnknown *outer, REFIID iid, void **out)
670 {
671     FIXME("iface %p, outer %p, iid %s, out %p stub!\n", iface, outer, debugstr_guid(iid), out);
672 
673     return E_NOTIMPL;
674 }
675 
676 static HRESULT WINAPI d3drm_frame3_AddDestroyCallback(IDirect3DRMFrame3 *iface,
677         D3DRMOBJECTCALLBACK cb, void *ctx)
678 {
679     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
680 
681     TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
682 
683     return d3drm_object_add_destroy_callback(&frame->obj, cb, ctx);
684 }
685 
686 static HRESULT WINAPI d3drm_frame2_AddDestroyCallback(IDirect3DRMFrame2 *iface,
687         D3DRMOBJECTCALLBACK cb, void *ctx)
688 {
689     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
690 
691     TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
692 
693     return IDirect3DRMFrame3_AddDestroyCallback(&frame->IDirect3DRMFrame3_iface, cb, ctx);
694 }
695 
696 static HRESULT WINAPI d3drm_frame1_AddDestroyCallback(IDirect3DRMFrame *iface,
697         D3DRMOBJECTCALLBACK cb, void *ctx)
698 {
699     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
700 
701     TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
702 
703     return IDirect3DRMFrame3_AddDestroyCallback(&frame->IDirect3DRMFrame3_iface, cb, ctx);
704 }
705 
706 static HRESULT WINAPI d3drm_frame3_DeleteDestroyCallback(IDirect3DRMFrame3 *iface,
707         D3DRMOBJECTCALLBACK cb, void *ctx)
708 {
709     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
710 
711     TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
712 
713     return d3drm_object_delete_destroy_callback(&frame->obj, cb, ctx);
714 }
715 
716 static HRESULT WINAPI d3drm_frame2_DeleteDestroyCallback(IDirect3DRMFrame2 *iface,
717         D3DRMOBJECTCALLBACK cb, void *ctx)
718 {
719     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
720 
721     TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
722 
723     return IDirect3DRMFrame3_DeleteDestroyCallback(&frame->IDirect3DRMFrame3_iface, cb, ctx);
724 }
725 
726 static HRESULT WINAPI d3drm_frame1_DeleteDestroyCallback(IDirect3DRMFrame *iface,
727         D3DRMOBJECTCALLBACK cb, void *ctx)
728 {
729     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
730 
731     TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
732 
733     return IDirect3DRMFrame3_DeleteDestroyCallback(&frame->IDirect3DRMFrame3_iface, cb, ctx);
734 }
735 
736 static HRESULT WINAPI d3drm_frame3_SetAppData(IDirect3DRMFrame3 *iface, DWORD data)
737 {
738     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
739 
740     TRACE("iface %p, data %#x.\n", iface, data);
741 
742     frame->obj.appdata = data;
743 
744     return D3DRM_OK;
745 }
746 
747 static HRESULT WINAPI d3drm_frame2_SetAppData(IDirect3DRMFrame2 *iface, DWORD data)
748 {
749     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
750 
751     TRACE("iface %p, data %#x.\n", iface, data);
752 
753     return d3drm_frame3_SetAppData(&frame->IDirect3DRMFrame3_iface, data);
754 }
755 
756 static HRESULT WINAPI d3drm_frame1_SetAppData(IDirect3DRMFrame *iface, DWORD data)
757 {
758     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
759 
760     TRACE("iface %p, data %#x.\n", iface, data);
761 
762     return d3drm_frame3_SetAppData(&frame->IDirect3DRMFrame3_iface, data);
763 }
764 
765 static DWORD WINAPI d3drm_frame3_GetAppData(IDirect3DRMFrame3 *iface)
766 {
767     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
768 
769     TRACE("iface %p.\n", iface);
770 
771     return frame->obj.appdata;
772 }
773 
774 static DWORD WINAPI d3drm_frame2_GetAppData(IDirect3DRMFrame2 *iface)
775 {
776     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
777 
778     TRACE("iface %p.\n", iface);
779 
780     return d3drm_frame3_GetAppData(&frame->IDirect3DRMFrame3_iface);
781 }
782 
783 static DWORD WINAPI d3drm_frame1_GetAppData(IDirect3DRMFrame *iface)
784 {
785     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
786 
787     TRACE("iface %p.\n", iface);
788 
789     return d3drm_frame3_GetAppData(&frame->IDirect3DRMFrame3_iface);
790 }
791 
792 static HRESULT WINAPI d3drm_frame3_SetName(IDirect3DRMFrame3 *iface, const char *name)
793 {
794     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
795 
796     TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
797 
798     return d3drm_object_set_name(&frame->obj, name);
799 }
800 
801 static HRESULT WINAPI d3drm_frame2_SetName(IDirect3DRMFrame2 *iface, const char *name)
802 {
803     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
804 
805     TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
806 
807     return d3drm_frame3_SetName(&frame->IDirect3DRMFrame3_iface, name);
808 }
809 
810 static HRESULT WINAPI d3drm_frame1_SetName(IDirect3DRMFrame *iface, const char *name)
811 {
812     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
813 
814     TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
815 
816     return d3drm_frame3_SetName(&frame->IDirect3DRMFrame3_iface, name);
817 }
818 
819 static HRESULT WINAPI d3drm_frame3_GetName(IDirect3DRMFrame3 *iface, DWORD *size, char *name)
820 {
821     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
822 
823     TRACE("iface %p, size %p, name %p.\n", iface, size, name);
824 
825     return d3drm_object_get_name(&frame->obj, size, name);
826 }
827 
828 static HRESULT WINAPI d3drm_frame2_GetName(IDirect3DRMFrame2 *iface, DWORD *size, char *name)
829 {
830     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
831 
832     TRACE("iface %p, size %p, name %p.\n", iface, size, name);
833 
834     return d3drm_frame3_GetName(&frame->IDirect3DRMFrame3_iface, size, name);
835 }
836 
837 static HRESULT WINAPI d3drm_frame1_GetName(IDirect3DRMFrame *iface, DWORD *size, char *name)
838 {
839     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
840 
841     TRACE("iface %p, size %p, name %p.\n", iface, size, name);
842 
843     return d3drm_frame3_GetName(&frame->IDirect3DRMFrame3_iface, size, name);
844 }
845 
846 static HRESULT WINAPI d3drm_frame3_GetClassName(IDirect3DRMFrame3 *iface, DWORD *size, char *name)
847 {
848     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
849 
850     TRACE("iface %p, size %p, name %p.\n", iface, size, name);
851 
852     return d3drm_object_get_class_name(&frame->obj, size, name);
853 }
854 
855 static HRESULT WINAPI d3drm_frame2_GetClassName(IDirect3DRMFrame2 *iface, DWORD *size, char *name)
856 {
857     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
858 
859     TRACE("iface %p, size %p, name %p.\n", iface, size, name);
860 
861     return d3drm_frame3_GetClassName(&frame->IDirect3DRMFrame3_iface, size, name);
862 }
863 
864 static HRESULT WINAPI d3drm_frame1_GetClassName(IDirect3DRMFrame *iface, DWORD *size, char *name)
865 {
866     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
867 
868     TRACE("iface %p, size %p, name %p.\n", iface, size, name);
869 
870     return d3drm_frame3_GetClassName(&frame->IDirect3DRMFrame3_iface, size, name);
871 }
872 
873 static HRESULT WINAPI d3drm_frame3_AddChild(IDirect3DRMFrame3 *iface, IDirect3DRMFrame3 *child)
874 {
875     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
876     struct d3drm_frame *child_obj = unsafe_impl_from_IDirect3DRMFrame3(child);
877 
878     TRACE("iface %p, child %p.\n", iface, child);
879 
880     if (!child_obj)
881         return D3DRMERR_BADOBJECT;
882 
883     if (child_obj->parent)
884     {
885         IDirect3DRMFrame3* parent = &child_obj->parent->IDirect3DRMFrame3_iface;
886 
887         if (parent == iface)
888         {
889             /* Passed frame is already a child so return success */
890             return D3DRM_OK;
891         }
892         else
893         {
894             /* Remove parent and continue */
895             IDirect3DRMFrame3_DeleteChild(parent, child);
896         }
897     }
898 
899     if (!d3drm_array_reserve((void **)&frame->children, &frame->children_size,
900             frame->nb_children + 1, sizeof(*frame->children)))
901         return E_OUTOFMEMORY;
902 
903     frame->children[frame->nb_children++] = child;
904     IDirect3DRMFrame3_AddRef(child);
905     child_obj->parent = frame;
906 
907     return D3DRM_OK;
908 }
909 
910 static HRESULT WINAPI d3drm_frame2_AddChild(IDirect3DRMFrame2 *iface, IDirect3DRMFrame *child)
911 {
912     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
913     IDirect3DRMFrame3 *child3;
914     HRESULT hr;
915 
916     TRACE("iface %p, child %p.\n", iface, child);
917 
918     if (!child)
919         return D3DRMERR_BADOBJECT;
920     hr = IDirect3DRMFrame_QueryInterface(child, &IID_IDirect3DRMFrame3, (void **)&child3);
921     if (hr != S_OK)
922         return D3DRMERR_BADOBJECT;
923     IDirect3DRMFrame_Release(child);
924 
925     return d3drm_frame3_AddChild(&frame->IDirect3DRMFrame3_iface, child3);
926 }
927 
928 static HRESULT WINAPI d3drm_frame1_AddChild(IDirect3DRMFrame *iface, IDirect3DRMFrame *child)
929 {
930     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
931     struct d3drm_frame *child_frame = unsafe_impl_from_IDirect3DRMFrame(child);
932 
933     TRACE("iface %p, child %p.\n", iface, child);
934 
935     if (!child_frame)
936         return D3DRMERR_BADOBJECT;
937 
938     return d3drm_frame3_AddChild(&frame->IDirect3DRMFrame3_iface, &child_frame->IDirect3DRMFrame3_iface);
939 }
940 
941 static HRESULT WINAPI d3drm_frame3_AddLight(IDirect3DRMFrame3 *iface, IDirect3DRMLight *light)
942 {
943     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
944     ULONG i;
945 
946     TRACE("iface %p, light %p.\n", iface, light);
947 
948     if (!light)
949         return D3DRMERR_BADOBJECT;
950 
951     /* Check if already existing and return gracefully without increasing ref count */
952     for (i = 0; i < frame->nb_lights; i++)
953         if (frame->lights[i] == light)
954             return D3DRM_OK;
955 
956     if (!d3drm_array_reserve((void **)&frame->lights, &frame->lights_size,
957             frame->nb_lights + 1, sizeof(*frame->lights)))
958         return E_OUTOFMEMORY;
959 
960     frame->lights[frame->nb_lights++] = light;
961     IDirect3DRMLight_AddRef(light);
962 
963     return D3DRM_OK;
964 }
965 
966 static HRESULT WINAPI d3drm_frame2_AddLight(IDirect3DRMFrame2 *iface, IDirect3DRMLight *light)
967 {
968     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
969 
970     TRACE("iface %p, light %p.\n", iface, light);
971 
972     return d3drm_frame3_AddLight(&frame->IDirect3DRMFrame3_iface, light);
973 }
974 
975 static HRESULT WINAPI d3drm_frame1_AddLight(IDirect3DRMFrame *iface, IDirect3DRMLight *light)
976 {
977     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
978 
979     TRACE("iface %p, light %p.\n", iface, light);
980 
981     return d3drm_frame3_AddLight(&frame->IDirect3DRMFrame3_iface, light);
982 }
983 
984 static HRESULT WINAPI d3drm_frame3_AddMoveCallback(IDirect3DRMFrame3 *iface,
985         D3DRMFRAME3MOVECALLBACK cb, void *ctx, DWORD flags)
986 {
987     FIXME("iface %p, cb %p, ctx %p flags %#x stub!\n", iface, cb, ctx, flags);
988 
989     return E_NOTIMPL;
990 }
991 
992 static HRESULT WINAPI d3drm_frame2_AddMoveCallback(IDirect3DRMFrame2 *iface,
993         D3DRMFRAMEMOVECALLBACK cb, void *ctx)
994 {
995     FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
996 
997     return E_NOTIMPL;
998 }
999 
1000 static HRESULT WINAPI d3drm_frame1_AddMoveCallback(IDirect3DRMFrame *iface,
1001         D3DRMFRAMEMOVECALLBACK cb, void *ctx)
1002 {
1003     FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
1004 
1005     return E_NOTIMPL;
1006 }
1007 
1008 static HRESULT WINAPI d3drm_frame3_AddTransform(IDirect3DRMFrame3 *iface,
1009         D3DRMCOMBINETYPE type, D3DRMMATRIX4D matrix)
1010 {
1011     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
1012     const struct d3drm_matrix *m = d3drm_matrix(matrix);
1013 
1014     TRACE("iface %p, type %#x, matrix %p.\n", iface, type, matrix);
1015 
1016     if (m->_14 != 0.0f || m->_24 != 0.0f || m->_34 != 0.0f || m->_44 != 1.0f)
1017         return D3DRMERR_BADVALUE;
1018 
1019     switch (type)
1020     {
1021         case D3DRMCOMBINE_REPLACE:
1022             frame->transform = *m;
1023             break;
1024 
1025         case D3DRMCOMBINE_BEFORE:
1026             d3drm_matrix_multiply_affine(&frame->transform, m, &frame->transform);
1027             break;
1028 
1029         case D3DRMCOMBINE_AFTER:
1030             d3drm_matrix_multiply_affine(&frame->transform, &frame->transform, m);
1031             break;
1032 
1033         default:
1034             FIXME("Unhandled type %#x.\n", type);
1035             return D3DRMERR_BADVALUE;
1036     }
1037 
1038     return S_OK;
1039 }
1040 
1041 static HRESULT WINAPI d3drm_frame2_AddTransform(IDirect3DRMFrame2 *iface,
1042         D3DRMCOMBINETYPE type, D3DRMMATRIX4D matrix)
1043 {
1044     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
1045 
1046     TRACE("iface %p, type %#x, matrix %p.\n", iface, type, matrix);
1047 
1048     return d3drm_frame3_AddTransform(&frame->IDirect3DRMFrame3_iface, type, matrix);
1049 }
1050 
1051 static HRESULT WINAPI d3drm_frame1_AddTransform(IDirect3DRMFrame *iface,
1052         D3DRMCOMBINETYPE type, D3DRMMATRIX4D matrix)
1053 {
1054     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
1055 
1056     TRACE("iface %p, type %#x, matrix %p.\n", iface, type, matrix);
1057 
1058     return d3drm_frame3_AddTransform(&frame->IDirect3DRMFrame3_iface, type, matrix);
1059 }
1060 
1061 static HRESULT WINAPI d3drm_frame3_AddTranslation(IDirect3DRMFrame3 *iface,
1062         D3DRMCOMBINETYPE type, D3DVALUE x, D3DVALUE y, D3DVALUE z)
1063 {
1064     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
1065 
1066     TRACE("iface %p, type %#x, x %.8e, y %.8e, z %.8e.\n", iface, type, x, y, z);
1067 
1068     switch (type)
1069     {
1070         case D3DRMCOMBINE_REPLACE:
1071             frame->transform = identity;
1072             frame->transform._41 = x;
1073             frame->transform._42 = y;
1074             frame->transform._43 = z;
1075             break;
1076 
1077         case D3DRMCOMBINE_BEFORE:
1078             frame->transform._41 += x * frame->transform._11 + y * frame->transform._21 + z * frame->transform._31;
1079             frame->transform._42 += x * frame->transform._12 + y * frame->transform._22 + z * frame->transform._32;
1080             frame->transform._43 += x * frame->transform._13 + y * frame->transform._23 + z * frame->transform._33;
1081             break;
1082 
1083         case D3DRMCOMBINE_AFTER:
1084             frame->transform._41 += x;
1085             frame->transform._42 += y;
1086             frame->transform._43 += z;
1087             break;
1088 
1089         default:
1090             FIXME("Unhandled type %#x.\n", type);
1091             return D3DRMERR_BADVALUE;
1092     }
1093 
1094     return D3DRM_OK;
1095 }
1096 
1097 static HRESULT WINAPI d3drm_frame2_AddTranslation(IDirect3DRMFrame2 *iface,
1098         D3DRMCOMBINETYPE type, D3DVALUE x, D3DVALUE y, D3DVALUE z)
1099 {
1100     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
1101 
1102     TRACE("iface %p, type %#x, x %.8e, y %.8e, z %.8e.\n", iface, type, x, y, z);
1103 
1104     return d3drm_frame3_AddTranslation(&frame->IDirect3DRMFrame3_iface, type, x, y, z);
1105 }
1106 
1107 static HRESULT WINAPI d3drm_frame1_AddTranslation(IDirect3DRMFrame *iface,
1108         D3DRMCOMBINETYPE type, D3DVALUE x, D3DVALUE y, D3DVALUE z)
1109 {
1110     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
1111 
1112     TRACE("iface %p, type %#x, x %.8e, y %.8e, z %.8e.\n", iface, type, x, y, z);
1113 
1114     return d3drm_frame3_AddTranslation(&frame->IDirect3DRMFrame3_iface, type, x, y, z);
1115 }
1116 
1117 static HRESULT WINAPI d3drm_frame3_AddScale(IDirect3DRMFrame3 *iface,
1118         D3DRMCOMBINETYPE type, D3DVALUE sx, D3DVALUE sy, D3DVALUE sz)
1119 {
1120     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
1121 
1122     TRACE("iface %p, type %#x, sx %.8e, sy %.8e, sz %.8e.\n", iface, type, sx, sy, sz);
1123 
1124     switch (type)
1125     {
1126         case D3DRMCOMBINE_REPLACE:
1127             frame->transform = identity;
1128             frame->transform._11 = sx;
1129             frame->transform._22 = sy;
1130             frame->transform._33 = sz;
1131             break;
1132 
1133         case D3DRMCOMBINE_BEFORE:
1134             frame->transform._11 *= sx;
1135             frame->transform._12 *= sx;
1136             frame->transform._13 *= sx;
1137             frame->transform._21 *= sy;
1138             frame->transform._22 *= sy;
1139             frame->transform._23 *= sy;
1140             frame->transform._31 *= sz;
1141             frame->transform._32 *= sz;
1142             frame->transform._33 *= sz;
1143             break;
1144 
1145         case D3DRMCOMBINE_AFTER:
1146             frame->transform._11 *= sx;
1147             frame->transform._12 *= sy;
1148             frame->transform._13 *= sz;
1149             frame->transform._21 *= sx;
1150             frame->transform._22 *= sy;
1151             frame->transform._23 *= sz;
1152             frame->transform._31 *= sx;
1153             frame->transform._32 *= sy;
1154             frame->transform._33 *= sz;
1155             frame->transform._41 *= sx;
1156             frame->transform._42 *= sy;
1157             frame->transform._43 *= sz;
1158             break;
1159 
1160         default:
1161             FIXME("Unhandled type %#x.\n", type);
1162             return D3DRMERR_BADVALUE;
1163     }
1164 
1165     return D3DRM_OK;
1166 }
1167 
1168 static HRESULT WINAPI d3drm_frame2_AddScale(IDirect3DRMFrame2 *iface,
1169         D3DRMCOMBINETYPE type, D3DVALUE sx, D3DVALUE sy, D3DVALUE sz)
1170 {
1171     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
1172 
1173     TRACE("iface %p, type %#x, sx %.8e, sy %.8e, sz %.8e.\n", iface, type, sx, sy, sz);
1174 
1175     return d3drm_frame3_AddScale(&frame->IDirect3DRMFrame3_iface, type, sx, sy, sz);
1176 }
1177 
1178 static HRESULT WINAPI d3drm_frame1_AddScale(IDirect3DRMFrame *iface,
1179         D3DRMCOMBINETYPE type, D3DVALUE sx, D3DVALUE sy, D3DVALUE sz)
1180 {
1181     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
1182 
1183     TRACE("iface %p, type %#x, sx %.8e, sy %.8e, sz %.8e.\n", iface, type, sx, sy, sz);
1184 
1185     return d3drm_frame3_AddScale(&frame->IDirect3DRMFrame3_iface, type, sx, sy, sz);
1186 }
1187 
1188 static HRESULT WINAPI d3drm_frame3_AddRotation(IDirect3DRMFrame3 *iface,
1189         D3DRMCOMBINETYPE type, D3DVALUE x, D3DVALUE y, D3DVALUE z, D3DVALUE theta)
1190 {
1191     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
1192     struct d3drm_matrix m;
1193     D3DVECTOR axis;
1194 
1195     TRACE("iface %p, type %#x, x %.8e, y %.8e, z %.8e, theta %.8e.\n", iface, type, x, y, z, theta);
1196 
1197     axis.u1.x = x;
1198     axis.u2.y = y;
1199     axis.u3.z = z;
1200 
1201     switch (type)
1202     {
1203         case D3DRMCOMBINE_REPLACE:
1204             d3drm_matrix_set_rotation(&frame->transform, &axis, theta);
1205             break;
1206 
1207         case D3DRMCOMBINE_BEFORE:
1208             d3drm_matrix_set_rotation(&m, &axis, theta);
1209             d3drm_matrix_multiply_affine(&frame->transform, &m, &frame->transform);
1210             break;
1211 
1212         case D3DRMCOMBINE_AFTER:
1213             d3drm_matrix_set_rotation(&m, &axis, theta);
1214             d3drm_matrix_multiply_affine(&frame->transform, &frame->transform, &m);
1215             break;
1216 
1217         default:
1218             FIXME("Unhandled type %#x.\n", type);
1219             return D3DRMERR_BADVALUE;
1220     }
1221 
1222     return D3DRM_OK;
1223 }
1224 
1225 static HRESULT WINAPI d3drm_frame2_AddRotation(IDirect3DRMFrame2 *iface,
1226         D3DRMCOMBINETYPE type, D3DVALUE x, D3DVALUE y, D3DVALUE z, D3DVALUE theta)
1227 {
1228     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
1229 
1230     TRACE("iface %p, type %#x, x %.8e, y %.8e, z %.8e, theta %.8e.\n", iface, type, x, y, z, theta);
1231 
1232     return d3drm_frame3_AddRotation(&frame->IDirect3DRMFrame3_iface, type, x, y, z, theta);
1233 }
1234 
1235 static HRESULT WINAPI d3drm_frame1_AddRotation(IDirect3DRMFrame *iface,
1236         D3DRMCOMBINETYPE type, D3DVALUE x, D3DVALUE y, D3DVALUE z, D3DVALUE theta)
1237 {
1238     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
1239 
1240     TRACE("iface %p, type %#x, x %.8e, y %.8e, z %.8e, theta %.8e.\n", iface, type, x, y, z, theta);
1241 
1242     return d3drm_frame3_AddRotation(&frame->IDirect3DRMFrame3_iface, type, x, y, z, theta);
1243 }
1244 
1245 static HRESULT WINAPI d3drm_frame3_AddVisual(IDirect3DRMFrame3 *iface, IUnknown *visual)
1246 {
1247     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
1248     ULONG i;
1249 
1250     TRACE("iface %p, visual %p.\n", iface, visual);
1251 
1252     if (!visual)
1253         return D3DRMERR_BADOBJECT;
1254 
1255     /* Check if already existing and return gracefully without increasing ref count */
1256     for (i = 0; i < frame->nb_visuals; i++)
1257         if (frame->visuals[i] == (IDirect3DRMVisual *)visual)
1258             return D3DRM_OK;
1259 
1260     if (!d3drm_array_reserve((void **)&frame->visuals, &frame->visuals_size,
1261             frame->nb_visuals + 1, sizeof(*frame->visuals)))
1262         return E_OUTOFMEMORY;
1263 
1264     frame->visuals[frame->nb_visuals++] = (IDirect3DRMVisual *)visual;
1265     IDirect3DRMVisual_AddRef(visual);
1266 
1267     return D3DRM_OK;
1268 }
1269 
1270 static HRESULT WINAPI d3drm_frame2_AddVisual(IDirect3DRMFrame2 *iface, IDirect3DRMVisual *visual)
1271 {
1272     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
1273 
1274     TRACE("iface %p, visual %p.\n", iface, visual);
1275 
1276     return d3drm_frame3_AddVisual(&frame->IDirect3DRMFrame3_iface, (IUnknown *)visual);
1277 }
1278 
1279 static HRESULT WINAPI d3drm_frame1_AddVisual(IDirect3DRMFrame *iface, IDirect3DRMVisual *visual)
1280 {
1281     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
1282 
1283     TRACE("iface %p, visual %p.\n", iface, visual);
1284 
1285     return d3drm_frame3_AddVisual(&frame->IDirect3DRMFrame3_iface, (IUnknown *)visual);
1286 }
1287 
1288 static HRESULT WINAPI d3drm_frame3_GetChildren(IDirect3DRMFrame3 *iface, IDirect3DRMFrameArray **children)
1289 {
1290     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
1291     struct d3drm_frame_array *array;
1292 
1293     TRACE("iface %p, children %p.\n", iface, children);
1294 
1295     if (!children)
1296         return D3DRMERR_BADVALUE;
1297 
1298     if (!(array = d3drm_frame_array_create(frame->nb_children, frame->children)))
1299         return E_OUTOFMEMORY;
1300 
1301     *children = &array->IDirect3DRMFrameArray_iface;
1302 
1303     return D3DRM_OK;
1304 }
1305 
1306 static HRESULT WINAPI d3drm_frame2_GetChildren(IDirect3DRMFrame2 *iface, IDirect3DRMFrameArray **children)
1307 {
1308     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
1309 
1310     TRACE("iface %p, children %p.\n", iface, children);
1311 
1312     return d3drm_frame3_GetChildren(&frame->IDirect3DRMFrame3_iface, children);
1313 }
1314 
1315 static HRESULT WINAPI d3drm_frame1_GetChildren(IDirect3DRMFrame *iface, IDirect3DRMFrameArray **children)
1316 {
1317     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
1318 
1319     TRACE("iface %p, children %p.\n", iface, children);
1320 
1321     return d3drm_frame3_GetChildren(&frame->IDirect3DRMFrame3_iface, children);
1322 }
1323 
1324 static D3DCOLOR WINAPI d3drm_frame3_GetColor(IDirect3DRMFrame3 *iface)
1325 {
1326     FIXME("iface %p stub!\n", iface);
1327 
1328     return 0;
1329 }
1330 
1331 static D3DCOLOR WINAPI d3drm_frame2_GetColor(IDirect3DRMFrame2 *iface)
1332 {
1333     FIXME("iface %p stub!\n", iface);
1334 
1335     return 0;
1336 }
1337 
1338 static D3DCOLOR WINAPI d3drm_frame1_GetColor(IDirect3DRMFrame *iface)
1339 {
1340     FIXME("iface %p stub!\n", iface);
1341 
1342     return 0;
1343 }
1344 
1345 static HRESULT WINAPI d3drm_frame3_GetLights(IDirect3DRMFrame3 *iface, IDirect3DRMLightArray **lights)
1346 {
1347     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
1348     struct d3drm_light_array *array;
1349 
1350     TRACE("iface %p, lights %p.\n", iface, lights);
1351 
1352     if (!lights)
1353         return D3DRMERR_BADVALUE;
1354 
1355     if (!(array = d3drm_light_array_create(frame->nb_lights, frame->lights)))
1356         return E_OUTOFMEMORY;
1357 
1358     *lights = &array->IDirect3DRMLightArray_iface;
1359 
1360     return D3DRM_OK;
1361 }
1362 
1363 static HRESULT WINAPI d3drm_frame2_GetLights(IDirect3DRMFrame2 *iface, IDirect3DRMLightArray **lights)
1364 {
1365     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
1366 
1367     TRACE("iface %p, lights %p.\n", iface, lights);
1368 
1369     return d3drm_frame3_GetLights(&frame->IDirect3DRMFrame3_iface, lights);
1370 }
1371 
1372 static HRESULT WINAPI d3drm_frame1_GetLights(IDirect3DRMFrame *iface, IDirect3DRMLightArray **lights)
1373 {
1374     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
1375 
1376     TRACE("iface %p, lights %p.\n", iface, lights);
1377 
1378     return d3drm_frame3_GetLights(&frame->IDirect3DRMFrame3_iface, lights);
1379 }
1380 
1381 static D3DRMMATERIALMODE WINAPI d3drm_frame3_GetMaterialMode(IDirect3DRMFrame3 *iface)
1382 {
1383     FIXME("iface %p stub!\n", iface);
1384 
1385     return D3DRMMATERIAL_FROMPARENT;
1386 }
1387 
1388 static D3DRMMATERIALMODE WINAPI d3drm_frame2_GetMaterialMode(IDirect3DRMFrame2 *iface)
1389 {
1390     FIXME("iface %p stub!\n", iface);
1391 
1392     return D3DRMMATERIAL_FROMPARENT;
1393 }
1394 
1395 static D3DRMMATERIALMODE WINAPI d3drm_frame1_GetMaterialMode(IDirect3DRMFrame *iface)
1396 {
1397     FIXME("iface %p stub!\n", iface);
1398 
1399     return D3DRMMATERIAL_FROMPARENT;
1400 }
1401 
1402 static HRESULT WINAPI d3drm_frame3_GetParent(IDirect3DRMFrame3 *iface, IDirect3DRMFrame3 **parent)
1403 {
1404     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
1405 
1406     TRACE("iface %p, parent %p.\n", iface, parent);
1407 
1408     if (!parent)
1409         return D3DRMERR_BADVALUE;
1410 
1411     if (frame->parent)
1412     {
1413         *parent = &frame->parent->IDirect3DRMFrame3_iface;
1414         IDirect3DRMFrame_AddRef(*parent);
1415     }
1416     else
1417     {
1418         *parent = NULL;
1419     }
1420 
1421     return D3DRM_OK;
1422 }
1423 
1424 static HRESULT WINAPI d3drm_frame2_GetParent(IDirect3DRMFrame2 *iface, IDirect3DRMFrame **parent)
1425 {
1426     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
1427 
1428     TRACE("iface %p, parent %p.\n", iface, parent);
1429 
1430     if (!parent)
1431         return D3DRMERR_BADVALUE;
1432 
1433     if (frame->parent)
1434     {
1435         *parent = &frame->parent->IDirect3DRMFrame_iface;
1436         IDirect3DRMFrame_AddRef(*parent);
1437     }
1438     else
1439     {
1440         *parent = NULL;
1441     }
1442 
1443     return D3DRM_OK;
1444 }
1445 
1446 static HRESULT WINAPI d3drm_frame1_GetParent(IDirect3DRMFrame *iface, IDirect3DRMFrame **parent)
1447 {
1448     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
1449 
1450     TRACE("iface %p, parent %p.\n", iface, parent);
1451 
1452     return d3drm_frame2_GetParent(&frame->IDirect3DRMFrame2_iface, parent);
1453 }
1454 
1455 static HRESULT WINAPI d3drm_frame3_GetPosition(IDirect3DRMFrame3 *iface,
1456         IDirect3DRMFrame3 *reference, D3DVECTOR *position)
1457 {
1458     FIXME("iface %p, reference %p, position %p stub!\n", iface, reference, position);
1459 
1460     return E_NOTIMPL;
1461 }
1462 
1463 static HRESULT WINAPI d3drm_frame2_GetPosition(IDirect3DRMFrame2 *iface,
1464         IDirect3DRMFrame *reference, D3DVECTOR *position)
1465 {
1466     FIXME("iface %p, reference %p, position %p stub!\n", iface, reference, position);
1467 
1468     return E_NOTIMPL;
1469 }
1470 
1471 static HRESULT WINAPI d3drm_frame1_GetPosition(IDirect3DRMFrame *iface,
1472         IDirect3DRMFrame *reference, D3DVECTOR *position)
1473 {
1474     FIXME("iface %p, reference %p, position %p stub!\n", iface, reference, position);
1475 
1476     return E_NOTIMPL;
1477 }
1478 
1479 
1480 static HRESULT WINAPI d3drm_frame3_GetRotation(IDirect3DRMFrame3 *iface,
1481         IDirect3DRMFrame3 *reference, D3DVECTOR *axis, D3DVALUE *theta)
1482 {
1483     FIXME("iface %p, reference %p, axis %p, theta %p stub!\n", iface, reference, axis, theta);
1484 
1485     return E_NOTIMPL;
1486 }
1487 
1488 static HRESULT WINAPI d3drm_frame2_GetRotation(IDirect3DRMFrame2 *iface,
1489         IDirect3DRMFrame *reference, D3DVECTOR *axis, D3DVALUE *theta)
1490 {
1491     FIXME("iface %p, reference %p, axis %p, theta %p stub!\n", iface, reference, axis, theta);
1492 
1493     return E_NOTIMPL;
1494 }
1495 
1496 static HRESULT WINAPI d3drm_frame1_GetRotation(IDirect3DRMFrame *iface,
1497         IDirect3DRMFrame *reference, D3DVECTOR *axis, D3DVALUE *theta)
1498 {
1499     FIXME("iface %p, reference %p, axis %p, theta %p stub!\n", iface, reference, axis, theta);
1500 
1501     return E_NOTIMPL;
1502 }
1503 
1504 static HRESULT WINAPI d3drm_frame3_GetScene(IDirect3DRMFrame3 *iface, IDirect3DRMFrame3 **scene)
1505 {
1506     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
1507 
1508     TRACE("iface %p, scene %p.\n", iface, scene);
1509 
1510     if (!scene)
1511         return D3DRMERR_BADVALUE;
1512 
1513     while (frame->parent)
1514         frame = frame->parent;
1515 
1516     *scene = &frame->IDirect3DRMFrame3_iface;
1517     IDirect3DRMFrame3_AddRef(*scene);
1518 
1519     return D3DRM_OK;
1520 }
1521 
1522 static HRESULT WINAPI d3drm_frame2_GetScene(IDirect3DRMFrame2 *iface, IDirect3DRMFrame **scene)
1523 {
1524     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
1525     IDirect3DRMFrame3 *frame3;
1526     HRESULT hr;
1527 
1528     TRACE("iface %p, scene %p.\n", iface, scene);
1529 
1530     if (!scene)
1531         return D3DRMERR_BADVALUE;
1532 
1533     hr = IDirect3DRMFrame3_GetScene(&frame->IDirect3DRMFrame3_iface, &frame3);
1534     if (FAILED(hr) || !frame3)
1535     {
1536         *scene = NULL;
1537         return hr;
1538     }
1539 
1540     hr = IDirect3DRMFrame3_QueryInterface(frame3, &IID_IDirect3DRMFrame, (void **)scene);
1541     IDirect3DRMFrame3_Release(frame3);
1542 
1543     return hr;
1544 }
1545 
1546 static HRESULT WINAPI d3drm_frame1_GetScene(IDirect3DRMFrame *iface, IDirect3DRMFrame **scene)
1547 {
1548     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
1549 
1550     TRACE("iface %p, scene %p.\n", iface, scene);
1551 
1552     return d3drm_frame2_GetScene(&frame->IDirect3DRMFrame2_iface, scene);
1553 }
1554 
1555 static D3DRMSORTMODE WINAPI d3drm_frame3_GetSortMode(IDirect3DRMFrame3 *iface)
1556 {
1557     FIXME("iface %p stub!\n", iface);
1558 
1559     return D3DRMSORT_FROMPARENT;
1560 }
1561 
1562 static D3DRMSORTMODE WINAPI d3drm_frame2_GetSortMode(IDirect3DRMFrame2 *iface)
1563 {
1564     FIXME("iface %p stub!\n", iface);
1565 
1566     return D3DRMSORT_FROMPARENT;
1567 }
1568 
1569 static D3DRMSORTMODE WINAPI d3drm_frame1_GetSortMode(IDirect3DRMFrame *iface)
1570 {
1571     FIXME("iface %p stub!\n", iface);
1572 
1573     return D3DRMSORT_FROMPARENT;
1574 }
1575 
1576 static HRESULT WINAPI d3drm_frame3_GetTexture(IDirect3DRMFrame3 *iface, IDirect3DRMTexture3 **texture)
1577 {
1578     FIXME("iface %p, texture %p stub!\n", iface, texture);
1579 
1580     return E_NOTIMPL;
1581 }
1582 
1583 static HRESULT WINAPI d3drm_frame2_GetTexture(IDirect3DRMFrame2 *iface, IDirect3DRMTexture **texture)
1584 {
1585     FIXME("iface %p, texture %p stub!\n", iface, texture);
1586 
1587     return E_NOTIMPL;
1588 }
1589 
1590 static HRESULT WINAPI d3drm_frame1_GetTexture(IDirect3DRMFrame *iface, IDirect3DRMTexture **texture)
1591 {
1592     FIXME("iface %p, texture %p stub!\n", iface, texture);
1593 
1594     return E_NOTIMPL;
1595 }
1596 
1597 static HRESULT WINAPI d3drm_frame3_GetTransform(IDirect3DRMFrame3 *iface,
1598         IDirect3DRMFrame3 *reference, D3DRMMATRIX4D matrix)
1599 {
1600     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
1601     struct d3drm_matrix *m = d3drm_matrix(matrix);
1602 
1603     TRACE("iface %p, reference %p, matrix %p.\n", iface, reference, matrix);
1604 
1605     if (reference)
1606         FIXME("Ignoring reference frame %p.\n", reference);
1607 
1608     *m = frame->transform;
1609 
1610     return D3DRM_OK;
1611 }
1612 
1613 static HRESULT WINAPI d3drm_frame2_GetTransform(IDirect3DRMFrame2 *iface, D3DRMMATRIX4D matrix)
1614 {
1615     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
1616     struct d3drm_matrix *m = d3drm_matrix(matrix);
1617 
1618     TRACE("iface %p, matrix %p.\n", iface, matrix);
1619 
1620     *m = frame->transform;
1621 
1622     return D3DRM_OK;
1623 }
1624 
1625 static HRESULT WINAPI d3drm_frame1_GetTransform(IDirect3DRMFrame *iface, D3DRMMATRIX4D matrix)
1626 {
1627     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
1628 
1629     TRACE("iface %p, matrix %p.\n", iface, matrix);
1630 
1631     return d3drm_frame2_GetTransform(&frame->IDirect3DRMFrame2_iface, matrix);
1632 }
1633 
1634 static HRESULT WINAPI d3drm_frame3_GetVelocity(IDirect3DRMFrame3 *iface,
1635         IDirect3DRMFrame3 *reference, D3DVECTOR *velocity, BOOL with_rotation)
1636 {
1637     FIXME("iface %p, reference %p, velocity %p, with_rotation %#x stub!\n",
1638             iface, reference, velocity, with_rotation);
1639 
1640     return E_NOTIMPL;
1641 }
1642 
1643 static HRESULT WINAPI d3drm_frame2_GetVelocity(IDirect3DRMFrame2 *iface,
1644         IDirect3DRMFrame *reference, D3DVECTOR *velocity, BOOL with_rotation)
1645 {
1646     FIXME("iface %p, reference %p, velocity %p, with_rotation %#x stub!\n",
1647             iface, reference, velocity, with_rotation);
1648 
1649     return E_NOTIMPL;
1650 }
1651 
1652 static HRESULT WINAPI d3drm_frame1_GetVelocity(IDirect3DRMFrame *iface,
1653         IDirect3DRMFrame *reference, D3DVECTOR *velocity, BOOL with_rotation)
1654 {
1655     FIXME("iface %p, reference %p, velocity %p, with_rotation %#x stub!\n",
1656             iface, reference, velocity, with_rotation);
1657 
1658     return E_NOTIMPL;
1659 }
1660 
1661 static HRESULT WINAPI d3drm_frame3_GetOrientation(IDirect3DRMFrame3 *iface,
1662         IDirect3DRMFrame3 *reference, D3DVECTOR *dir, D3DVECTOR *up)
1663 {
1664     FIXME("iface %p, reference %p, dir %p, up %p stub!\n", iface, reference, dir, up);
1665 
1666     return E_NOTIMPL;
1667 }
1668 
1669 static HRESULT WINAPI d3drm_frame2_GetOrientation(IDirect3DRMFrame2 *iface,
1670         IDirect3DRMFrame *reference, D3DVECTOR *dir, D3DVECTOR *up)
1671 {
1672     FIXME("iface %p, reference %p, dir %p, up %p stub!\n", iface, reference, dir, up);
1673 
1674     return E_NOTIMPL;
1675 }
1676 
1677 static HRESULT WINAPI d3drm_frame1_GetOrientation(IDirect3DRMFrame *iface,
1678         IDirect3DRMFrame *reference, D3DVECTOR *dir, D3DVECTOR *up)
1679 {
1680     FIXME("iface %p, reference %p, dir %p, up %p stub!\n", iface, reference, dir, up);
1681 
1682     return E_NOTIMPL;
1683 }
1684 
1685 static HRESULT WINAPI d3drm_frame3_GetVisuals(IDirect3DRMFrame3 *iface, DWORD *count, IUnknown **visuals)
1686 {
1687     FIXME("iface %p, count %p, visuals %p stub!\n", iface, count, visuals);
1688 
1689     return E_NOTIMPL;
1690 }
1691 
1692 static HRESULT WINAPI d3drm_frame2_GetVisuals(IDirect3DRMFrame2 *iface, IDirect3DRMVisualArray **visuals)
1693 {
1694     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
1695     struct d3drm_visual_array *array;
1696 
1697     TRACE("iface %p, visuals %p.\n", iface, visuals);
1698 
1699     if (!visuals)
1700         return D3DRMERR_BADVALUE;
1701 
1702     if (!(array = d3drm_visual_array_create(frame->nb_visuals, frame->visuals)))
1703         return E_OUTOFMEMORY;
1704 
1705     *visuals = &array->IDirect3DRMVisualArray_iface;
1706 
1707     return D3DRM_OK;
1708 }
1709 
1710 static HRESULT WINAPI d3drm_frame1_GetVisuals(IDirect3DRMFrame *iface, IDirect3DRMVisualArray **visuals)
1711 {
1712     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
1713 
1714     TRACE("iface %p, visuals %p.\n", iface, visuals);
1715 
1716     return d3drm_frame2_GetVisuals(&frame->IDirect3DRMFrame2_iface, visuals);
1717 }
1718 
1719 static HRESULT WINAPI d3drm_frame2_GetTextureTopology(IDirect3DRMFrame2 *iface, BOOL *wrap_u, BOOL *wrap_v)
1720 {
1721     FIXME("iface %p, wrap_u %p, wrap_v %p stub!\n", iface, wrap_u, wrap_v);
1722 
1723     return E_NOTIMPL;
1724 }
1725 
1726 static HRESULT WINAPI d3drm_frame1_GetTextureTopology(IDirect3DRMFrame *iface, BOOL *wrap_u, BOOL *wrap_v)
1727 {
1728     FIXME("iface %p, wrap_u %p, wrap_v %p stub!\n", iface, wrap_u, wrap_v);
1729 
1730     return E_NOTIMPL;
1731 }
1732 
1733 static HRESULT WINAPI d3drm_frame3_InverseTransform(IDirect3DRMFrame3 *iface, D3DVECTOR *d, D3DVECTOR *s)
1734 {
1735     FIXME("iface %p, d %p, s %p stub!\n", iface, d, s);
1736 
1737     return E_NOTIMPL;
1738 }
1739 
1740 static HRESULT WINAPI d3drm_frame2_InverseTransform(IDirect3DRMFrame2 *iface, D3DVECTOR *d, D3DVECTOR *s)
1741 {
1742     FIXME("iface %p, d %p, s %p stub!\n", iface, d, s);
1743 
1744     return E_NOTIMPL;
1745 }
1746 
1747 static HRESULT WINAPI d3drm_frame1_InverseTransform(IDirect3DRMFrame *iface, D3DVECTOR *d, D3DVECTOR *s)
1748 {
1749     FIXME("iface %p, d %p, s %p stub!\n", iface, d, s);
1750 
1751     return E_NOTIMPL;
1752 }
1753 
1754 static HRESULT WINAPI d3drm_frame3_Load(IDirect3DRMFrame3 *iface, void *filename,
1755         void *name, D3DRMLOADOPTIONS flags, D3DRMLOADTEXTURE3CALLBACK cb, void *ctx)
1756 {
1757     FIXME("iface %p, filename %p, name %p, flags %#x, cb %p, ctx %p stub!\n",
1758             iface, filename, name, flags, cb, ctx);
1759 
1760     return E_NOTIMPL;
1761 }
1762 
1763 static HRESULT WINAPI d3drm_frame2_Load(IDirect3DRMFrame2 *iface, void *filename,
1764         void *name, D3DRMLOADOPTIONS flags, D3DRMLOADTEXTURECALLBACK cb, void *ctx)
1765 {
1766     FIXME("iface %p, filename %p, name %p, flags %#x, cb %p, ctx %p stub!\n",
1767             iface, filename, name, flags, cb, ctx);
1768 
1769     return E_NOTIMPL;
1770 }
1771 
1772 static HRESULT WINAPI d3drm_frame1_Load(IDirect3DRMFrame *iface, void *filename,
1773         void *name, D3DRMLOADOPTIONS flags, D3DRMLOADTEXTURECALLBACK cb, void *ctx)
1774 {
1775     FIXME("iface %p, filename %p, name %p, flags %#x, cb %p, ctx %p stub!\n",
1776             iface, filename, name, flags, cb, ctx);
1777 
1778     return E_NOTIMPL;
1779 }
1780 
1781 static HRESULT WINAPI d3drm_frame3_LookAt(IDirect3DRMFrame3 *iface, IDirect3DRMFrame3 *target,
1782         IDirect3DRMFrame3 *reference, D3DRMFRAMECONSTRAINT constraint)
1783 {
1784     FIXME("iface %p, target %p, reference %p, constraint %#x stub!\n", iface, target, reference, constraint);
1785 
1786     return E_NOTIMPL;
1787 }
1788 
1789 static HRESULT WINAPI d3drm_frame2_LookAt(IDirect3DRMFrame2 *iface, IDirect3DRMFrame *target,
1790         IDirect3DRMFrame *reference, D3DRMFRAMECONSTRAINT constraint)
1791 {
1792     FIXME("iface %p, target %p, reference %p, constraint %#x stub!\n", iface, target, reference, constraint);
1793 
1794     return E_NOTIMPL;
1795 }
1796 
1797 static HRESULT WINAPI d3drm_frame1_LookAt(IDirect3DRMFrame *iface, IDirect3DRMFrame *target,
1798         IDirect3DRMFrame *reference, D3DRMFRAMECONSTRAINT constraint)
1799 {
1800     FIXME("iface %p, target %p, reference %p, constraint %#x stub!\n", iface, target, reference, constraint);
1801 
1802     return E_NOTIMPL;
1803 }
1804 
1805 static HRESULT WINAPI d3drm_frame3_Move(IDirect3DRMFrame3 *iface, D3DVALUE delta)
1806 {
1807     FIXME("iface %p, delta %.8e stub!\n", iface, delta);
1808 
1809     return E_NOTIMPL;
1810 }
1811 
1812 static HRESULT WINAPI d3drm_frame2_Move(IDirect3DRMFrame2 *iface, D3DVALUE delta)
1813 {
1814     FIXME("iface %p, delta %.8e stub!\n", iface, delta);
1815 
1816     return E_NOTIMPL;
1817 }
1818 
1819 static HRESULT WINAPI d3drm_frame1_Move(IDirect3DRMFrame *iface, D3DVALUE delta)
1820 {
1821     FIXME("iface %p, delta %.8e stub!\n", iface, delta);
1822 
1823     return E_NOTIMPL;
1824 }
1825 
1826 static HRESULT WINAPI d3drm_frame3_DeleteChild(IDirect3DRMFrame3 *iface, IDirect3DRMFrame3 *child)
1827 {
1828     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
1829     struct d3drm_frame *child_impl = unsafe_impl_from_IDirect3DRMFrame3(child);
1830     ULONG i;
1831 
1832     TRACE("iface %p, child %p.\n", iface, child);
1833 
1834     if (!child_impl)
1835         return D3DRMERR_BADOBJECT;
1836 
1837     /* Check if child exists */
1838     for (i = 0; i < frame->nb_children; ++i)
1839     {
1840         if (frame->children[i] == child)
1841             break;
1842     }
1843 
1844     if (i == frame->nb_children)
1845         return D3DRMERR_BADVALUE;
1846 
1847     memmove(frame->children + i, frame->children + i + 1, sizeof(*frame->children) * (frame->nb_children - 1 - i));
1848     IDirect3DRMFrame3_Release(child);
1849     child_impl->parent = NULL;
1850     --frame->nb_children;
1851 
1852     return D3DRM_OK;
1853 }
1854 
1855 static HRESULT WINAPI d3drm_frame2_DeleteChild(IDirect3DRMFrame2 *iface, IDirect3DRMFrame *child)
1856 {
1857     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
1858     IDirect3DRMFrame3 *child3;
1859     HRESULT hr;
1860 
1861     TRACE("iface %p, child %p.\n", iface, child);
1862 
1863     if (!child)
1864         return D3DRMERR_BADOBJECT;
1865     if (FAILED(hr = IDirect3DRMFrame_QueryInterface(child, &IID_IDirect3DRMFrame3, (void **)&child3)))
1866         return D3DRMERR_BADOBJECT;
1867     IDirect3DRMFrame_Release(child);
1868 
1869     return d3drm_frame3_DeleteChild(&frame->IDirect3DRMFrame3_iface, child3);
1870 }
1871 
1872 static HRESULT WINAPI d3drm_frame1_DeleteChild(IDirect3DRMFrame *iface, IDirect3DRMFrame *child)
1873 {
1874     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
1875     struct d3drm_frame *child_frame = unsafe_impl_from_IDirect3DRMFrame(child);
1876 
1877     TRACE("iface %p, child %p.\n", iface, child);
1878 
1879     if (!child_frame)
1880         return D3DRMERR_BADOBJECT;
1881 
1882     return d3drm_frame3_DeleteChild(&frame->IDirect3DRMFrame3_iface, &child_frame->IDirect3DRMFrame3_iface);
1883 }
1884 
1885 static HRESULT WINAPI d3drm_frame3_DeleteLight(IDirect3DRMFrame3 *iface, IDirect3DRMLight *light)
1886 {
1887     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
1888     ULONG i;
1889 
1890     TRACE("iface %p, light %p.\n", iface, light);
1891 
1892     if (!light)
1893         return D3DRMERR_BADOBJECT;
1894 
1895     /* Check if visual exists */
1896     for (i = 0; i < frame->nb_lights; ++i)
1897     {
1898         if (frame->lights[i] == light)
1899             break;
1900     }
1901 
1902     if (i == frame->nb_lights)
1903         return D3DRMERR_BADVALUE;
1904 
1905     memmove(frame->lights + i, frame->lights + i + 1, sizeof(*frame->lights) * (frame->nb_lights - 1 - i));
1906     IDirect3DRMLight_Release(light);
1907     --frame->nb_lights;
1908 
1909     return D3DRM_OK;
1910 }
1911 
1912 static HRESULT WINAPI d3drm_frame2_DeleteLight(IDirect3DRMFrame2 *iface, IDirect3DRMLight *light)
1913 {
1914     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
1915 
1916     TRACE("iface %p, light %p.\n", iface, light);
1917 
1918     return d3drm_frame3_DeleteLight(&frame->IDirect3DRMFrame3_iface, light);
1919 }
1920 
1921 static HRESULT WINAPI d3drm_frame1_DeleteLight(IDirect3DRMFrame *iface, IDirect3DRMLight *light)
1922 {
1923     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
1924 
1925     TRACE("iface %p, light %p.\n", iface, light);
1926 
1927     return d3drm_frame3_DeleteLight(&frame->IDirect3DRMFrame3_iface, light);
1928 }
1929 
1930 static HRESULT WINAPI d3drm_frame3_DeleteMoveCallback(IDirect3DRMFrame3 *iface,
1931         D3DRMFRAME3MOVECALLBACK cb, void *ctx)
1932 {
1933     FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
1934 
1935     return E_NOTIMPL;
1936 }
1937 
1938 static HRESULT WINAPI d3drm_frame2_DeleteMoveCallback(IDirect3DRMFrame2 *iface,
1939         D3DRMFRAMEMOVECALLBACK cb, void *ctx)
1940 {
1941     FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
1942 
1943     return E_NOTIMPL;
1944 }
1945 
1946 static HRESULT WINAPI d3drm_frame1_DeleteMoveCallback(IDirect3DRMFrame *iface,
1947         D3DRMFRAMEMOVECALLBACK cb, void *ctx)
1948 {
1949     FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
1950 
1951     return E_NOTIMPL;
1952 }
1953 
1954 static HRESULT WINAPI d3drm_frame3_DeleteVisual(IDirect3DRMFrame3 *iface, IUnknown *visual)
1955 {
1956     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
1957     ULONG i;
1958 
1959     TRACE("iface %p, visual %p.\n", iface, visual);
1960 
1961     if (!visual)
1962         return D3DRMERR_BADOBJECT;
1963 
1964     /* Check if visual exists */
1965     for (i = 0; i < frame->nb_visuals; ++i)
1966     {
1967         if (frame->visuals[i] == (IDirect3DRMVisual *)visual)
1968             break;
1969     }
1970 
1971     if (i == frame->nb_visuals)
1972         return D3DRMERR_BADVALUE;
1973 
1974     memmove(frame->visuals + i, frame->visuals + i + 1, sizeof(*frame->visuals) * (frame->nb_visuals - 1 - i));
1975     IDirect3DRMVisual_Release(visual);
1976     --frame->nb_visuals;
1977 
1978     return D3DRM_OK;
1979 }
1980 
1981 static HRESULT WINAPI d3drm_frame2_DeleteVisual(IDirect3DRMFrame2 *iface, IDirect3DRMVisual *visual)
1982 {
1983     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
1984 
1985     TRACE("iface %p, visual %p.\n", iface, visual);
1986 
1987     return d3drm_frame3_DeleteVisual(&frame->IDirect3DRMFrame3_iface, (IUnknown *)visual);
1988 }
1989 
1990 static HRESULT WINAPI d3drm_frame1_DeleteVisual(IDirect3DRMFrame *iface, IDirect3DRMVisual *visual)
1991 {
1992     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
1993 
1994     TRACE("iface %p, visual %p.\n", iface, visual);
1995 
1996     return d3drm_frame3_DeleteVisual(&frame->IDirect3DRMFrame3_iface, (IUnknown *)visual);
1997 }
1998 
1999 static D3DCOLOR WINAPI d3drm_frame3_GetSceneBackground(IDirect3DRMFrame3 *iface)
2000 {
2001     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
2002 
2003     TRACE("iface %p.\n", iface);
2004 
2005     return frame->scenebackground;
2006 }
2007 
2008 static D3DCOLOR WINAPI d3drm_frame2_GetSceneBackground(IDirect3DRMFrame2 *iface)
2009 {
2010     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
2011 
2012     TRACE("iface %p.\n", iface);
2013 
2014     return d3drm_frame3_GetSceneBackground(&frame->IDirect3DRMFrame3_iface);
2015 }
2016 
2017 static D3DCOLOR WINAPI d3drm_frame1_GetSceneBackground(IDirect3DRMFrame *iface)
2018 {
2019     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
2020 
2021     TRACE("iface %p.\n", iface);
2022 
2023     return d3drm_frame3_GetSceneBackground(&frame->IDirect3DRMFrame3_iface);
2024 }
2025 
2026 static HRESULT WINAPI d3drm_frame3_GetSceneBackgroundDepth(IDirect3DRMFrame3 *iface,
2027         IDirectDrawSurface **surface)
2028 {
2029     FIXME("iface %p, surface %p stub!\n", iface, surface);
2030 
2031     return E_NOTIMPL;
2032 }
2033 
2034 static HRESULT WINAPI d3drm_frame2_GetSceneBackgroundDepth(IDirect3DRMFrame2 *iface,
2035         IDirectDrawSurface **surface)
2036 {
2037     FIXME("iface %p, surface %p stub!\n", iface, surface);
2038 
2039     return E_NOTIMPL;
2040 }
2041 
2042 static HRESULT WINAPI d3drm_frame1_GetSceneBackgroundDepth(IDirect3DRMFrame *iface,
2043         IDirectDrawSurface **surface)
2044 {
2045     FIXME("iface %p, surface %p stub!\n", iface, surface);
2046 
2047     return E_NOTIMPL;
2048 }
2049 
2050 static D3DCOLOR WINAPI d3drm_frame3_GetSceneFogColor(IDirect3DRMFrame3 *iface)
2051 {
2052     FIXME("iface %p stub!\n", iface);
2053 
2054     return 0;
2055 }
2056 
2057 static D3DCOLOR WINAPI d3drm_frame2_GetSceneFogColor(IDirect3DRMFrame2 *iface)
2058 {
2059     FIXME("iface %p stub!\n", iface);
2060 
2061     return 0;
2062 }
2063 
2064 static D3DCOLOR WINAPI d3drm_frame1_GetSceneFogColor(IDirect3DRMFrame *iface)
2065 {
2066     FIXME("iface %p stub!\n", iface);
2067 
2068     return 0;
2069 }
2070 
2071 static BOOL WINAPI d3drm_frame3_GetSceneFogEnable(IDirect3DRMFrame3 *iface)
2072 {
2073     FIXME("iface %p stub!\n", iface);
2074 
2075     return FALSE;
2076 }
2077 
2078 static BOOL WINAPI d3drm_frame2_GetSceneFogEnable(IDirect3DRMFrame2 *iface)
2079 {
2080     FIXME("iface %p stub!\n", iface);
2081 
2082     return FALSE;
2083 }
2084 
2085 static BOOL WINAPI d3drm_frame1_GetSceneFogEnable(IDirect3DRMFrame *iface)
2086 {
2087     FIXME("iface %p stub!\n", iface);
2088 
2089     return FALSE;
2090 }
2091 
2092 static D3DRMFOGMODE WINAPI d3drm_frame3_GetSceneFogMode(IDirect3DRMFrame3 *iface)
2093 {
2094     FIXME("iface %p stub!\n", iface);
2095 
2096     return D3DRMFOG_LINEAR;
2097 }
2098 
2099 static D3DRMFOGMODE WINAPI d3drm_frame2_GetSceneFogMode(IDirect3DRMFrame2 *iface)
2100 {
2101     FIXME("iface %p stub!\n", iface);
2102 
2103     return D3DRMFOG_LINEAR;
2104 }
2105 
2106 static D3DRMFOGMODE WINAPI d3drm_frame1_GetSceneFogMode(IDirect3DRMFrame *iface)
2107 {
2108     FIXME("iface %p stub!\n", iface);
2109 
2110     return D3DRMFOG_LINEAR;
2111 }
2112 
2113 static HRESULT WINAPI d3drm_frame3_GetSceneFogParams(IDirect3DRMFrame3 *iface,
2114         D3DVALUE *start, D3DVALUE *end, D3DVALUE *density)
2115 {
2116     FIXME("iface %p, start %p, end %p, density %p stub!\n", iface, start, end, density);
2117 
2118     return E_NOTIMPL;
2119 }
2120 
2121 static HRESULT WINAPI d3drm_frame2_GetSceneFogParams(IDirect3DRMFrame2 *iface,
2122         D3DVALUE *start, D3DVALUE *end, D3DVALUE *density)
2123 {
2124     FIXME("iface %p, start %p, end %p, density %p stub!\n", iface, start, end, density);
2125 
2126     return E_NOTIMPL;
2127 }
2128 
2129 static HRESULT WINAPI d3drm_frame1_GetSceneFogParams(IDirect3DRMFrame *iface,
2130         D3DVALUE *start, D3DVALUE *end, D3DVALUE *density)
2131 {
2132     FIXME("iface %p, start %p, end %p, density %p stub!\n", iface, start, end, density);
2133 
2134     return E_NOTIMPL;
2135 }
2136 
2137 static HRESULT WINAPI d3drm_frame3_SetSceneBackground(IDirect3DRMFrame3 *iface, D3DCOLOR color)
2138 {
2139     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
2140 
2141     TRACE("iface %p, color 0x%08x.\n", iface, color);
2142 
2143     frame->scenebackground = color;
2144 
2145     return D3DRM_OK;
2146 }
2147 
2148 static HRESULT WINAPI d3drm_frame2_SetSceneBackground(IDirect3DRMFrame2 *iface, D3DCOLOR color)
2149 {
2150     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
2151 
2152     TRACE("iface %p, color 0x%08x.\n", iface, color);
2153 
2154     return d3drm_frame3_SetSceneBackground(&frame->IDirect3DRMFrame3_iface, color);
2155 }
2156 
2157 static HRESULT WINAPI d3drm_frame1_SetSceneBackground(IDirect3DRMFrame *iface, D3DCOLOR color)
2158 {
2159     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
2160 
2161     TRACE("iface %p, color 0x%08x.\n", iface, color);
2162 
2163     return d3drm_frame3_SetSceneBackground(&frame->IDirect3DRMFrame3_iface, color);
2164 }
2165 
2166 static HRESULT WINAPI d3drm_frame3_SetSceneBackgroundRGB(IDirect3DRMFrame3 *iface,
2167         D3DVALUE red, D3DVALUE green, D3DVALUE blue)
2168 {
2169     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
2170 
2171     TRACE("iface %p, red %.8e, green %.8e, blue %.8e.\n", iface, red, green, blue);
2172 
2173     d3drm_set_color(&frame->scenebackground, red, green, blue, 1.0f);
2174 
2175     return D3DRM_OK;
2176 }
2177 
2178 static HRESULT WINAPI d3drm_frame2_SetSceneBackgroundRGB(IDirect3DRMFrame2 *iface,
2179         D3DVALUE red, D3DVALUE green, D3DVALUE blue)
2180 {
2181     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
2182 
2183     TRACE("iface %p, red %.8e, green %.8e, blue %.8e.\n", iface, red, green, blue);
2184 
2185     return d3drm_frame3_SetSceneBackgroundRGB(&frame->IDirect3DRMFrame3_iface, red, green, blue);
2186 }
2187 
2188 static HRESULT WINAPI d3drm_frame1_SetSceneBackgroundRGB(IDirect3DRMFrame *iface,
2189         D3DVALUE red, D3DVALUE green, D3DVALUE blue)
2190 {
2191     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
2192 
2193     TRACE("iface %p, red %.8e, green %.8e, blue %.8e.\n", iface, red, green, blue);
2194 
2195     return d3drm_frame3_SetSceneBackgroundRGB(&frame->IDirect3DRMFrame3_iface, red, green, blue);
2196 }
2197 
2198 static HRESULT WINAPI d3drm_frame3_SetSceneBackgroundDepth(IDirect3DRMFrame3 *iface,
2199         IDirectDrawSurface *surface)
2200 {
2201     FIXME("iface %p, surface %p stub!\n", iface, surface);
2202 
2203     return E_NOTIMPL;
2204 }
2205 
2206 static HRESULT WINAPI d3drm_frame2_SetSceneBackgroundDepth(IDirect3DRMFrame2 *iface,
2207         IDirectDrawSurface *surface)
2208 {
2209     FIXME("iface %p, surface %p stub!\n", iface, surface);
2210 
2211     return E_NOTIMPL;
2212 }
2213 
2214 static HRESULT WINAPI d3drm_frame1_SetSceneBackgroundDepth(IDirect3DRMFrame *iface,
2215         IDirectDrawSurface *surface)
2216 {
2217     FIXME("iface %p, surface %p stub!\n", iface, surface);
2218 
2219     return E_NOTIMPL;
2220 }
2221 
2222 static HRESULT WINAPI d3drm_frame3_SetSceneBackgroundImage(IDirect3DRMFrame3 *iface,
2223         IDirect3DRMTexture3 *texture)
2224 {
2225     FIXME("iface %p, texture %p stub!\n", iface, texture);
2226 
2227     return E_NOTIMPL;
2228 }
2229 
2230 static HRESULT WINAPI d3drm_frame2_SetSceneBackgroundImage(IDirect3DRMFrame2 *iface,
2231         IDirect3DRMTexture *texture)
2232 {
2233     FIXME("iface %p, texture %p stub!\n", iface, texture);
2234 
2235     return E_NOTIMPL;
2236 }
2237 
2238 static HRESULT WINAPI d3drm_frame1_SetSceneBackgroundImage(IDirect3DRMFrame *iface,
2239         IDirect3DRMTexture *texture)
2240 {
2241     FIXME("iface %p, texture %p stub!\n", iface, texture);
2242 
2243     return E_NOTIMPL;
2244 }
2245 
2246 static HRESULT WINAPI d3drm_frame3_SetSceneFogEnable(IDirect3DRMFrame3 *iface, BOOL enable)
2247 {
2248     FIXME("iface %p, enable %#x stub!\n", iface, enable);
2249 
2250     return E_NOTIMPL;
2251 }
2252 
2253 static HRESULT WINAPI d3drm_frame2_SetSceneFogEnable(IDirect3DRMFrame2 *iface, BOOL enable)
2254 {
2255     FIXME("iface %p, enable %#x stub!\n", iface, enable);
2256 
2257     return E_NOTIMPL;
2258 }
2259 
2260 static HRESULT WINAPI d3drm_frame1_SetSceneFogEnable(IDirect3DRMFrame *iface, BOOL enable)
2261 {
2262     FIXME("iface %p, enable %#x stub!\n", iface, enable);
2263 
2264     return E_NOTIMPL;
2265 }
2266 
2267 static HRESULT WINAPI d3drm_frame3_SetSceneFogColor(IDirect3DRMFrame3 *iface, D3DCOLOR color)
2268 {
2269     FIXME("iface %p, color 0x%08x stub!\n", iface, color);
2270 
2271     return E_NOTIMPL;
2272 }
2273 
2274 static HRESULT WINAPI d3drm_frame2_SetSceneFogColor(IDirect3DRMFrame2 *iface, D3DCOLOR color)
2275 {
2276     FIXME("iface %p, color 0x%08x stub!\n", iface, color);
2277 
2278     return E_NOTIMPL;
2279 }
2280 
2281 static HRESULT WINAPI d3drm_frame1_SetSceneFogColor(IDirect3DRMFrame *iface, D3DCOLOR color)
2282 {
2283     FIXME("iface %p, color 0x%08x stub!\n", iface, color);
2284 
2285     return E_NOTIMPL;
2286 }
2287 
2288 static HRESULT WINAPI d3drm_frame3_SetSceneFogMode(IDirect3DRMFrame3 *iface, D3DRMFOGMODE mode)
2289 {
2290     FIXME("iface %p, mode %#x stub!\n", iface, mode);
2291 
2292     return E_NOTIMPL;
2293 }
2294 
2295 static HRESULT WINAPI d3drm_frame2_SetSceneFogMode(IDirect3DRMFrame2 *iface, D3DRMFOGMODE mode)
2296 {
2297     FIXME("iface %p, mode %#x stub!\n", iface, mode);
2298 
2299     return E_NOTIMPL;
2300 }
2301 
2302 static HRESULT WINAPI d3drm_frame1_SetSceneFogMode(IDirect3DRMFrame *iface, D3DRMFOGMODE mode)
2303 {
2304     FIXME("iface %p, mode %#x stub!\n", iface, mode);
2305 
2306     return E_NOTIMPL;
2307 }
2308 
2309 static HRESULT WINAPI d3drm_frame3_SetSceneFogParams(IDirect3DRMFrame3 *iface,
2310         D3DVALUE start, D3DVALUE end, D3DVALUE density)
2311 {
2312     FIXME("iface %p, start %.8e, end %.8e, density %.8e stub!\n", iface, start, end, density);
2313 
2314     return E_NOTIMPL;
2315 }
2316 
2317 static HRESULT WINAPI d3drm_frame2_SetSceneFogParams(IDirect3DRMFrame2 *iface,
2318         D3DVALUE start, D3DVALUE end, D3DVALUE density)
2319 {
2320     FIXME("iface %p, start %.8e, end %.8e, density %.8e stub!\n", iface, start, end, density);
2321 
2322     return E_NOTIMPL;
2323 }
2324 
2325 static HRESULT WINAPI d3drm_frame1_SetSceneFogParams(IDirect3DRMFrame *iface,
2326         D3DVALUE start, D3DVALUE end, D3DVALUE density)
2327 {
2328     FIXME("iface %p, start %.8e, end %.8e, density %.8e stub!\n", iface, start, end, density);
2329 
2330     return E_NOTIMPL;
2331 }
2332 
2333 static HRESULT WINAPI d3drm_frame3_SetColor(IDirect3DRMFrame3 *iface, D3DCOLOR color)
2334 {
2335     FIXME("iface %p, color 0x%08x stub!\n", iface, color);
2336 
2337     return E_NOTIMPL;
2338 }
2339 
2340 static HRESULT WINAPI d3drm_frame2_SetColor(IDirect3DRMFrame2 *iface, D3DCOLOR color)
2341 {
2342     FIXME("iface %p, color 0x%08x stub!\n", iface, color);
2343 
2344     return E_NOTIMPL;
2345 }
2346 
2347 static HRESULT WINAPI d3drm_frame1_SetColor(IDirect3DRMFrame *iface, D3DCOLOR color)
2348 {
2349     FIXME("iface %p, color 0x%08x stub!\n", iface, color);
2350 
2351     return E_NOTIMPL;
2352 }
2353 
2354 static HRESULT WINAPI d3drm_frame3_SetColorRGB(IDirect3DRMFrame3 *iface,
2355         D3DVALUE red, D3DVALUE green, D3DVALUE blue)
2356 {
2357     FIXME("iface %p, red %.8e, green %.8e, blue %.8e stub!\n", iface, red, green, blue);
2358 
2359     return E_NOTIMPL;
2360 }
2361 
2362 static HRESULT WINAPI d3drm_frame2_SetColorRGB(IDirect3DRMFrame2 *iface,
2363         D3DVALUE red, D3DVALUE green, D3DVALUE blue)
2364 {
2365     FIXME("iface %p, red %.8e, green %.8e, blue %.8e stub!\n", iface, red, green, blue);
2366 
2367     return E_NOTIMPL;
2368 }
2369 
2370 static HRESULT WINAPI d3drm_frame1_SetColorRGB(IDirect3DRMFrame *iface,
2371         D3DVALUE red, D3DVALUE green, D3DVALUE blue)
2372 {
2373     FIXME("iface %p, red %.8e, green %.8e, blue %.8e stub!\n", iface, red, green, blue);
2374 
2375     return E_NOTIMPL;
2376 }
2377 
2378 static D3DRMZBUFFERMODE WINAPI d3drm_frame3_GetZbufferMode(IDirect3DRMFrame3 *iface)
2379 {
2380     FIXME("iface %p stub!\n", iface);
2381 
2382     return D3DRMZBUFFER_FROMPARENT;
2383 }
2384 
2385 static D3DRMZBUFFERMODE WINAPI d3drm_frame2_GetZbufferMode(IDirect3DRMFrame2 *iface)
2386 {
2387     FIXME("iface %p stub!\n", iface);
2388 
2389     return D3DRMZBUFFER_FROMPARENT;
2390 }
2391 
2392 static D3DRMZBUFFERMODE WINAPI d3drm_frame1_GetZbufferMode(IDirect3DRMFrame *iface)
2393 {
2394     FIXME("iface %p stub!\n", iface);
2395 
2396     return D3DRMZBUFFER_FROMPARENT;
2397 }
2398 
2399 static HRESULT WINAPI d3drm_frame3_SetMaterialMode(IDirect3DRMFrame3 *iface, D3DRMMATERIALMODE mode)
2400 {
2401     FIXME("iface %p, mode %#x stub!\n", iface, mode);
2402 
2403     return E_NOTIMPL;
2404 }
2405 
2406 static HRESULT WINAPI d3drm_frame2_SetMaterialMode(IDirect3DRMFrame2 *iface, D3DRMMATERIALMODE mode)
2407 {
2408     FIXME("iface %p, mode %#x stub!\n", iface, mode);
2409 
2410     return E_NOTIMPL;
2411 }
2412 
2413 static HRESULT WINAPI d3drm_frame1_SetMaterialMode(IDirect3DRMFrame *iface, D3DRMMATERIALMODE mode)
2414 {
2415     FIXME("iface %p, mode %#x stub!\n", iface, mode);
2416 
2417     return E_NOTIMPL;
2418 }
2419 
2420 static HRESULT WINAPI d3drm_frame3_SetOrientation(IDirect3DRMFrame3 *iface, IDirect3DRMFrame3 *reference,
2421         D3DVALUE dx, D3DVALUE dy, D3DVALUE dz, D3DVALUE ux, D3DVALUE uy, D3DVALUE uz)
2422 {
2423     FIXME("iface %p, reference %p, dx %.8e, dy %.8e, dz %.8e, ux %.8e, uy %.8e, uz %.8e stub!\n",
2424             iface, reference, dx, dy, dz, ux, uy, uz);
2425 
2426     return E_NOTIMPL;
2427 }
2428 
2429 static HRESULT WINAPI d3drm_frame2_SetOrientation(IDirect3DRMFrame2 *iface, IDirect3DRMFrame *reference,
2430         D3DVALUE dx, D3DVALUE dy, D3DVALUE dz, D3DVALUE ux, D3DVALUE uy, D3DVALUE uz)
2431 {
2432     FIXME("iface %p, reference %p, dx %.8e, dy %.8e, dz %.8e, ux %.8e, uy %.8e, uz %.8e stub!\n",
2433             iface, reference, dx, dy, dz, ux, uy, uz);
2434 
2435     return E_NOTIMPL;
2436 }
2437 
2438 static HRESULT WINAPI d3drm_frame1_SetOrientation(IDirect3DRMFrame *iface, IDirect3DRMFrame *reference,
2439         D3DVALUE dx, D3DVALUE dy, D3DVALUE dz, D3DVALUE ux, D3DVALUE uy, D3DVALUE uz)
2440 {
2441     FIXME("iface %p, reference %p, dx %.8e, dy %.8e, dz %.8e, ux %.8e, uy %.8e, uz %.8e stub!\n",
2442             iface, reference, dx, dy, dz, ux, uy, uz);
2443 
2444     return E_NOTIMPL;
2445 }
2446 
2447 static HRESULT WINAPI d3drm_frame3_SetPosition(IDirect3DRMFrame3 *iface,
2448         IDirect3DRMFrame3 *reference, D3DVALUE x, D3DVALUE y, D3DVALUE z)
2449 {
2450     FIXME("iface %p, reference %p, x %.8e, y %.8e, z %.8e stub!\n", iface, reference, x, y, z);
2451 
2452     return E_NOTIMPL;
2453 }
2454 
2455 static HRESULT WINAPI d3drm_frame2_SetPosition(IDirect3DRMFrame2 *iface,
2456         IDirect3DRMFrame *reference, D3DVALUE x, D3DVALUE y, D3DVALUE z)
2457 {
2458     FIXME("iface %p, reference %p, x %.8e, y %.8e, z %.8e stub!\n", iface, reference, x, y, z);
2459 
2460     return E_NOTIMPL;
2461 }
2462 
2463 static HRESULT WINAPI d3drm_frame1_SetPosition(IDirect3DRMFrame *iface,
2464         IDirect3DRMFrame *reference, D3DVALUE x, D3DVALUE y, D3DVALUE z)
2465 {
2466     FIXME("iface %p, reference %p, x %.8e, y %.8e, z %.8e stub!\n", iface, reference, x, y, z);
2467 
2468     return E_NOTIMPL;
2469 }
2470 
2471 static HRESULT WINAPI d3drm_frame3_SetRotation(IDirect3DRMFrame3 *iface,
2472         IDirect3DRMFrame3 *reference, D3DVALUE x, D3DVALUE y, D3DVALUE z, D3DVALUE theta)
2473 {
2474     FIXME("iface %p, reference %p, x %.8e, y %.8e, z %.8e, theta %.8e stub!\n",
2475             iface, reference, x, y, z, theta);
2476 
2477     return E_NOTIMPL;
2478 }
2479 
2480 static HRESULT WINAPI d3drm_frame2_SetRotation(IDirect3DRMFrame2 *iface,
2481         IDirect3DRMFrame *reference, D3DVALUE x, D3DVALUE y, D3DVALUE z, D3DVALUE theta)
2482 {
2483     FIXME("iface %p, reference %p, x %.8e, y %.8e, z %.8e, theta %.8e stub!\n",
2484             iface, reference, x, y, z, theta);
2485 
2486     return E_NOTIMPL;
2487 }
2488 
2489 static HRESULT WINAPI d3drm_frame1_SetRotation(IDirect3DRMFrame *iface,
2490         IDirect3DRMFrame *reference, D3DVALUE x, D3DVALUE y, D3DVALUE z, D3DVALUE theta)
2491 {
2492     FIXME("iface %p, reference %p, x %.8e, y %.8e, z %.8e, theta %.8e stub!\n",
2493             iface, reference, x, y, z, theta);
2494 
2495     return E_NOTIMPL;
2496 }
2497 
2498 static HRESULT WINAPI d3drm_frame3_SetSortMode(IDirect3DRMFrame3 *iface, D3DRMSORTMODE mode)
2499 {
2500     FIXME("iface %p, mode %#x stub!\n", iface, mode);
2501 
2502     return E_NOTIMPL;
2503 }
2504 
2505 static HRESULT WINAPI d3drm_frame2_SetSortMode(IDirect3DRMFrame2 *iface, D3DRMSORTMODE mode)
2506 {
2507     FIXME("iface %p, mode %#x stub!\n", iface, mode);
2508 
2509     return E_NOTIMPL;
2510 }
2511 
2512 static HRESULT WINAPI d3drm_frame1_SetSortMode(IDirect3DRMFrame *iface, D3DRMSORTMODE mode)
2513 {
2514     FIXME("iface %p, mode %#x stub!\n", iface, mode);
2515 
2516     return E_NOTIMPL;
2517 }
2518 
2519 static HRESULT WINAPI d3drm_frame3_SetTexture(IDirect3DRMFrame3 *iface, IDirect3DRMTexture3 *texture)
2520 {
2521     FIXME("iface %p, texture %p stub!\n", iface, texture);
2522 
2523     return E_NOTIMPL;
2524 }
2525 
2526 static HRESULT WINAPI d3drm_frame2_SetTexture(IDirect3DRMFrame2 *iface, IDirect3DRMTexture *texture)
2527 {
2528     FIXME("iface %p, texture %p stub!\n", iface, texture);
2529 
2530     return E_NOTIMPL;
2531 }
2532 
2533 static HRESULT WINAPI d3drm_frame1_SetTexture(IDirect3DRMFrame *iface, IDirect3DRMTexture *texture)
2534 {
2535     FIXME("iface %p, texture %p stub!\n", iface, texture);
2536 
2537     return E_NOTIMPL;
2538 }
2539 
2540 static HRESULT WINAPI d3drm_frame2_SetTextureTopology(IDirect3DRMFrame2 *iface, BOOL wrap_u, BOOL wrap_v)
2541 {
2542     FIXME("iface %p, wrap_u %#x, wrap_v %#x stub!\n", iface, wrap_u, wrap_v);
2543 
2544     return E_NOTIMPL;
2545 }
2546 
2547 static HRESULT WINAPI d3drm_frame1_SetTextureTopology(IDirect3DRMFrame *iface, BOOL wrap_u, BOOL wrap_v)
2548 {
2549     FIXME("iface %p, wrap_u %#x, wrap_v %#x stub!\n", iface, wrap_u, wrap_v);
2550 
2551     return E_NOTIMPL;
2552 }
2553 
2554 static HRESULT WINAPI d3drm_frame3_SetVelocity(IDirect3DRMFrame3 *iface,
2555         IDirect3DRMFrame3 *reference, D3DVALUE x, D3DVALUE y, D3DVALUE z, BOOL with_rotation)
2556 {
2557     FIXME("iface %p, reference %p, x %.8e, y %.8e, z %.8e, with_rotation %#x.\n",
2558             iface, reference, x, y, z, with_rotation);
2559 
2560     return E_NOTIMPL;
2561 }
2562 
2563 static HRESULT WINAPI d3drm_frame2_SetVelocity(IDirect3DRMFrame2 *iface,
2564         IDirect3DRMFrame *reference, D3DVALUE x, D3DVALUE y, D3DVALUE z, BOOL with_rotation)
2565 {
2566     FIXME("iface %p, reference %p, x %.8e, y %.8e, z %.8e, with_rotation %#x stub!\n",
2567             iface, reference, x, y, z, with_rotation);
2568 
2569     return E_NOTIMPL;
2570 }
2571 
2572 static HRESULT WINAPI d3drm_frame1_SetVelocity(IDirect3DRMFrame *iface,
2573         IDirect3DRMFrame *reference, D3DVALUE x, D3DVALUE y, D3DVALUE z, BOOL with_rotation)
2574 {
2575     FIXME("iface %p, reference %p, x %.8e, y %.8e, z %.8e, with_rotation %#x stub!\n",
2576             iface, reference, x, y, z, with_rotation);
2577 
2578     return E_NOTIMPL;
2579 }
2580 
2581 static HRESULT WINAPI d3drm_frame3_SetZbufferMode(IDirect3DRMFrame3 *iface, D3DRMZBUFFERMODE mode)
2582 {
2583     FIXME("iface %p, mode %#x stub!\n", iface, mode);
2584 
2585     return E_NOTIMPL;
2586 }
2587 
2588 static HRESULT WINAPI d3drm_frame2_SetZbufferMode(IDirect3DRMFrame2 *iface, D3DRMZBUFFERMODE mode)
2589 {
2590     FIXME("iface %p, mode %#x stub!\n", iface, mode);
2591 
2592     return E_NOTIMPL;
2593 }
2594 
2595 static HRESULT WINAPI d3drm_frame1_SetZbufferMode(IDirect3DRMFrame *iface, D3DRMZBUFFERMODE mode)
2596 {
2597     FIXME("iface %p, mode %#x stub!\n", iface, mode);
2598 
2599     return E_NOTIMPL;
2600 }
2601 
2602 static HRESULT WINAPI d3drm_frame3_Transform(IDirect3DRMFrame3 *iface, D3DVECTOR *d, D3DVECTOR *s)
2603 {
2604     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
2605 
2606     TRACE("iface %p, d %p, s %p.\n", iface, d, s);
2607 
2608     d3drm_vector_transform_affine(d, s, &frame->transform);
2609     while ((frame = frame->parent))
2610     {
2611         d3drm_vector_transform_affine(d, d, &frame->transform);
2612     }
2613 
2614     return D3DRM_OK;
2615 }
2616 
2617 static HRESULT WINAPI d3drm_frame2_Transform(IDirect3DRMFrame2 *iface, D3DVECTOR *d, D3DVECTOR *s)
2618 {
2619     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
2620 
2621     TRACE("iface %p, d %p, s %p.\n", iface, d, s);
2622 
2623     return d3drm_frame3_Transform(&frame->IDirect3DRMFrame3_iface, d, s);
2624 }
2625 
2626 static HRESULT WINAPI d3drm_frame1_Transform(IDirect3DRMFrame *iface, D3DVECTOR *d, D3DVECTOR *s)
2627 {
2628     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
2629 
2630     TRACE("iface %p, d %p, s %p.\n", iface, d, s);
2631 
2632     return d3drm_frame3_Transform(&frame->IDirect3DRMFrame3_iface, d, s);
2633 }
2634 
2635 static HRESULT WINAPI d3drm_frame2_AddMoveCallback2(IDirect3DRMFrame2 *iface,
2636         D3DRMFRAMEMOVECALLBACK cb, void *ctx, DWORD flags)
2637 {
2638     FIXME("iface %p, cb %p, ctx %p, flags %#x stub!\n", iface, cb, ctx, flags);
2639 
2640     return E_NOTIMPL;
2641 }
2642 
2643 static HRESULT WINAPI d3drm_frame3_GetBox(IDirect3DRMFrame3 *iface, D3DRMBOX *box)
2644 {
2645     FIXME("iface %p, box %p stub!\n", iface, box);
2646 
2647     return E_NOTIMPL;
2648 }
2649 
2650 static HRESULT WINAPI d3drm_frame2_GetBox(IDirect3DRMFrame2 *iface, D3DRMBOX *box)
2651 {
2652     FIXME("iface %p, box %p stub!\n", iface, box);
2653 
2654     return E_NOTIMPL;
2655 }
2656 
2657 static BOOL WINAPI d3drm_frame3_GetBoxEnable(IDirect3DRMFrame3 *iface)
2658 {
2659     FIXME("iface %p stub!\n", iface);
2660 
2661     return FALSE;
2662 }
2663 
2664 static BOOL WINAPI d3drm_frame2_GetBoxEnable(IDirect3DRMFrame2 *iface)
2665 {
2666     FIXME("iface %p stub!\n", iface);
2667 
2668     return FALSE;
2669 }
2670 
2671 static HRESULT WINAPI d3drm_frame3_GetAxes(IDirect3DRMFrame3 *iface, D3DVECTOR *dir, D3DVECTOR *up)
2672 {
2673     FIXME("iface %p, dir %p, up %p stub!\n", iface, dir, up);
2674 
2675     return E_NOTIMPL;
2676 }
2677 
2678 static HRESULT WINAPI d3drm_frame2_GetAxes(IDirect3DRMFrame2 *iface, D3DVECTOR *dir, D3DVECTOR *up)
2679 {
2680     FIXME("iface %p, dir %p, up %p stub!\n", iface, dir, up);
2681 
2682     return E_NOTIMPL;
2683 }
2684 
2685 static HRESULT WINAPI d3drm_frame3_GetMaterial(IDirect3DRMFrame3 *iface, IDirect3DRMMaterial2 **material)
2686 {
2687     FIXME("iface %p, material %p stub!\n", iface, material);
2688 
2689     return E_NOTIMPL;
2690 }
2691 
2692 static HRESULT WINAPI d3drm_frame2_GetMaterial(IDirect3DRMFrame2 *iface, IDirect3DRMMaterial **material)
2693 {
2694     FIXME("iface %p, material %p stub!\n", iface, material);
2695 
2696     return E_NOTIMPL;
2697 }
2698 
2699 static BOOL WINAPI d3drm_frame3_GetInheritAxes(IDirect3DRMFrame3 *iface)
2700 {
2701     FIXME("iface %p stub!\n", iface);
2702 
2703     return FALSE;
2704 }
2705 
2706 static BOOL WINAPI d3drm_frame2_GetInheritAxes(IDirect3DRMFrame2 *iface)
2707 {
2708     FIXME("iface %p stub!\n", iface);
2709 
2710     return FALSE;
2711 }
2712 
2713 static HRESULT WINAPI d3drm_frame3_GetHierarchyBox(IDirect3DRMFrame3 *iface, D3DRMBOX *box)
2714 {
2715     FIXME("iface %p, box %p stub!\n", iface, box);
2716 
2717     return E_NOTIMPL;
2718 }
2719 
2720 static HRESULT WINAPI d3drm_frame2_GetHierarchyBox(IDirect3DRMFrame2 *iface, D3DRMBOX *box)
2721 {
2722     FIXME("iface %p, box %p stub!\n", iface, box);
2723 
2724     return E_NOTIMPL;
2725 }
2726 
2727 static HRESULT WINAPI d3drm_frame3_SetBox(IDirect3DRMFrame3 *iface, D3DRMBOX *box)
2728 {
2729     FIXME("iface %p, box %p stub!\n", iface, box);
2730 
2731     return E_NOTIMPL;
2732 }
2733 
2734 static HRESULT WINAPI d3drm_frame3_SetBoxEnable(IDirect3DRMFrame3 *iface, BOOL enable)
2735 {
2736     FIXME("iface %p, enable %#x stub!\n", iface, enable);
2737 
2738     return E_NOTIMPL;
2739 }
2740 
2741 static HRESULT WINAPI d3drm_frame3_SetAxes(IDirect3DRMFrame3 *iface,
2742         D3DVALUE dx, D3DVALUE dy, D3DVALUE dz, D3DVALUE ux, D3DVALUE uy, D3DVALUE uz)
2743 {
2744     FIXME("iface %p, dx %.8e, dy %.8e, dz %.8e, ux %.8e, uy %.8e, uz %.8e stub!\n",
2745             iface, dx, dy, dz, ux, uy, uz);
2746 
2747     return E_NOTIMPL;
2748 }
2749 
2750 static HRESULT WINAPI d3drm_frame3_SetInheritAxes(IDirect3DRMFrame3 *iface, BOOL inherit)
2751 {
2752     FIXME("iface %p, inherit %#x stub!\n", iface, inherit);
2753 
2754     return E_NOTIMPL;
2755 }
2756 
2757 static HRESULT WINAPI d3drm_frame3_SetMaterial(IDirect3DRMFrame3 *iface, IDirect3DRMMaterial2 *material)
2758 {
2759     FIXME("iface %p, material %p stub!\n", iface, material);
2760 
2761     return E_NOTIMPL;
2762 }
2763 
2764 static HRESULT WINAPI d3drm_frame3_SetQuaternion(IDirect3DRMFrame3 *iface,
2765         IDirect3DRMFrame3 *reference, D3DRMQUATERNION *q)
2766 {
2767     FIXME("iface %p, reference %p, q %p stub!\n", iface, reference, q);
2768 
2769     return E_NOTIMPL;
2770 }
2771 
2772 static HRESULT WINAPI d3drm_frame3_RayPick(IDirect3DRMFrame3 *iface, IDirect3DRMFrame3 *reference,
2773         D3DRMRAY *ray, DWORD flags, IDirect3DRMPicked2Array **visuals)
2774 {
2775     FIXME("iface %p, reference %p, ray %p, flags %#x, visuals %p stub!\n",
2776             iface, reference, ray, flags, visuals);
2777 
2778     return E_NOTIMPL;
2779 }
2780 
2781 static HRESULT WINAPI d3drm_frame3_Save(IDirect3DRMFrame3 *iface,
2782         const char *filename, D3DRMXOFFORMAT format, D3DRMSAVEOPTIONS flags)
2783 {
2784     FIXME("iface %p, filename %s, format %#x, flags %#x stub!\n",
2785             iface, debugstr_a(filename), format, flags);
2786 
2787     return E_NOTIMPL;
2788 }
2789 
2790 static HRESULT WINAPI d3drm_frame3_TransformVectors(IDirect3DRMFrame3 *iface,
2791         IDirect3DRMFrame3 *reference, DWORD num, D3DVECTOR *dst, D3DVECTOR *src)
2792 {
2793     FIXME("iface %p, reference %p, num %u, dst %p, src %p stub!\n", iface, reference, num, dst, src);
2794 
2795     return E_NOTIMPL;
2796 }
2797 
2798 static HRESULT WINAPI d3drm_frame3_InverseTransformVectors(IDirect3DRMFrame3 *iface,
2799         IDirect3DRMFrame3 *reference, DWORD num, D3DVECTOR *dst, D3DVECTOR *src)
2800 {
2801     FIXME("iface %p, reference %p, num %u, dst %p, src %p stub!\n", iface, reference, num, dst, src);
2802 
2803     return E_NOTIMPL;
2804 }
2805 
2806 static HRESULT WINAPI d3drm_frame3_SetTraversalOptions(IDirect3DRMFrame3 *iface, DWORD options)
2807 {
2808     static const DWORD supported_options = D3DRMFRAME_RENDERENABLE | D3DRMFRAME_PICKENABLE;
2809     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
2810 
2811     TRACE("iface %p, options %#x.\n", iface, options);
2812 
2813     if (options & ~supported_options)
2814         return D3DRMERR_BADVALUE;
2815 
2816     frame->traversal_options = options;
2817 
2818     return D3DRM_OK;
2819 }
2820 
2821 static HRESULT WINAPI d3drm_frame3_GetTraversalOptions(IDirect3DRMFrame3 *iface, DWORD *options)
2822 {
2823     struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
2824 
2825     TRACE("iface %p, options %p.\n", iface, options);
2826 
2827     if (!options)
2828         return D3DRMERR_BADVALUE;
2829 
2830     *options = frame->traversal_options;
2831 
2832     return D3DRM_OK;
2833 }
2834 
2835 static HRESULT WINAPI d3drm_frame3_SetSceneFogMethod(IDirect3DRMFrame3 *iface, DWORD flags)
2836 {
2837     FIXME("iface %p, flags %#x stub!\n", iface, flags);
2838 
2839     return E_NOTIMPL;
2840 }
2841 
2842 static HRESULT WINAPI d3drm_frame3_GetSceneFogMethod(IDirect3DRMFrame3 *iface, DWORD *fog_mode)
2843 {
2844     FIXME("iface %p, fog_mode %p stub!\n", iface, fog_mode);
2845 
2846     return E_NOTIMPL;
2847 }
2848 
2849 static HRESULT WINAPI d3drm_frame3_SetMaterialOverride(IDirect3DRMFrame3 *iface,
2850         D3DRMMATERIALOVERRIDE *override)
2851 {
2852     FIXME("iface %p, override %p stub!\n", iface, override);
2853 
2854     return E_NOTIMPL;
2855 }
2856 
2857 static HRESULT WINAPI d3drm_frame3_GetMaterialOverride(IDirect3DRMFrame3 *iface,
2858         D3DRMMATERIALOVERRIDE *override)
2859 {
2860     FIXME("iface %p, override %p stub!\n", iface, override);
2861 
2862     return E_NOTIMPL;
2863 }
2864 
2865 static const struct IDirect3DRMFrame3Vtbl d3drm_frame3_vtbl =
2866 {
2867     d3drm_frame3_QueryInterface,
2868     d3drm_frame3_AddRef,
2869     d3drm_frame3_Release,
2870     d3drm_frame3_Clone,
2871     d3drm_frame3_AddDestroyCallback,
2872     d3drm_frame3_DeleteDestroyCallback,
2873     d3drm_frame3_SetAppData,
2874     d3drm_frame3_GetAppData,
2875     d3drm_frame3_SetName,
2876     d3drm_frame3_GetName,
2877     d3drm_frame3_GetClassName,
2878     d3drm_frame3_AddChild,
2879     d3drm_frame3_AddLight,
2880     d3drm_frame3_AddMoveCallback,
2881     d3drm_frame3_AddTransform,
2882     d3drm_frame3_AddTranslation,
2883     d3drm_frame3_AddScale,
2884     d3drm_frame3_AddRotation,
2885     d3drm_frame3_AddVisual,
2886     d3drm_frame3_GetChildren,
2887     d3drm_frame3_GetColor,
2888     d3drm_frame3_GetLights,
2889     d3drm_frame3_GetMaterialMode,
2890     d3drm_frame3_GetParent,
2891     d3drm_frame3_GetPosition,
2892     d3drm_frame3_GetRotation,
2893     d3drm_frame3_GetScene,
2894     d3drm_frame3_GetSortMode,
2895     d3drm_frame3_GetTexture,
2896     d3drm_frame3_GetTransform,
2897     d3drm_frame3_GetVelocity,
2898     d3drm_frame3_GetOrientation,
2899     d3drm_frame3_GetVisuals,
2900     d3drm_frame3_InverseTransform,
2901     d3drm_frame3_Load,
2902     d3drm_frame3_LookAt,
2903     d3drm_frame3_Move,
2904     d3drm_frame3_DeleteChild,
2905     d3drm_frame3_DeleteLight,
2906     d3drm_frame3_DeleteMoveCallback,
2907     d3drm_frame3_DeleteVisual,
2908     d3drm_frame3_GetSceneBackground,
2909     d3drm_frame3_GetSceneBackgroundDepth,
2910     d3drm_frame3_GetSceneFogColor,
2911     d3drm_frame3_GetSceneFogEnable,
2912     d3drm_frame3_GetSceneFogMode,
2913     d3drm_frame3_GetSceneFogParams,
2914     d3drm_frame3_SetSceneBackground,
2915     d3drm_frame3_SetSceneBackgroundRGB,
2916     d3drm_frame3_SetSceneBackgroundDepth,
2917     d3drm_frame3_SetSceneBackgroundImage,
2918     d3drm_frame3_SetSceneFogEnable,
2919     d3drm_frame3_SetSceneFogColor,
2920     d3drm_frame3_SetSceneFogMode,
2921     d3drm_frame3_SetSceneFogParams,
2922     d3drm_frame3_SetColor,
2923     d3drm_frame3_SetColorRGB,
2924     d3drm_frame3_GetZbufferMode,
2925     d3drm_frame3_SetMaterialMode,
2926     d3drm_frame3_SetOrientation,
2927     d3drm_frame3_SetPosition,
2928     d3drm_frame3_SetRotation,
2929     d3drm_frame3_SetSortMode,
2930     d3drm_frame3_SetTexture,
2931     d3drm_frame3_SetVelocity,
2932     d3drm_frame3_SetZbufferMode,
2933     d3drm_frame3_Transform,
2934     d3drm_frame3_GetBox,
2935     d3drm_frame3_GetBoxEnable,
2936     d3drm_frame3_GetAxes,
2937     d3drm_frame3_GetMaterial,
2938     d3drm_frame3_GetInheritAxes,
2939     d3drm_frame3_GetHierarchyBox,
2940     d3drm_frame3_SetBox,
2941     d3drm_frame3_SetBoxEnable,
2942     d3drm_frame3_SetAxes,
2943     d3drm_frame3_SetInheritAxes,
2944     d3drm_frame3_SetMaterial,
2945     d3drm_frame3_SetQuaternion,
2946     d3drm_frame3_RayPick,
2947     d3drm_frame3_Save,
2948     d3drm_frame3_TransformVectors,
2949     d3drm_frame3_InverseTransformVectors,
2950     d3drm_frame3_SetTraversalOptions,
2951     d3drm_frame3_GetTraversalOptions,
2952     d3drm_frame3_SetSceneFogMethod,
2953     d3drm_frame3_GetSceneFogMethod,
2954     d3drm_frame3_SetMaterialOverride,
2955     d3drm_frame3_GetMaterialOverride,
2956 };
2957 
2958 static const struct IDirect3DRMFrame2Vtbl d3drm_frame2_vtbl =
2959 {
2960     d3drm_frame2_QueryInterface,
2961     d3drm_frame2_AddRef,
2962     d3drm_frame2_Release,
2963     d3drm_frame2_Clone,
2964     d3drm_frame2_AddDestroyCallback,
2965     d3drm_frame2_DeleteDestroyCallback,
2966     d3drm_frame2_SetAppData,
2967     d3drm_frame2_GetAppData,
2968     d3drm_frame2_SetName,
2969     d3drm_frame2_GetName,
2970     d3drm_frame2_GetClassName,
2971     d3drm_frame2_AddChild,
2972     d3drm_frame2_AddLight,
2973     d3drm_frame2_AddMoveCallback,
2974     d3drm_frame2_AddTransform,
2975     d3drm_frame2_AddTranslation,
2976     d3drm_frame2_AddScale,
2977     d3drm_frame2_AddRotation,
2978     d3drm_frame2_AddVisual,
2979     d3drm_frame2_GetChildren,
2980     d3drm_frame2_GetColor,
2981     d3drm_frame2_GetLights,
2982     d3drm_frame2_GetMaterialMode,
2983     d3drm_frame2_GetParent,
2984     d3drm_frame2_GetPosition,
2985     d3drm_frame2_GetRotation,
2986     d3drm_frame2_GetScene,
2987     d3drm_frame2_GetSortMode,
2988     d3drm_frame2_GetTexture,
2989     d3drm_frame2_GetTransform,
2990     d3drm_frame2_GetVelocity,
2991     d3drm_frame2_GetOrientation,
2992     d3drm_frame2_GetVisuals,
2993     d3drm_frame2_GetTextureTopology,
2994     d3drm_frame2_InverseTransform,
2995     d3drm_frame2_Load,
2996     d3drm_frame2_LookAt,
2997     d3drm_frame2_Move,
2998     d3drm_frame2_DeleteChild,
2999     d3drm_frame2_DeleteLight,
3000     d3drm_frame2_DeleteMoveCallback,
3001     d3drm_frame2_DeleteVisual,
3002     d3drm_frame2_GetSceneBackground,
3003     d3drm_frame2_GetSceneBackgroundDepth,
3004     d3drm_frame2_GetSceneFogColor,
3005     d3drm_frame2_GetSceneFogEnable,
3006     d3drm_frame2_GetSceneFogMode,
3007     d3drm_frame2_GetSceneFogParams,
3008     d3drm_frame2_SetSceneBackground,
3009     d3drm_frame2_SetSceneBackgroundRGB,
3010     d3drm_frame2_SetSceneBackgroundDepth,
3011     d3drm_frame2_SetSceneBackgroundImage,
3012     d3drm_frame2_SetSceneFogEnable,
3013     d3drm_frame2_SetSceneFogColor,
3014     d3drm_frame2_SetSceneFogMode,
3015     d3drm_frame2_SetSceneFogParams,
3016     d3drm_frame2_SetColor,
3017     d3drm_frame2_SetColorRGB,
3018     d3drm_frame2_GetZbufferMode,
3019     d3drm_frame2_SetMaterialMode,
3020     d3drm_frame2_SetOrientation,
3021     d3drm_frame2_SetPosition,
3022     d3drm_frame2_SetRotation,
3023     d3drm_frame2_SetSortMode,
3024     d3drm_frame2_SetTexture,
3025     d3drm_frame2_SetTextureTopology,
3026     d3drm_frame2_SetVelocity,
3027     d3drm_frame2_SetZbufferMode,
3028     d3drm_frame2_Transform,
3029     d3drm_frame2_AddMoveCallback2,
3030     d3drm_frame2_GetBox,
3031     d3drm_frame2_GetBoxEnable,
3032     d3drm_frame2_GetAxes,
3033     d3drm_frame2_GetMaterial,
3034     d3drm_frame2_GetInheritAxes,
3035     d3drm_frame2_GetHierarchyBox,
3036 };
3037 
3038 static const struct IDirect3DRMFrameVtbl d3drm_frame1_vtbl =
3039 {
3040     d3drm_frame1_QueryInterface,
3041     d3drm_frame1_AddRef,
3042     d3drm_frame1_Release,
3043     d3drm_frame1_Clone,
3044     d3drm_frame1_AddDestroyCallback,
3045     d3drm_frame1_DeleteDestroyCallback,
3046     d3drm_frame1_SetAppData,
3047     d3drm_frame1_GetAppData,
3048     d3drm_frame1_SetName,
3049     d3drm_frame1_GetName,
3050     d3drm_frame1_GetClassName,
3051     d3drm_frame1_AddChild,
3052     d3drm_frame1_AddLight,
3053     d3drm_frame1_AddMoveCallback,
3054     d3drm_frame1_AddTransform,
3055     d3drm_frame1_AddTranslation,
3056     d3drm_frame1_AddScale,
3057     d3drm_frame1_AddRotation,
3058     d3drm_frame1_AddVisual,
3059     d3drm_frame1_GetChildren,
3060     d3drm_frame1_GetColor,
3061     d3drm_frame1_GetLights,
3062     d3drm_frame1_GetMaterialMode,
3063     d3drm_frame1_GetParent,
3064     d3drm_frame1_GetPosition,
3065     d3drm_frame1_GetRotation,
3066     d3drm_frame1_GetScene,
3067     d3drm_frame1_GetSortMode,
3068     d3drm_frame1_GetTexture,
3069     d3drm_frame1_GetTransform,
3070     d3drm_frame1_GetVelocity,
3071     d3drm_frame1_GetOrientation,
3072     d3drm_frame1_GetVisuals,
3073     d3drm_frame1_GetTextureTopology,
3074     d3drm_frame1_InverseTransform,
3075     d3drm_frame1_Load,
3076     d3drm_frame1_LookAt,
3077     d3drm_frame1_Move,
3078     d3drm_frame1_DeleteChild,
3079     d3drm_frame1_DeleteLight,
3080     d3drm_frame1_DeleteMoveCallback,
3081     d3drm_frame1_DeleteVisual,
3082     d3drm_frame1_GetSceneBackground,
3083     d3drm_frame1_GetSceneBackgroundDepth,
3084     d3drm_frame1_GetSceneFogColor,
3085     d3drm_frame1_GetSceneFogEnable,
3086     d3drm_frame1_GetSceneFogMode,
3087     d3drm_frame1_GetSceneFogParams,
3088     d3drm_frame1_SetSceneBackground,
3089     d3drm_frame1_SetSceneBackgroundRGB,
3090     d3drm_frame1_SetSceneBackgroundDepth,
3091     d3drm_frame1_SetSceneBackgroundImage,
3092     d3drm_frame1_SetSceneFogEnable,
3093     d3drm_frame1_SetSceneFogColor,
3094     d3drm_frame1_SetSceneFogMode,
3095     d3drm_frame1_SetSceneFogParams,
3096     d3drm_frame1_SetColor,
3097     d3drm_frame1_SetColorRGB,
3098     d3drm_frame1_GetZbufferMode,
3099     d3drm_frame1_SetMaterialMode,
3100     d3drm_frame1_SetOrientation,
3101     d3drm_frame1_SetPosition,
3102     d3drm_frame1_SetRotation,
3103     d3drm_frame1_SetSortMode,
3104     d3drm_frame1_SetTexture,
3105     d3drm_frame1_SetTextureTopology,
3106     d3drm_frame1_SetVelocity,
3107     d3drm_frame1_SetZbufferMode,
3108     d3drm_frame1_Transform,
3109 };
3110 
3111 struct d3drm_frame *unsafe_impl_from_IDirect3DRMFrame3(IDirect3DRMFrame3 *iface)
3112 {
3113     if (!iface)
3114         return NULL;
3115     assert(iface->lpVtbl == &d3drm_frame3_vtbl);
3116 
3117     return impl_from_IDirect3DRMFrame3(iface);
3118 }
3119 
3120 struct d3drm_frame *unsafe_impl_from_IDirect3DRMFrame(IDirect3DRMFrame *iface)
3121 {
3122     if (!iface)
3123         return NULL;
3124     assert(iface->lpVtbl == &d3drm_frame1_vtbl);
3125 
3126     return impl_from_IDirect3DRMFrame(iface);
3127 }
3128 
3129 HRESULT d3drm_frame_create(struct d3drm_frame **frame, IUnknown *parent_frame, IDirect3DRM *d3drm)
3130 {
3131     static const char classname[] = "Frame";
3132     struct d3drm_frame *object;
3133     HRESULT hr = D3DRM_OK;
3134 
3135     TRACE("frame %p, parent_frame %p, d3drm %p.\n", frame, parent_frame, d3drm);
3136 
3137     if (!(object = heap_alloc_zero(sizeof(*object))))
3138         return E_OUTOFMEMORY;
3139 
3140     object->IDirect3DRMFrame_iface.lpVtbl = &d3drm_frame1_vtbl;
3141     object->IDirect3DRMFrame2_iface.lpVtbl = &d3drm_frame2_vtbl;
3142     object->IDirect3DRMFrame3_iface.lpVtbl = &d3drm_frame3_vtbl;
3143     object->d3drm = d3drm;
3144     object->ref = 1;
3145     d3drm_set_color(&object->scenebackground, 0.0f, 0.0f, 0.0f, 1.0f);
3146     object->traversal_options = D3DRMFRAME_RENDERENABLE | D3DRMFRAME_PICKENABLE;
3147 
3148     d3drm_object_init(&object->obj, classname);
3149 
3150     object->transform = identity;
3151 
3152     if (parent_frame)
3153     {
3154         IDirect3DRMFrame3 *p;
3155 
3156         if (FAILED(hr = IDirect3DRMFrame_QueryInterface(parent_frame, &IID_IDirect3DRMFrame3, (void **)&p)))
3157         {
3158             heap_free(object);
3159             return hr;
3160         }
3161         IDirect3DRMFrame_Release(parent_frame);
3162         IDirect3DRMFrame3_AddChild(p, &object->IDirect3DRMFrame3_iface);
3163     }
3164 
3165     IDirect3DRM_AddRef(object->d3drm);
3166 
3167     *frame = object;
3168 
3169     return hr;
3170 }
3171 
3172 static HRESULT WINAPI d3drm_animation2_QueryInterface(IDirect3DRMAnimation2 *iface, REFIID riid, void **out)
3173 {
3174     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
3175 
3176     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
3177 
3178     if (IsEqualGUID(riid, &IID_IDirect3DRMAnimation)
3179             || IsEqualGUID(riid, &IID_IDirect3DRMObject)
3180             || IsEqualGUID(riid, &IID_IUnknown))
3181     {
3182         *out = &animation->IDirect3DRMAnimation_iface;
3183     }
3184     else if (IsEqualGUID(riid, &IID_IDirect3DRMAnimation2))
3185     {
3186         *out = &animation->IDirect3DRMAnimation2_iface;
3187     }
3188     else
3189     {
3190         *out = NULL;
3191         WARN("%s not implemented, returning CLASS_E_CLASSNOTAVAILABLE.\n", debugstr_guid(riid));
3192         return CLASS_E_CLASSNOTAVAILABLE;
3193     }
3194 
3195     IUnknown_AddRef((IUnknown *)*out);
3196     return S_OK;
3197 }
3198 
3199 static HRESULT WINAPI d3drm_animation1_QueryInterface(IDirect3DRMAnimation *iface, REFIID riid, void **out)
3200 {
3201     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
3202 
3203     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
3204 
3205     return IDirect3DRMAnimation2_QueryInterface(&animation->IDirect3DRMAnimation2_iface, riid, out);
3206 }
3207 
3208 static ULONG WINAPI d3drm_animation2_AddRef(IDirect3DRMAnimation2 *iface)
3209 {
3210     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
3211     ULONG refcount = InterlockedIncrement(&animation->ref);
3212 
3213     TRACE("%p increasing refcount to %u.\n", iface, refcount);
3214 
3215     return refcount;
3216 }
3217 
3218 static ULONG WINAPI d3drm_animation1_AddRef(IDirect3DRMAnimation *iface)
3219 {
3220     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
3221     return IDirect3DRMAnimation2_AddRef(&animation->IDirect3DRMAnimation2_iface);
3222 }
3223 
3224 static ULONG WINAPI d3drm_animation2_Release(IDirect3DRMAnimation2 *iface)
3225 {
3226     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
3227     ULONG refcount = InterlockedDecrement(&animation->ref);
3228 
3229     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
3230 
3231     if (!refcount)
3232     {
3233         d3drm_object_cleanup((IDirect3DRMObject *)&animation->IDirect3DRMAnimation_iface, &animation->obj);
3234         IDirect3DRM_Release(animation->d3drm);
3235         heap_free(animation->rotate.keys);
3236         heap_free(animation->scale.keys);
3237         heap_free(animation->position.keys);
3238         heap_free(animation);
3239     }
3240 
3241     return refcount;
3242 }
3243 
3244 static ULONG WINAPI d3drm_animation1_Release(IDirect3DRMAnimation *iface)
3245 {
3246     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
3247 
3248     return IDirect3DRMAnimation2_Release(&animation->IDirect3DRMAnimation2_iface);
3249 }
3250 
3251 static HRESULT WINAPI d3drm_animation2_Clone(IDirect3DRMAnimation2 *iface, IUnknown *outer, REFIID iid, void **out)
3252 {
3253     FIXME("iface %p, outer %p, iid %s, out %p stub!\n", iface, outer, debugstr_guid(iid), out);
3254 
3255     return E_NOTIMPL;
3256 }
3257 
3258 static HRESULT WINAPI d3drm_animation1_Clone(IDirect3DRMAnimation *iface, IUnknown *outer, REFIID iid, void **out)
3259 {
3260     FIXME("iface %p, outer %p, iid %s, out %p stub!\n", iface, outer, debugstr_guid(iid), out);
3261 
3262     return E_NOTIMPL;
3263 }
3264 
3265 static HRESULT WINAPI d3drm_animation2_AddDestroyCallback(IDirect3DRMAnimation2 *iface,
3266         D3DRMOBJECTCALLBACK cb, void *ctx)
3267 {
3268     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
3269 
3270     TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
3271 
3272     return d3drm_object_add_destroy_callback(&animation->obj, cb, ctx);
3273 }
3274 
3275 static HRESULT WINAPI d3drm_animation1_AddDestroyCallback(IDirect3DRMAnimation *iface,
3276         D3DRMOBJECTCALLBACK cb, void *ctx)
3277 {
3278     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
3279 
3280     TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
3281 
3282     return IDirect3DRMAnimation2_AddDestroyCallback(&animation->IDirect3DRMAnimation2_iface, cb, ctx);
3283 }
3284 
3285 static HRESULT WINAPI d3drm_animation2_DeleteDestroyCallback(IDirect3DRMAnimation2 *iface,
3286         D3DRMOBJECTCALLBACK cb, void *ctx)
3287 {
3288     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
3289 
3290     TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
3291 
3292     return d3drm_object_delete_destroy_callback(&animation->obj, cb, ctx);
3293 }
3294 
3295 static HRESULT WINAPI d3drm_animation1_DeleteDestroyCallback(IDirect3DRMAnimation *iface,
3296         D3DRMOBJECTCALLBACK cb, void *ctx)
3297 {
3298     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
3299 
3300     TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
3301 
3302     return IDirect3DRMAnimation2_DeleteDestroyCallback(&animation->IDirect3DRMAnimation2_iface, cb, ctx);
3303 }
3304 
3305 static HRESULT WINAPI d3drm_animation2_SetAppData(IDirect3DRMAnimation2 *iface, DWORD data)
3306 {
3307     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
3308 
3309     TRACE("iface %p, data %#x.\n", iface, data);
3310 
3311     animation->obj.appdata = data;
3312 
3313     return D3DRM_OK;
3314 }
3315 
3316 static HRESULT WINAPI d3drm_animation1_SetAppData(IDirect3DRMAnimation *iface, DWORD data)
3317 {
3318     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
3319 
3320     TRACE("iface %p, data %#x.\n", iface, data);
3321 
3322     return d3drm_animation2_SetAppData(&animation->IDirect3DRMAnimation2_iface, data);
3323 }
3324 
3325 static DWORD WINAPI d3drm_animation2_GetAppData(IDirect3DRMAnimation2 *iface)
3326 {
3327     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
3328 
3329     TRACE("iface %p.\n", iface);
3330 
3331     return animation->obj.appdata;
3332 }
3333 
3334 static DWORD WINAPI d3drm_animation1_GetAppData(IDirect3DRMAnimation *iface)
3335 {
3336     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
3337 
3338     TRACE("iface %p.\n", iface);
3339 
3340     return d3drm_animation2_GetAppData(&animation->IDirect3DRMAnimation2_iface);
3341 }
3342 
3343 static HRESULT WINAPI d3drm_animation2_SetName(IDirect3DRMAnimation2 *iface, const char *name)
3344 {
3345     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
3346 
3347     TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
3348 
3349     return d3drm_object_set_name(&animation->obj, name);
3350 }
3351 
3352 static HRESULT WINAPI d3drm_animation1_SetName(IDirect3DRMAnimation *iface, const char *name)
3353 {
3354     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
3355 
3356     TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
3357 
3358     return d3drm_animation2_SetName(&animation->IDirect3DRMAnimation2_iface, name);
3359 }
3360 
3361 static HRESULT WINAPI d3drm_animation2_GetName(IDirect3DRMAnimation2 *iface, DWORD *size, char *name)
3362 {
3363     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
3364 
3365     TRACE("iface %p, size %p, name %p.\n", iface, size, name);
3366 
3367     return d3drm_object_get_name(&animation->obj, size, name);
3368 }
3369 
3370 static HRESULT WINAPI d3drm_animation1_GetName(IDirect3DRMAnimation *iface, DWORD *size, char *name)
3371 {
3372     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
3373 
3374     TRACE("iface %p, size %p, name %p.\n", iface, size, name);
3375 
3376     return d3drm_animation2_GetName(&animation->IDirect3DRMAnimation2_iface, size, name);
3377 }
3378 
3379 static HRESULT WINAPI d3drm_animation2_GetClassName(IDirect3DRMAnimation2 *iface, DWORD *size, char *name)
3380 {
3381     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
3382 
3383     TRACE("iface %p, size %p, name %p.\n", iface, size, name);
3384 
3385     return d3drm_object_get_class_name(&animation->obj, size, name);
3386 }
3387 
3388 static HRESULT WINAPI d3drm_animation1_GetClassName(IDirect3DRMAnimation *iface, DWORD *size, char *name)
3389 {
3390     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
3391 
3392     TRACE("iface %p, size %p, name %p.\n", iface, size, name);
3393 
3394     return d3drm_animation2_GetClassName(&animation->IDirect3DRMAnimation2_iface, size, name);
3395 }
3396 
3397 static HRESULT WINAPI d3drm_animation2_SetOptions(IDirect3DRMAnimation2 *iface, D3DRMANIMATIONOPTIONS options)
3398 {
3399     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
3400     static const DWORD supported_options = D3DRMANIMATION_OPEN | D3DRMANIMATION_CLOSED | D3DRMANIMATION_LINEARPOSITION
3401         | D3DRMANIMATION_SPLINEPOSITION | D3DRMANIMATION_SCALEANDROTATION | D3DRMANIMATION_POSITION;
3402 
3403     TRACE("iface %p, options %#x.\n", iface, options);
3404 
3405     if (!(options & supported_options))
3406         return D3DRMERR_BADVALUE;
3407 
3408     if ((options & (D3DRMANIMATION_OPEN | D3DRMANIMATION_CLOSED)) == (D3DRMANIMATION_OPEN | D3DRMANIMATION_CLOSED) ||
3409             (options & (D3DRMANIMATION_LINEARPOSITION | D3DRMANIMATION_SPLINEPOSITION)) ==
3410             (D3DRMANIMATION_LINEARPOSITION | D3DRMANIMATION_SPLINEPOSITION) ||
3411             (options & (D3DRMANIMATION_SCALEANDROTATION | D3DRMANIMATION_POSITION)) ==
3412             (D3DRMANIMATION_SCALEANDROTATION | D3DRMANIMATION_POSITION))
3413     {
3414         return D3DRMERR_BADVALUE;
3415     }
3416 
3417     animation->options = options;
3418 
3419     return D3DRM_OK;
3420 }
3421 
3422 static HRESULT WINAPI d3drm_animation1_SetOptions(IDirect3DRMAnimation *iface, D3DRMANIMATIONOPTIONS options)
3423 {
3424     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
3425 
3426     TRACE("iface %p, %#x.\n", iface, options);
3427 
3428     return d3drm_animation2_SetOptions(&animation->IDirect3DRMAnimation2_iface, options);
3429 }
3430 
3431 static SIZE_T d3drm_animation_lookup_key(const struct d3drm_animation_key *keys,
3432         SIZE_T count, D3DVALUE time)
3433 {
3434     SIZE_T start = 0, cur = 0, end = count;
3435 
3436     while (start < end)
3437     {
3438         cur = start + (end - start) / 2;
3439 
3440         if (time == keys[cur].time)
3441             return cur;
3442 
3443         if (time < keys[cur].time)
3444             end = cur;
3445         else
3446             start = cur + 1;
3447     }
3448 
3449     return cur;
3450 }
3451 
3452 static SIZE_T d3drm_animation_get_index_min(const struct d3drm_animation_key *keys, SIZE_T count, D3DVALUE time)
3453 {
3454     SIZE_T i;
3455 
3456     i = d3drm_animation_lookup_key(keys, count, time);
3457     while (i > 0 && keys[i - 1].time == time)
3458         --i;
3459 
3460     return i;
3461 }
3462 
3463 static SIZE_T d3drm_animation_get_index_max(const struct d3drm_animation_key *keys, SIZE_T count, D3DVALUE time)
3464 {
3465     SIZE_T i;
3466 
3467     i = d3drm_animation_lookup_key(keys, count, time);
3468     while (i < count - 1 && keys[i + 1].time == time)
3469         ++i;
3470 
3471     return i;
3472 }
3473 
3474 static SIZE_T d3drm_animation_get_insert_position(const struct d3drm_animation_keys *keys, D3DVALUE time)
3475 {
3476     if (!keys->count || time < keys->keys[0].time)
3477         return 0;
3478 
3479     if (time >= keys->keys[keys->count - 1].time)
3480         return keys->count;
3481 
3482     return d3drm_animation_get_index_max(keys->keys, keys->count, time);
3483 }
3484 
3485 static const struct d3drm_animation_key *d3drm_animation_get_range(const struct d3drm_animation_keys *keys,
3486         D3DVALUE time_min, D3DVALUE time_max, SIZE_T *count)
3487 {
3488     SIZE_T min;
3489 
3490     if (!keys->count || time_max < keys->keys[0].time
3491             || time_min > keys->keys[keys->count - 1].time)
3492         return NULL;
3493 
3494     min = d3drm_animation_get_index_min(keys->keys, keys->count, time_min);
3495     if (count)
3496         *count = d3drm_animation_get_index_max(&keys->keys[min], keys->count - min, time_max) - min + 1;
3497 
3498     return &keys->keys[min];
3499 }
3500 
3501 static HRESULT WINAPI d3drm_animation2_AddKey(IDirect3DRMAnimation2 *iface, D3DRMANIMATIONKEY *key)
3502 {
3503     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
3504     struct d3drm_animation_keys *keys;
3505     SIZE_T index;
3506 
3507     TRACE("iface %p, key %p.\n", iface, key);
3508 
3509     if (!key || key->dwSize != sizeof(*key))
3510         return E_INVALIDARG;
3511 
3512     switch (key->dwKeyType)
3513     {
3514         case D3DRMANIMATION_POSITIONKEY:
3515             keys = &animation->position;
3516             break;
3517         case D3DRMANIMATION_SCALEKEY:
3518             keys = &animation->scale;
3519             break;
3520         case D3DRMANIMATION_ROTATEKEY:
3521             keys = &animation->rotate;
3522             break;
3523         default:
3524             return E_INVALIDARG;
3525     }
3526 
3527     index = d3drm_animation_get_insert_position(keys, key->dvTime);
3528 
3529     if (!d3drm_array_reserve((void **)&keys->keys, &keys->size, keys->count + 1, sizeof(*keys->keys)))
3530         return E_OUTOFMEMORY;
3531 
3532     if (index < keys->count)
3533         memmove(&keys->keys[index + 1], &keys->keys[index], sizeof(*keys->keys) * (keys->count - index));
3534     keys->keys[index].time = key->dvTime;
3535     switch (key->dwKeyType)
3536     {
3537         case D3DRMANIMATION_POSITIONKEY:
3538             keys->keys[index].u.position = key->u.dvPositionKey;
3539             break;
3540         case D3DRMANIMATION_SCALEKEY:
3541             keys->keys[index].u.scale = key->u.dvScaleKey;
3542             break;
3543         case D3DRMANIMATION_ROTATEKEY:
3544             keys->keys[index].u.rotate = key->u.dqRotateKey;
3545             break;
3546     }
3547     ++keys->count;
3548 
3549     return D3DRM_OK;
3550 }
3551 
3552 static HRESULT WINAPI d3drm_animation2_AddRotateKey(IDirect3DRMAnimation2 *iface, D3DVALUE time, D3DRMQUATERNION *q)
3553 {
3554     D3DRMANIMATIONKEY key;
3555 
3556     TRACE("iface %p, time %.8e, q %p.\n", iface, time, q);
3557 
3558     key.dwSize = sizeof(key);
3559     key.dwKeyType = D3DRMANIMATION_ROTATEKEY;
3560     key.dvTime = time;
3561     key.dwID = 0;
3562     key.u.dqRotateKey = *q;
3563 
3564     return d3drm_animation2_AddKey(iface, &key);
3565 }
3566 
3567 static HRESULT WINAPI d3drm_animation1_AddRotateKey(IDirect3DRMAnimation *iface, D3DVALUE time, D3DRMQUATERNION *q)
3568 {
3569     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
3570 
3571     TRACE("iface %p, time %.8e, q %p.\n", iface, time, q);
3572 
3573     return d3drm_animation2_AddRotateKey(&animation->IDirect3DRMAnimation2_iface, time, q);
3574 }
3575 
3576 static HRESULT WINAPI d3drm_animation2_AddPositionKey(IDirect3DRMAnimation2 *iface, D3DVALUE time,
3577         D3DVALUE x, D3DVALUE y, D3DVALUE z)
3578 {
3579     D3DRMANIMATIONKEY key;
3580 
3581     TRACE("iface %p, time %.8e, x %.8e, y %.8e, z %.8e.\n", iface, time, x, y, z);
3582 
3583     key.dwSize = sizeof(key);
3584     key.dwKeyType = D3DRMANIMATION_POSITIONKEY;
3585     key.dvTime = time;
3586     key.dwID = 0;
3587     key.u.dvPositionKey.u1.x = x;
3588     key.u.dvPositionKey.u2.y = y;
3589     key.u.dvPositionKey.u3.z = z;
3590 
3591     return d3drm_animation2_AddKey(iface, &key);
3592 }
3593 
3594 static HRESULT WINAPI d3drm_animation1_AddPositionKey(IDirect3DRMAnimation *iface, D3DVALUE time,
3595         D3DVALUE x, D3DVALUE y, D3DVALUE z)
3596 {
3597     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
3598 
3599     TRACE("iface %p, time %.8e, x %.8e, y %.8e, z %.8e.\n", iface, time, x, y, z);
3600 
3601     return d3drm_animation2_AddPositionKey(&animation->IDirect3DRMAnimation2_iface, time, x, y, z);
3602 }
3603 
3604 static HRESULT WINAPI d3drm_animation2_AddScaleKey(IDirect3DRMAnimation2 *iface, D3DVALUE time,
3605         D3DVALUE x, D3DVALUE y, D3DVALUE z)
3606 {
3607     D3DRMANIMATIONKEY key;
3608 
3609     TRACE("iface %p, time %.8e, x %.8e, y %.8e, z %.8e.\n", iface, time, x, y, z);
3610 
3611     key.dwSize = sizeof(key);
3612     key.dwKeyType = D3DRMANIMATION_SCALEKEY;
3613     key.dvTime = time;
3614     key.dwID = 0;
3615     key.u.dvScaleKey.u1.x = x;
3616     key.u.dvScaleKey.u2.y = y;
3617     key.u.dvScaleKey.u3.z = z;
3618 
3619     return d3drm_animation2_AddKey(iface, &key);
3620 }
3621 
3622 static HRESULT WINAPI d3drm_animation1_AddScaleKey(IDirect3DRMAnimation *iface, D3DVALUE time,
3623         D3DVALUE x, D3DVALUE y, D3DVALUE z)
3624 {
3625     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
3626 
3627     TRACE("iface %p, time %.8e, x %.8e, y %.8e, z %.8e.\n", iface, time, x, y, z);
3628 
3629     return d3drm_animation2_AddScaleKey(&animation->IDirect3DRMAnimation2_iface, time, x, y, z);
3630 }
3631 
3632 static void d3drm_animation_delete_key(struct d3drm_animation_keys *keys, const struct d3drm_animation_key *key)
3633 {
3634     SIZE_T index = key - keys->keys;
3635 
3636     if (index < keys->count - 1)
3637         memmove(&keys->keys[index], &keys->keys[index + 1], sizeof(*keys->keys) * (keys->count - index - 1));
3638     --keys->count;
3639 }
3640 
3641 static HRESULT WINAPI d3drm_animation2_DeleteKey(IDirect3DRMAnimation2 *iface, D3DVALUE time)
3642 {
3643     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
3644     const struct d3drm_animation_key *key;
3645 
3646     TRACE("iface %p, time %.8e.\n", iface, time);
3647 
3648     if ((key = d3drm_animation_get_range(&animation->rotate, time, time, NULL)))
3649         d3drm_animation_delete_key(&animation->rotate, key);
3650 
3651     if ((key = d3drm_animation_get_range(&animation->position, time, time, NULL)))
3652         d3drm_animation_delete_key(&animation->position, key);
3653 
3654     if ((key = d3drm_animation_get_range(&animation->scale, time, time, NULL)))
3655         d3drm_animation_delete_key(&animation->scale, key);
3656 
3657     return D3DRM_OK;
3658 }
3659 
3660 static HRESULT WINAPI d3drm_animation1_DeleteKey(IDirect3DRMAnimation *iface, D3DVALUE time)
3661 {
3662     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
3663 
3664     TRACE("iface %p, time %.8e.\n", iface, time);
3665 
3666     return d3drm_animation2_DeleteKey(&animation->IDirect3DRMAnimation2_iface, time);
3667 }
3668 
3669 static HRESULT WINAPI d3drm_animation1_SetFrame(IDirect3DRMAnimation *iface, IDirect3DRMFrame *frame)
3670 {
3671     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
3672     HRESULT hr = D3DRM_OK;
3673 
3674     TRACE("iface %p, frame %p.\n", iface, frame);
3675 
3676     if (frame)
3677     {
3678         hr = IDirect3DRMFrame_QueryInterface(frame, &IID_IDirect3DRMFrame3, (void **)&animation->frame);
3679         if (SUCCEEDED(hr))
3680             IDirect3DRMFrame3_Release(animation->frame);
3681     }
3682     else
3683         animation->frame = NULL;
3684 
3685     return hr;
3686 }
3687 
3688 static HRESULT WINAPI d3drm_animation1_SetTime(IDirect3DRMAnimation *iface, D3DVALUE time)
3689 {
3690     FIXME("iface %p, time %.8e.\n", iface, time);
3691 
3692     return E_NOTIMPL;
3693 }
3694 
3695 static D3DRMANIMATIONOPTIONS WINAPI d3drm_animation2_GetOptions(IDirect3DRMAnimation2 *iface)
3696 {
3697     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
3698 
3699     TRACE("iface %p.\n", iface);
3700 
3701     return animation->options;
3702 }
3703 
3704 static D3DRMANIMATIONOPTIONS WINAPI d3drm_animation1_GetOptions(IDirect3DRMAnimation *iface)
3705 {
3706     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
3707 
3708     TRACE("iface %p.\n", iface);
3709 
3710     return d3drm_animation2_GetOptions(&animation->IDirect3DRMAnimation2_iface);
3711 }
3712 
3713 static HRESULT WINAPI d3drm_animation2_SetFrame(IDirect3DRMAnimation2 *iface, IDirect3DRMFrame3 *frame)
3714 {
3715     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
3716 
3717     TRACE("iface %p, frame %p.\n", iface, frame);
3718 
3719     animation->frame = frame;
3720 
3721     return D3DRM_OK;
3722 }
3723 
3724 static HRESULT WINAPI d3drm_animation2_SetTime(IDirect3DRMAnimation2 *iface, D3DVALUE time)
3725 {
3726     FIXME("iface %p, time %.8e.\n", iface, time);
3727 
3728     return E_NOTIMPL;
3729 }
3730 
3731 static HRESULT WINAPI d3drm_animation2_GetFrame(IDirect3DRMAnimation2 *iface, IDirect3DRMFrame3 **frame)
3732 {
3733     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
3734 
3735     TRACE("iface %p, frame %p.\n", iface, frame);
3736 
3737     if (!frame)
3738         return D3DRMERR_BADVALUE;
3739 
3740     *frame = animation->frame;
3741     if (*frame)
3742         IDirect3DRMFrame3_AddRef(*frame);
3743 
3744     return D3DRM_OK;
3745 }
3746 
3747 static HRESULT WINAPI d3drm_animation2_DeleteKeyByID(IDirect3DRMAnimation2 *iface, DWORD id)
3748 {
3749     FIXME("iface %p, id %#x.\n", iface, id);
3750 
3751     return E_NOTIMPL;
3752 }
3753 
3754 static HRESULT WINAPI d3drm_animation2_ModifyKey(IDirect3DRMAnimation2 *iface, D3DRMANIMATIONKEY *key)
3755 {
3756     FIXME("iface %p, key %p.\n", iface, key);
3757 
3758     return E_NOTIMPL;
3759 }
3760 
3761 static HRESULT WINAPI d3drm_animation2_GetKeys(IDirect3DRMAnimation2 *iface, D3DVALUE time_min, D3DVALUE time_max,
3762         DWORD *key_count, D3DRMANIMATIONKEY *keys)
3763 {
3764     struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
3765     const struct d3drm_animation_key *key;
3766     SIZE_T count, i;
3767 
3768     TRACE("iface %p, time min %.8e, time max %.8e, key_count %p, keys %p.\n",
3769             iface, time_min, time_max, key_count, keys);
3770 
3771     if (!key_count)
3772         return D3DRMERR_BADVALUE;
3773 
3774     *key_count = 0;
3775 
3776     if ((key = d3drm_animation_get_range(&animation->rotate, time_min, time_max, &count)))
3777     {
3778         if (keys)
3779         {
3780             for (i = 0; i < count; ++i)
3781             {
3782                 keys[i].dwSize = sizeof(*keys);
3783                 keys[i].dwKeyType = D3DRMANIMATION_ROTATEKEY;
3784                 keys[i].dvTime = key[i].time;
3785                 keys[i].dwID = 0; /* FIXME */
3786                 keys[i].u.dqRotateKey = key[i].u.rotate;
3787             }
3788             keys += count;
3789         }
3790         *key_count += count;
3791     }
3792 
3793     if ((key = d3drm_animation_get_range(&animation->position, time_min, time_max, &count)))
3794     {
3795         if (keys)
3796         {
3797             for (i = 0; i < count; ++i)
3798             {
3799                 keys[i].dwSize = sizeof(*keys);
3800                 keys[i].dwKeyType = D3DRMANIMATION_POSITIONKEY;
3801                 keys[i].dvTime = key[i].time;
3802                 keys[i].dwID = 0; /* FIXME */
3803                 keys[i].u.dvPositionKey = key[i].u.position;
3804             }
3805             keys += count;
3806         }
3807         *key_count += count;
3808     }
3809 
3810     if ((key = d3drm_animation_get_range(&animation->scale, time_min, time_max, &count)))
3811     {
3812         if (keys)
3813         {
3814             for (i = 0; keys && i < count; ++i)
3815             {
3816                 keys[i].dwSize = sizeof(*keys);
3817                 keys[i].dwKeyType = D3DRMANIMATION_SCALEKEY;
3818                 keys[i].dvTime = key[i].time;
3819                 keys[i].dwID = 0; /* FIXME */
3820                 keys[i].u.dvScaleKey = key[i].u.scale;
3821             }
3822             keys += count;
3823         }
3824         *key_count += count;
3825     }
3826 
3827     return *key_count ? D3DRM_OK : D3DRMERR_NOSUCHKEY;
3828 }
3829 
3830 static const struct IDirect3DRMAnimationVtbl d3drm_animation1_vtbl =
3831 {
3832     d3drm_animation1_QueryInterface,
3833     d3drm_animation1_AddRef,
3834     d3drm_animation1_Release,
3835     d3drm_animation1_Clone,
3836     d3drm_animation1_AddDestroyCallback,
3837     d3drm_animation1_DeleteDestroyCallback,
3838     d3drm_animation1_SetAppData,
3839     d3drm_animation1_GetAppData,
3840     d3drm_animation1_SetName,
3841     d3drm_animation1_GetName,
3842     d3drm_animation1_GetClassName,
3843     d3drm_animation1_SetOptions,
3844     d3drm_animation1_AddRotateKey,
3845     d3drm_animation1_AddPositionKey,
3846     d3drm_animation1_AddScaleKey,
3847     d3drm_animation1_DeleteKey,
3848     d3drm_animation1_SetFrame,
3849     d3drm_animation1_SetTime,
3850     d3drm_animation1_GetOptions,
3851 };
3852 
3853 static const struct IDirect3DRMAnimation2Vtbl d3drm_animation2_vtbl =
3854 {
3855     d3drm_animation2_QueryInterface,
3856     d3drm_animation2_AddRef,
3857     d3drm_animation2_Release,
3858     d3drm_animation2_Clone,
3859     d3drm_animation2_AddDestroyCallback,
3860     d3drm_animation2_DeleteDestroyCallback,
3861     d3drm_animation2_SetAppData,
3862     d3drm_animation2_GetAppData,
3863     d3drm_animation2_SetName,
3864     d3drm_animation2_GetName,
3865     d3drm_animation2_GetClassName,
3866     d3drm_animation2_SetOptions,
3867     d3drm_animation2_AddRotateKey,
3868     d3drm_animation2_AddPositionKey,
3869     d3drm_animation2_AddScaleKey,
3870     d3drm_animation2_DeleteKey,
3871     d3drm_animation2_SetFrame,
3872     d3drm_animation2_SetTime,
3873     d3drm_animation2_GetOptions,
3874     d3drm_animation2_GetFrame,
3875     d3drm_animation2_DeleteKeyByID,
3876     d3drm_animation2_AddKey,
3877     d3drm_animation2_ModifyKey,
3878     d3drm_animation2_GetKeys,
3879 };
3880 
3881 HRESULT d3drm_animation_create(struct d3drm_animation **animation, IDirect3DRM *d3drm)
3882 {
3883     static const char classname[] = "Animation";
3884     struct d3drm_animation *object;
3885     HRESULT hr = D3DRM_OK;
3886 
3887     TRACE("animation %p, d3drm %p.\n", animation, d3drm);
3888 
3889     if (!(object = heap_alloc_zero(sizeof(*object))))
3890         return E_OUTOFMEMORY;
3891 
3892     object->IDirect3DRMAnimation_iface.lpVtbl = &d3drm_animation1_vtbl;
3893     object->IDirect3DRMAnimation2_iface.lpVtbl = &d3drm_animation2_vtbl;
3894     object->d3drm = d3drm;
3895     object->ref = 1;
3896     object->options = D3DRMANIMATION_CLOSED | D3DRMANIMATION_LINEARPOSITION;
3897 
3898     d3drm_object_init(&object->obj, classname);
3899 
3900     IDirect3DRM_AddRef(object->d3drm);
3901 
3902     *animation = object;
3903 
3904     return hr;
3905 }
3906