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