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