xref: /reactos/dll/directx/wine/d3drm/viewport.c (revision 139a3d66)
1 /*
2  * Implementation of IDirect3DRMViewport Interface
3  *
4  * Copyright 2012 André Hentschel
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #include "d3drm_private.h"
22 
23 WINE_DEFAULT_DEBUG_CHANNEL(d3drm);
24 
25 static inline struct d3drm_viewport *impl_from_IDirect3DRMViewport(IDirect3DRMViewport *iface)
26 {
27     return CONTAINING_RECORD(iface, struct d3drm_viewport, IDirect3DRMViewport_iface);
28 }
29 
30 static inline struct d3drm_viewport *impl_from_IDirect3DRMViewport2(IDirect3DRMViewport2 *iface)
31 {
32     return CONTAINING_RECORD(iface, struct d3drm_viewport, IDirect3DRMViewport2_iface);
33 }
34 
35 static inline void d3drm_normalize_d3d_color(D3DCOLORVALUE *color_value, D3DCOLOR color)
36 {
37     color_value->u1.r = RGBA_GETRED(color) / 255.0f;
38     color_value->u2.g = RGBA_GETGREEN(color) / 255.0f;
39     color_value->u3.b = RGBA_GETBLUE(color) / 255.0f;
40     color_value->u4.a = RGBA_GETALPHA(color) / 255.0f;
41 }
42 
43 static HRESULT d3drm_update_background_material(struct d3drm_viewport *viewport)
44 {
45     IDirect3DRMFrame *root_frame;
46     D3DCOLOR color;
47     D3DMATERIAL mat;
48     HRESULT hr;
49 
50     if (FAILED(hr = IDirect3DRMFrame_GetScene(viewport->camera, &root_frame)))
51         return hr;
52     color = IDirect3DRMFrame_GetSceneBackground(root_frame);
53     IDirect3DRMFrame_Release(root_frame);
54 
55     memset(&mat, 0, sizeof(mat));
56     mat.dwSize = sizeof(mat);
57     d3drm_normalize_d3d_color(&mat.u.diffuse, color);
58 
59     return IDirect3DMaterial_SetMaterial(viewport->material, &mat);
60 }
61 
62 static void d3drm_viewport_destroy(struct d3drm_viewport *viewport)
63 {
64     TRACE("viewport %p releasing attached interfaces.\n", viewport);
65 
66     d3drm_object_cleanup((IDirect3DRMObject *)&viewport->IDirect3DRMViewport_iface, &viewport->obj);
67 
68     if (viewport->d3d_viewport)
69     {
70         IDirect3DViewport_Release(viewport->d3d_viewport);
71         IDirect3DMaterial_Release(viewport->material);
72         IDirect3DRMFrame_Release(viewport->camera);
73         IDirect3DRM_Release(viewport->d3drm);
74     }
75 
76     heap_free(viewport);
77 }
78 
79 static HRESULT WINAPI d3drm_viewport2_QueryInterface(IDirect3DRMViewport2 *iface, REFIID riid, void **out)
80 {
81     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport2(iface);
82 
83     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
84 
85     if (IsEqualGUID(riid, &IID_IDirect3DRMViewport)
86             || IsEqualGUID(riid, &IID_IDirect3DRMObject)
87             || IsEqualGUID(riid, &IID_IUnknown))
88     {
89         *out = &viewport->IDirect3DRMViewport_iface;
90     }
91     else if (IsEqualGUID(riid, &IID_IDirect3DRMViewport2))
92     {
93         *out = &viewport->IDirect3DRMViewport2_iface;
94     }
95     else
96     {
97         *out = NULL;
98         WARN("%s not implemented, returning CLASS_E_CLASSNOTAVAILABLE.\n", debugstr_guid(riid));
99         return CLASS_E_CLASSNOTAVAILABLE;
100     }
101 
102     IUnknown_AddRef((IUnknown *)*out);
103     return S_OK;
104 }
105 
106 static HRESULT WINAPI d3drm_viewport1_QueryInterface(IDirect3DRMViewport *iface, REFIID riid, void **out)
107 {
108     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport(iface);
109 
110     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
111 
112     return d3drm_viewport2_QueryInterface(&viewport->IDirect3DRMViewport2_iface, riid, out);
113 }
114 
115 static ULONG WINAPI d3drm_viewport2_AddRef(IDirect3DRMViewport2 *iface)
116 {
117     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport2(iface);
118     ULONG refcount = InterlockedIncrement(&viewport->obj.ref);
119 
120     TRACE("%p increasing refcount to %u.\n", iface, refcount);
121 
122     return refcount;
123 }
124 
125 static ULONG WINAPI d3drm_viewport1_AddRef(IDirect3DRMViewport *iface)
126 {
127     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport(iface);
128 
129     TRACE("iface %p.\n", iface);
130 
131     return d3drm_viewport2_AddRef(&viewport->IDirect3DRMViewport2_iface);
132 }
133 
134 static ULONG WINAPI d3drm_viewport2_Release(IDirect3DRMViewport2 *iface)
135 {
136     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport2(iface);
137     ULONG refcount = InterlockedDecrement(&viewport->obj.ref);
138 
139     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
140 
141     if (!refcount)
142         d3drm_viewport_destroy(viewport);
143 
144     return refcount;
145 }
146 
147 static ULONG WINAPI d3drm_viewport1_Release(IDirect3DRMViewport *iface)
148 {
149     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport(iface);
150 
151     TRACE("iface %p.\n", iface);
152 
153     return d3drm_viewport2_Release(&viewport->IDirect3DRMViewport2_iface);
154 }
155 
156 static HRESULT WINAPI d3drm_viewport2_Clone(IDirect3DRMViewport2 *iface,
157         IUnknown *outer, REFIID iid, void **out)
158 {
159     FIXME("iface %p, outer %p, iid %s, out %p stub!\n", iface, outer, debugstr_guid(iid), out);
160 
161     return E_NOTIMPL;
162 }
163 
164 static HRESULT WINAPI d3drm_viewport1_Clone(IDirect3DRMViewport *iface,
165         IUnknown *outer, REFIID iid, void **out)
166 {
167     FIXME("iface %p, outer %p, iid %s, out %p stub!\n", iface, outer, debugstr_guid(iid), out);
168 
169     return E_NOTIMPL;
170 }
171 
172 static HRESULT WINAPI d3drm_viewport2_AddDestroyCallback(IDirect3DRMViewport2 *iface,
173         D3DRMOBJECTCALLBACK cb, void *ctx)
174 {
175     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport2(iface);
176 
177     TRACE("iface %p, cb %p, ctx %p\n", iface, cb, ctx);
178 
179     return d3drm_object_add_destroy_callback(&viewport->obj, cb, ctx);
180 }
181 
182 static HRESULT WINAPI d3drm_viewport1_AddDestroyCallback(IDirect3DRMViewport *iface,
183         D3DRMOBJECTCALLBACK cb, void *ctx)
184 {
185     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport(iface);
186 
187     TRACE("iface %p, cb %p, ctx %p\n", iface, cb, ctx);
188 
189     return d3drm_viewport2_AddDestroyCallback(&viewport->IDirect3DRMViewport2_iface, cb, ctx);
190 }
191 
192 static HRESULT WINAPI d3drm_viewport2_DeleteDestroyCallback(IDirect3DRMViewport2 *iface,
193         D3DRMOBJECTCALLBACK cb, void *ctx)
194 {
195     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport2(iface);
196 
197     TRACE("iface %p, cb %p, ctx %p\n", iface, cb, ctx);
198 
199     return d3drm_object_delete_destroy_callback(&viewport->obj, cb, ctx);
200 }
201 
202 static HRESULT WINAPI d3drm_viewport1_DeleteDestroyCallback(IDirect3DRMViewport *iface,
203         D3DRMOBJECTCALLBACK cb, void *ctx)
204 {
205     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport(iface);
206 
207     TRACE("iface %p, cb %p, ctx %p\n", iface, cb, ctx);
208 
209     return d3drm_viewport2_DeleteDestroyCallback(&viewport->IDirect3DRMViewport2_iface, cb, ctx);
210 }
211 
212 static HRESULT WINAPI d3drm_viewport2_SetAppData(IDirect3DRMViewport2 *iface, DWORD data)
213 {
214     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport2(iface);
215 
216     TRACE("iface %p, data %#x\n", iface, data);
217 
218     viewport->obj.appdata = data;
219     return S_OK;
220 }
221 
222 static HRESULT WINAPI d3drm_viewport1_SetAppData(IDirect3DRMViewport *iface, DWORD data)
223 {
224     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport(iface);
225 
226     TRACE("iface %p, data %#x\n", iface, data);
227 
228     return d3drm_viewport2_SetAppData(&viewport->IDirect3DRMViewport2_iface, data);
229 }
230 
231 static DWORD WINAPI d3drm_viewport2_GetAppData(IDirect3DRMViewport2 *iface)
232 {
233     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport2(iface);
234 
235     TRACE("iface %p\n", iface);
236 
237     return viewport->obj.appdata;
238 }
239 
240 static DWORD WINAPI d3drm_viewport1_GetAppData(IDirect3DRMViewport *iface)
241 {
242     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport(iface);
243 
244     TRACE("iface %p.\n", iface);
245 
246     return d3drm_viewport2_GetAppData(&viewport->IDirect3DRMViewport2_iface);
247 }
248 
249 static HRESULT WINAPI d3drm_viewport2_SetName(IDirect3DRMViewport2 *iface, const char *name)
250 {
251     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport2(iface);
252 
253     TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
254 
255     return d3drm_object_set_name(&viewport->obj, name);
256 }
257 
258 static HRESULT WINAPI d3drm_viewport1_SetName(IDirect3DRMViewport *iface, const char *name)
259 {
260     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport(iface);
261 
262     TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
263 
264     return d3drm_viewport2_SetName(&viewport->IDirect3DRMViewport2_iface, name);
265 }
266 
267 static HRESULT WINAPI d3drm_viewport2_GetName(IDirect3DRMViewport2 *iface, DWORD *size, char *name)
268 {
269     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport2(iface);
270 
271     TRACE("iface %p, size %p, name %p.\n", iface, size, name);
272 
273     return d3drm_object_get_name(&viewport->obj, size, name);
274 }
275 
276 static HRESULT WINAPI d3drm_viewport1_GetName(IDirect3DRMViewport *iface, DWORD *size, char *name)
277 {
278     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport(iface);
279 
280     TRACE("iface %p, size %p, name %p.\n", iface, size, name);
281 
282     return d3drm_viewport2_GetName(&viewport->IDirect3DRMViewport2_iface, size, name);
283 }
284 
285 static HRESULT WINAPI d3drm_viewport2_GetClassName(IDirect3DRMViewport2 *iface, DWORD *size, char *name)
286 {
287     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport2(iface);
288 
289     TRACE("iface %p, size %p, name %p.\n", iface, size, name);
290 
291     return d3drm_object_get_class_name(&viewport->obj, size, name);
292 }
293 
294 static HRESULT WINAPI d3drm_viewport1_GetClassName(IDirect3DRMViewport *iface, DWORD *size, char *name)
295 {
296     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport(iface);
297 
298     TRACE("iface %p, size %p, name %p.\n", iface, size, name);
299 
300     return d3drm_viewport2_GetClassName(&viewport->IDirect3DRMViewport2_iface, size, name);
301 }
302 
303 static HRESULT WINAPI d3drm_viewport2_Init(IDirect3DRMViewport2 *iface, IDirect3DRMDevice3 *device,
304         IDirect3DRMFrame3 *camera, DWORD x, DWORD y, DWORD width, DWORD height)
305 {
306     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport2(iface);
307     struct d3drm_device *device_obj = unsafe_impl_from_IDirect3DRMDevice3(device);
308     D3DVIEWPORT vp;
309     D3DVALUE scale;
310     IDirect3D *d3d1 = NULL;
311     IDirect3DDevice *d3d_device = NULL;
312     IDirect3DMaterial *material = NULL;
313     D3DMATERIALHANDLE hmat;
314     HRESULT hr = D3DRM_OK;
315 
316     TRACE("iface %p, device %p, camera %p, x %u, y %u, width %u, height %u.\n",
317             iface, device, camera, x, y, width, height);
318 
319     if (!device_obj || !camera
320             || width > device_obj->width
321             || height > device_obj->height)
322     {
323         return D3DRMERR_BADOBJECT;
324     }
325 
326     if (viewport->d3d_viewport)
327         return D3DRMERR_BADOBJECT;
328 
329     IDirect3DRM_AddRef(viewport->d3drm);
330 
331     if (FAILED(hr = IDirect3DRMDevice3_GetDirect3DDevice(device, &d3d_device)))
332         goto cleanup;
333 
334     if (FAILED(hr = IDirect3DDevice_GetDirect3D(d3d_device, &d3d1)))
335         goto cleanup;
336 
337     if (FAILED(hr = IDirect3D_CreateViewport(d3d1, &viewport->d3d_viewport, NULL)))
338         goto cleanup;
339 
340     if (FAILED(hr = IDirect3DDevice_AddViewport(d3d_device, viewport->d3d_viewport)))
341         goto cleanup;
342 
343     vp.dwSize = sizeof(vp);
344     vp.dwWidth = width;
345     vp.dwHeight = height;
346     vp.dwX = x;
347     vp.dwY = y;
348     scale = width > height ? (float)width / 2.0f : (float)height / 2.0f;
349     vp.dvScaleX = scale;
350     vp.dvScaleY = scale;
351     vp.dvMaxX = vp.dwWidth / (2.0f * vp.dvScaleX);
352     vp.dvMaxY = vp.dwHeight / (2.0f * vp.dvScaleY);
353     vp.dvMinZ = 0.0f;
354     vp.dvMaxZ = 1.0f;
355 
356     if (FAILED(hr = IDirect3DViewport_SetViewport(viewport->d3d_viewport, &vp)))
357         goto cleanup;
358 
359     if (FAILED(hr = IDirect3DRMFrame3_QueryInterface(camera, &IID_IDirect3DRMFrame, (void **)&viewport->camera)))
360         goto cleanup;
361 
362     if (FAILED(hr = IDirect3D_CreateMaterial(d3d1, &material, NULL)))
363         goto cleanup;
364 
365     if (FAILED(hr = IDirect3DMaterial_GetHandle(material, d3d_device, &hmat)))
366         goto cleanup;
367 
368     hr = IDirect3DViewport_SetBackground(viewport->d3d_viewport, hmat);
369     viewport->material = material;
370     viewport->device = device_obj;
371 
372     viewport->clip.left = -0.5f;
373     viewport->clip.top = 0.5f;
374     viewport->clip.right = 0.5f;
375     viewport->clip.bottom = -0.5f;
376     viewport->clip.front = 1.0f;
377     viewport->clip.back = 100.0f;
378 
379 cleanup:
380 
381     if (FAILED(hr))
382     {
383         if (viewport->d3d_viewport)
384         {
385             IDirect3DViewport_Release(viewport->d3d_viewport);
386             viewport->d3d_viewport = NULL;
387         }
388         if (viewport->camera)
389             IDirect3DRMFrame_Release(viewport->camera);
390         if (material)
391             IDirect3DMaterial_Release(material);
392         IDirect3DRM_Release(viewport->d3drm);
393     }
394     if (d3d_device)
395         IDirect3DDevice_Release(d3d_device);
396     if (d3d1)
397         IDirect3D_Release(d3d1);
398 
399     return hr;
400 }
401 
402 static HRESULT WINAPI d3drm_viewport1_Init(IDirect3DRMViewport *iface, IDirect3DRMDevice *device,
403         IDirect3DRMFrame *camera, DWORD x, DWORD y, DWORD width, DWORD height)
404 {
405     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport(iface);
406     struct d3drm_frame *frame = unsafe_impl_from_IDirect3DRMFrame(camera);
407     IDirect3DRMDevice3 *device3;
408     HRESULT hr;
409 
410     TRACE("iface %p, device %p, camera %p, x %u, y %u, width %u, height %u.\n",
411           iface, device, camera, x, y, width, height);
412 
413     if (!device || !frame)
414         return D3DRMERR_BADOBJECT;
415 
416     if (FAILED(hr = IDirect3DRMDevice_QueryInterface(device, &IID_IDirect3DRMDevice3, (void **)&device3)))
417         return hr;
418 
419     hr = d3drm_viewport2_Init(&viewport->IDirect3DRMViewport2_iface, device3, &frame->IDirect3DRMFrame3_iface,
420             x, y, width, height);
421     IDirect3DRMDevice3_Release(device3);
422 
423     return hr;
424 }
425 
426 static HRESULT WINAPI d3drm_viewport2_Clear(IDirect3DRMViewport2 *iface, DWORD flags)
427 {
428     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport2(iface);
429     DDSCAPS caps = { DDSCAPS_ZBUFFER };
430     HRESULT hr;
431     D3DRECT clear_rect;
432     IDirectDrawSurface *ds;
433     DWORD clear_flags = 0;
434 
435     TRACE("iface %p, flags %#x.\n", iface, flags);
436 
437     clear_rect.u1.x1 = clear_rect.u2.y1 = 0;
438     clear_rect.u3.x2 = viewport->device->width;
439     clear_rect.u4.y2 = viewport->device->height;
440 
441     if (flags & D3DRMCLEAR_TARGET)
442     {
443         clear_flags |= D3DCLEAR_TARGET;
444         d3drm_update_background_material(viewport);
445     }
446     if (flags & D3DRMCLEAR_ZBUFFER)
447     {
448         hr = IDirectDrawSurface_GetAttachedSurface(viewport->device->render_target, &caps, &ds);
449         if (SUCCEEDED(hr))
450         {
451             clear_flags |= D3DCLEAR_ZBUFFER;
452             IDirectDrawSurface_Release(ds);
453         }
454     }
455     if (flags & D3DRMCLEAR_DIRTYRECTS)
456         FIXME("Flag D3DRMCLEAR_DIRTYRECT not implemented yet.\n");
457 
458     if (FAILED(hr = IDirect3DViewport_Clear(viewport->d3d_viewport, 1, &clear_rect, clear_flags)))
459         return hr;
460 
461     return D3DRM_OK;
462 }
463 
464 static HRESULT WINAPI d3drm_viewport1_Clear(IDirect3DRMViewport *iface)
465 {
466     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport(iface);
467 
468     TRACE("iface %p.\n", iface);
469 
470     return d3drm_viewport2_Clear(&viewport->IDirect3DRMViewport2_iface, D3DRMCLEAR_ALL);
471 }
472 
473 static HRESULT WINAPI d3drm_viewport2_Render(IDirect3DRMViewport2 *iface, IDirect3DRMFrame3 *frame)
474 {
475     FIXME("iface %p, frame %p stub!\n", iface, frame);
476 
477     return D3DRM_OK;
478 }
479 
480 static HRESULT WINAPI d3drm_viewport1_Render(IDirect3DRMViewport *iface, IDirect3DRMFrame *frame)
481 {
482     FIXME("iface %p, frame %p stub!\n", iface, frame);
483 
484     return D3DRM_OK;
485 }
486 
487 static HRESULT WINAPI d3drm_viewport2_SetFront(IDirect3DRMViewport2 *iface, D3DVALUE front)
488 {
489     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport2(iface);
490 
491     TRACE("iface %p, front %.8e.\n", iface, front);
492 
493     if (!viewport->d3d_viewport)
494         return D3DRMERR_BADOBJECT;
495 
496     if (front <= 0.0f)
497         return D3DRMERR_BADVALUE;
498 
499     viewport->clip.front = front;
500 
501     return D3DRM_OK;
502 }
503 
504 static HRESULT WINAPI d3drm_viewport1_SetFront(IDirect3DRMViewport *iface, D3DVALUE front)
505 {
506     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport(iface);
507 
508     TRACE("iface %p, front %.8e.\n", iface, front);
509 
510     return d3drm_viewport2_SetFront(&viewport->IDirect3DRMViewport2_iface, front);
511 }
512 
513 static HRESULT WINAPI d3drm_viewport2_SetBack(IDirect3DRMViewport2 *iface, D3DVALUE back)
514 {
515     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport2(iface);
516 
517     TRACE("iface %p, back %.8e.\n", iface, back);
518 
519     if (!viewport->d3d_viewport)
520         return D3DRMERR_BADOBJECT;
521 
522     if (back <= viewport->clip.front)
523         return D3DRMERR_BADVALUE;
524 
525     viewport->clip.back = back;
526 
527     return D3DRM_OK;
528 }
529 
530 static HRESULT WINAPI d3drm_viewport1_SetBack(IDirect3DRMViewport *iface, D3DVALUE back)
531 {
532     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport(iface);
533 
534     TRACE("iface %p, back %.8e.\n", iface, back);
535 
536     return d3drm_viewport2_SetBack(&viewport->IDirect3DRMViewport2_iface, back);
537 }
538 
539 static HRESULT WINAPI d3drm_viewport2_SetField(IDirect3DRMViewport2 *iface, D3DVALUE field)
540 {
541     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport2(iface);
542 
543     TRACE("iface %p, field %.8e.\n", iface, field);
544 
545     if (!viewport->d3d_viewport)
546         return D3DRMERR_BADOBJECT;
547 
548     if (field <= 0.0f)
549         return D3DRMERR_BADVALUE;
550 
551     viewport->clip.left = -field;
552     viewport->clip.right = field;
553     viewport->clip.bottom = -field;
554     viewport->clip.top = field;
555 
556     return D3DRM_OK;
557 }
558 
559 static HRESULT WINAPI d3drm_viewport1_SetField(IDirect3DRMViewport *iface, D3DVALUE field)
560 {
561     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport(iface);
562 
563     TRACE("iface %p, field %.8e.\n", iface, field);
564 
565     return d3drm_viewport2_SetField(&viewport->IDirect3DRMViewport2_iface, field);
566 }
567 
568 static HRESULT WINAPI d3drm_viewport2_SetUniformScaling(IDirect3DRMViewport2 *iface, BOOL b)
569 {
570     FIXME("iface %p, b %#x stub!\n", iface, b);
571 
572     return E_NOTIMPL;
573 }
574 
575 static HRESULT WINAPI d3drm_viewport1_SetUniformScaling(IDirect3DRMViewport *iface, BOOL b)
576 {
577     FIXME("iface %p, b %#x stub!\n", iface, b);
578 
579     return E_NOTIMPL;
580 }
581 
582 static HRESULT WINAPI d3drm_viewport2_SetCamera(IDirect3DRMViewport2 *iface, IDirect3DRMFrame3 *camera)
583 {
584     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport2(iface);
585     struct d3drm_frame *frame = unsafe_impl_from_IDirect3DRMFrame3(camera);
586 
587     TRACE("iface %p, camera %p.\n", iface, camera);
588 
589     if (!camera || !viewport->camera)
590         return D3DRMERR_BADOBJECT;
591 
592     IDirect3DRMFrame_AddRef(&frame->IDirect3DRMFrame_iface);
593     IDirect3DRMFrame_Release(viewport->camera);
594     viewport->camera = &frame->IDirect3DRMFrame_iface;
595 
596     return D3DRM_OK;
597 }
598 
599 static HRESULT WINAPI d3drm_viewport1_SetCamera(IDirect3DRMViewport *iface, IDirect3DRMFrame *camera)
600 {
601     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport(iface);
602     struct d3drm_frame *frame = unsafe_impl_from_IDirect3DRMFrame(camera);
603 
604     TRACE("iface %p, camera %p.\n", iface, camera);
605 
606     return d3drm_viewport2_SetCamera(&viewport->IDirect3DRMViewport2_iface,
607             frame ? &frame->IDirect3DRMFrame3_iface : NULL);
608 }
609 
610 static HRESULT WINAPI d3drm_viewport2_SetProjection(IDirect3DRMViewport2 *iface, D3DRMPROJECTIONTYPE type)
611 {
612     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport2(iface);
613 
614     TRACE("iface %p, type %#x.\n", iface, type);
615 
616     viewport->projection = type;
617 
618     return D3DRM_OK;
619 }
620 
621 static HRESULT WINAPI d3drm_viewport1_SetProjection(IDirect3DRMViewport *iface, D3DRMPROJECTIONTYPE type)
622 {
623     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport(iface);
624 
625     TRACE("iface %p, type %#x.\n", iface, type);
626 
627     return d3drm_viewport2_SetProjection(&viewport->IDirect3DRMViewport2_iface, type);
628 }
629 
630 static HRESULT WINAPI d3drm_viewport2_Transform(IDirect3DRMViewport2 *iface, D3DRMVECTOR4D *d, D3DVECTOR *s)
631 {
632     FIXME("iface %p, d %p, s %p stub!\n", iface, d, s);
633 
634     return E_NOTIMPL;
635 }
636 
637 static HRESULT WINAPI d3drm_viewport1_Transform(IDirect3DRMViewport *iface, D3DRMVECTOR4D *d, D3DVECTOR *s)
638 {
639     FIXME("iface %p, d %p, s %p stub!\n", iface, d, s);
640 
641     return E_NOTIMPL;
642 }
643 
644 static HRESULT WINAPI d3drm_viewport2_InverseTransform(IDirect3DRMViewport2 *iface, D3DVECTOR *d, D3DRMVECTOR4D *s)
645 {
646     FIXME("iface %p, d %p, s %p stub!\n", iface, d, s);
647 
648     return E_NOTIMPL;
649 }
650 
651 static HRESULT WINAPI d3drm_viewport1_InverseTransform(IDirect3DRMViewport *iface, D3DVECTOR *d, D3DRMVECTOR4D *s)
652 {
653     FIXME("iface %p, d %p, s %p stub!\n", iface, d, s);
654 
655     return E_NOTIMPL;
656 }
657 
658 static HRESULT WINAPI d3drm_viewport2_Configure(IDirect3DRMViewport2 *iface,
659         LONG x, LONG y, DWORD width, DWORD height)
660 {
661     FIXME("iface %p, x %d, y %d, width %u, height %u stub!\n", iface, x, y, width, height);
662 
663     return E_NOTIMPL;
664 }
665 
666 static HRESULT WINAPI d3drm_viewport1_Configure(IDirect3DRMViewport *iface,
667         LONG x, LONG y, DWORD width, DWORD height)
668 {
669     FIXME("iface %p, x %d, y %d, width %u, height %u stub!\n", iface, x, y, width, height);
670 
671     return E_NOTIMPL;
672 }
673 
674 static HRESULT WINAPI d3drm_viewport2_ForceUpdate(IDirect3DRMViewport2* iface,
675         DWORD x1, DWORD y1, DWORD x2, DWORD y2)
676 {
677     FIXME("iface %p, x1 %u, y1 %u, x2 %u, y2 %u stub!\n", iface, x1, y1, x2, y2);
678 
679     return E_NOTIMPL;
680 }
681 
682 static HRESULT WINAPI d3drm_viewport1_ForceUpdate(IDirect3DRMViewport *iface,
683         DWORD x1, DWORD y1, DWORD x2, DWORD y2)
684 {
685     FIXME("iface %p, x1 %u, y1 %u, x2 %u, y2 %u stub!\n", iface, x1, y1, x2, y2);
686 
687     return E_NOTIMPL;
688 }
689 
690 static HRESULT WINAPI d3drm_viewport2_SetPlane(IDirect3DRMViewport2 *iface,
691         D3DVALUE left, D3DVALUE right, D3DVALUE bottom, D3DVALUE top)
692 {
693     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport2(iface);
694 
695     TRACE("iface %p, left %.8e, right %.8e, bottom %.8e, top %.8e.\n",
696             iface, left, right, bottom, top);
697 
698     if (!viewport->d3d_viewport)
699         return D3DRMERR_BADOBJECT;
700 
701     viewport->clip.left = left;
702     viewport->clip.right = right;
703     viewport->clip.bottom = bottom;
704     viewport->clip.top = top;
705 
706     return D3DRM_OK;
707 }
708 
709 static HRESULT WINAPI d3drm_viewport1_SetPlane(IDirect3DRMViewport *iface,
710         D3DVALUE left, D3DVALUE right, D3DVALUE bottom, D3DVALUE top)
711 {
712     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport(iface);
713 
714     TRACE("iface %p, left %.8e, right %.8e, bottom %.8e, top %.8e.\n",
715             iface, left, right, bottom, top);
716 
717     return d3drm_viewport2_SetPlane(&viewport->IDirect3DRMViewport2_iface, left, right, bottom, top);
718 }
719 
720 static HRESULT WINAPI d3drm_viewport2_GetCamera(IDirect3DRMViewport2 *iface, IDirect3DRMFrame3 **camera)
721 {
722     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport2(iface);
723 
724     TRACE("iface %p, camera %p.\n", iface, camera);
725 
726     if (!camera)
727         return D3DRMERR_BADVALUE;
728 
729     if (!viewport->camera)
730         return D3DRMERR_BADOBJECT;
731 
732     return IDirect3DRMFrame_QueryInterface(viewport->camera, &IID_IDirect3DRMFrame3, (void **)camera);
733 }
734 
735 static HRESULT WINAPI d3drm_viewport1_GetCamera(IDirect3DRMViewport *iface, IDirect3DRMFrame **camera)
736 {
737     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport(iface);
738     struct d3drm_frame *camera_impl;
739     IDirect3DRMFrame3 *camera3;
740     HRESULT hr;
741 
742     TRACE("iface %p, camera %p.\n", iface, camera);
743 
744     if (!camera)
745         return D3DRMERR_BADVALUE;
746 
747     if (FAILED(hr = d3drm_viewport2_GetCamera(&viewport->IDirect3DRMViewport2_iface, &camera3)))
748         return hr;
749 
750     camera_impl = unsafe_impl_from_IDirect3DRMFrame3(camera3);
751     *camera = &camera_impl->IDirect3DRMFrame_iface;
752 
753     return D3DRM_OK;
754 }
755 
756 static HRESULT WINAPI d3drm_viewport2_GetDevice(IDirect3DRMViewport2 *iface, IDirect3DRMDevice3 **device)
757 {
758     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport2(iface);
759 
760     TRACE("iface %p, device %p.\n", iface, device);
761 
762     if (!device)
763         return D3DRMERR_BADVALUE;
764 
765     if (!viewport->device)
766         return D3DRMERR_BADOBJECT;
767 
768     *device = &viewport->device->IDirect3DRMDevice3_iface;
769     IDirect3DRMDevice3_AddRef(*device);
770 
771     return D3DRM_OK;
772 }
773 
774 static HRESULT WINAPI d3drm_viewport1_GetDevice(IDirect3DRMViewport *iface, IDirect3DRMDevice **device)
775 {
776     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport(iface);
777 
778     TRACE("iface %p, device %p.\n\n", iface, device);
779 
780     if (!device)
781         return D3DRMERR_BADVALUE;
782 
783     if (!viewport->device)
784         return D3DRMERR_BADOBJECT;
785 
786     *device = &viewport->device->IDirect3DRMDevice_iface;
787     IDirect3DRMDevice_AddRef(*device);
788 
789     return D3DRM_OK;
790 }
791 
792 static HRESULT WINAPI d3drm_viewport2_GetPlane(IDirect3DRMViewport2 *iface,
793         D3DVALUE *left, D3DVALUE *right, D3DVALUE *bottom, D3DVALUE *top)
794 {
795     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport2(iface);
796 
797     TRACE("iface %p, left %p, right %p, bottom %p, top %p.\n",
798             iface, left, right, bottom, top);
799 
800     if (!viewport->d3d_viewport)
801         return D3DRMERR_BADOBJECT;
802 
803     *left = viewport->clip.left;
804     *right = viewport->clip.right;
805     *bottom = viewport->clip.bottom;
806     *top = viewport->clip.top;
807 
808     return D3DRM_OK;
809 }
810 
811 static HRESULT WINAPI d3drm_viewport1_GetPlane(IDirect3DRMViewport *iface,
812         D3DVALUE *left, D3DVALUE *right, D3DVALUE *bottom, D3DVALUE *top)
813 {
814     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport(iface);
815 
816     TRACE("iface %p, left %p, right %p, bottom %p, top %p.\n",
817             iface, left, right, bottom, top);
818 
819     return d3drm_viewport2_GetPlane(&viewport->IDirect3DRMViewport2_iface, left, right, bottom, top);
820 }
821 
822 static HRESULT WINAPI d3drm_viewport2_Pick(IDirect3DRMViewport2 *iface,
823         LONG x, LONG y, IDirect3DRMPickedArray **visuals)
824 {
825     FIXME("iface %p, x %d, y %d, visuals %p stub!\n", iface, x, y, visuals);
826 
827     return E_NOTIMPL;
828 }
829 
830 static HRESULT WINAPI d3drm_viewport1_Pick(IDirect3DRMViewport *iface,
831         LONG x, LONG y, IDirect3DRMPickedArray **visuals)
832 {
833     FIXME("iface %p, x %d, y %d, visuals %p stub!\n", iface, x, y, visuals);
834 
835     return E_NOTIMPL;
836 }
837 
838 static BOOL WINAPI d3drm_viewport2_GetUniformScaling(IDirect3DRMViewport2 *iface)
839 {
840     FIXME("iface %p stub!\n", iface);
841 
842     return FALSE;
843 }
844 
845 static BOOL WINAPI d3drm_viewport1_GetUniformScaling(IDirect3DRMViewport *iface)
846 {
847     FIXME("iface %p stub!\n", iface);
848 
849     return FALSE;
850 }
851 
852 static LONG WINAPI d3drm_viewport2_GetX(IDirect3DRMViewport2 *iface)
853 {
854     FIXME("iface %p stub!\n", iface);
855 
856     return E_NOTIMPL;
857 }
858 
859 static LONG WINAPI d3drm_viewport1_GetX(IDirect3DRMViewport *iface)
860 {
861     FIXME("iface %p stub!\n", iface);
862 
863     return E_NOTIMPL;
864 }
865 
866 static LONG WINAPI d3drm_viewport2_GetY(IDirect3DRMViewport2 *iface)
867 {
868     FIXME("iface %p stub!\n", iface);
869 
870     return E_NOTIMPL;
871 }
872 
873 static LONG WINAPI d3drm_viewport1_GetY(IDirect3DRMViewport *iface)
874 {
875     FIXME("iface %p stub!\n", iface);
876 
877     return E_NOTIMPL;
878 }
879 
880 static DWORD WINAPI d3drm_viewport2_GetWidth(IDirect3DRMViewport2 *iface)
881 {
882     FIXME("iface %p stub!\n", iface);
883 
884     return E_NOTIMPL;
885 }
886 
887 static DWORD WINAPI d3drm_viewport1_GetWidth(IDirect3DRMViewport *iface)
888 {
889     FIXME("iface %p stub!\n", iface);
890 
891     return E_NOTIMPL;
892 }
893 
894 static DWORD WINAPI d3drm_viewport2_GetHeight(IDirect3DRMViewport2 *iface)
895 {
896     FIXME("iface %p stub!\n", iface);
897 
898     return E_NOTIMPL;
899 }
900 
901 static DWORD WINAPI d3drm_viewport1_GetHeight(IDirect3DRMViewport *iface)
902 {
903     FIXME("iface %p stub!\n", iface);
904 
905     return E_NOTIMPL;
906 }
907 
908 static D3DVALUE WINAPI d3drm_viewport2_GetField(IDirect3DRMViewport2 *iface)
909 {
910     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport2(iface);
911 
912     TRACE("iface %p.\n", iface);
913 
914     if (!viewport->d3d_viewport)
915         return -1.0f;
916 
917     return (viewport->clip.right - viewport->clip.left
918             + viewport->clip.top - viewport->clip.bottom) / 4.0f;
919 }
920 
921 static D3DVALUE WINAPI d3drm_viewport1_GetField(IDirect3DRMViewport *iface)
922 {
923     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport(iface);
924 
925     TRACE("iface %p.\n", iface);
926 
927     return d3drm_viewport2_GetField(&viewport->IDirect3DRMViewport2_iface);
928 }
929 
930 static D3DVALUE WINAPI d3drm_viewport2_GetBack(IDirect3DRMViewport2 *iface)
931 {
932     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport2(iface);
933 
934     TRACE("iface %p.\n", iface);
935 
936     if (!viewport->d3d_viewport)
937         return -1.0f;
938 
939     return viewport->clip.back;
940 }
941 
942 static D3DVALUE WINAPI d3drm_viewport1_GetBack(IDirect3DRMViewport *iface)
943 {
944     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport(iface);
945 
946     TRACE("iface %p.\n", iface);
947 
948     return d3drm_viewport2_GetBack(&viewport->IDirect3DRMViewport2_iface);
949 }
950 
951 static D3DVALUE WINAPI d3drm_viewport2_GetFront(IDirect3DRMViewport2 *iface)
952 {
953     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport2(iface);
954 
955     TRACE("iface %p.\n", iface);
956 
957     if (!viewport->d3d_viewport)
958         return -1.0f;
959 
960     return viewport->clip.front;
961 }
962 
963 static D3DVALUE WINAPI d3drm_viewport1_GetFront(IDirect3DRMViewport *iface)
964 {
965     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport(iface);
966 
967     TRACE("iface %p.\n", iface);
968 
969     return d3drm_viewport2_GetFront(&viewport->IDirect3DRMViewport2_iface);
970 }
971 
972 static D3DRMPROJECTIONTYPE WINAPI d3drm_viewport2_GetProjection(IDirect3DRMViewport2 *iface)
973 {
974     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport2(iface);
975 
976     TRACE("iface %p.\n", iface);
977 
978     return viewport->projection;
979 }
980 
981 static D3DRMPROJECTIONTYPE WINAPI d3drm_viewport1_GetProjection(IDirect3DRMViewport *iface)
982 {
983     struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport(iface);
984 
985     TRACE("iface %p.\n", iface);
986 
987     return d3drm_viewport2_GetProjection(&viewport->IDirect3DRMViewport2_iface);
988 }
989 
990 static HRESULT WINAPI d3drm_viewport2_GetDirect3DViewport(IDirect3DRMViewport2 *iface,
991         IDirect3DViewport **viewport)
992 {
993     struct d3drm_viewport *viewport_object = impl_from_IDirect3DRMViewport2(iface);
994 
995     TRACE("iface %p, viewport %p.\n", iface, viewport);
996 
997     if (!viewport)
998         return D3DRMERR_BADVALUE;
999 
1000     if (!viewport_object->d3d_viewport)
1001         return D3DRMERR_BADOBJECT;
1002 
1003     *viewport = viewport_object->d3d_viewport;
1004     IDirect3DViewport_AddRef(*viewport);
1005 
1006     return D3DRM_OK;
1007 }
1008 
1009 static HRESULT WINAPI d3drm_viewport1_GetDirect3DViewport(IDirect3DRMViewport *iface,
1010         IDirect3DViewport **viewport)
1011 {
1012     struct d3drm_viewport *viewport_object = impl_from_IDirect3DRMViewport(iface);
1013 
1014     TRACE("iface %p, viewport %p.\n", iface, viewport);
1015 
1016     return d3drm_viewport2_GetDirect3DViewport(&viewport_object->IDirect3DRMViewport2_iface, viewport);
1017 }
1018 
1019 static HRESULT WINAPI d3drm_viewport2_TransformVectors(IDirect3DRMViewport2 *iface,
1020         DWORD vector_count, D3DRMVECTOR4D *dst, D3DVECTOR *src)
1021 {
1022     FIXME("iface %p, vector_count %u, dst %p, src %p stub!\n", iface, vector_count, dst, src);
1023 
1024     return E_NOTIMPL;
1025 }
1026 
1027 static HRESULT WINAPI d3drm_viewport2_InverseTransformVectors(IDirect3DRMViewport2 *iface,
1028         DWORD vector_count, D3DVECTOR *dst, D3DRMVECTOR4D *src)
1029 {
1030     FIXME("iface %p, vector_count %u, dst %p, src %p stub!\n", iface, vector_count, dst, src);
1031 
1032     return E_NOTIMPL;
1033 }
1034 
1035 static const struct IDirect3DRMViewport2Vtbl d3drm_viewport2_vtbl =
1036 {
1037     d3drm_viewport2_QueryInterface,
1038     d3drm_viewport2_AddRef,
1039     d3drm_viewport2_Release,
1040     d3drm_viewport2_Clone,
1041     d3drm_viewport2_AddDestroyCallback,
1042     d3drm_viewport2_DeleteDestroyCallback,
1043     d3drm_viewport2_SetAppData,
1044     d3drm_viewport2_GetAppData,
1045     d3drm_viewport2_SetName,
1046     d3drm_viewport2_GetName,
1047     d3drm_viewport2_GetClassName,
1048     d3drm_viewport2_Init,
1049     d3drm_viewport2_Clear,
1050     d3drm_viewport2_Render,
1051     d3drm_viewport2_SetFront,
1052     d3drm_viewport2_SetBack,
1053     d3drm_viewport2_SetField,
1054     d3drm_viewport2_SetUniformScaling,
1055     d3drm_viewport2_SetCamera,
1056     d3drm_viewport2_SetProjection,
1057     d3drm_viewport2_Transform,
1058     d3drm_viewport2_InverseTransform,
1059     d3drm_viewport2_Configure,
1060     d3drm_viewport2_ForceUpdate,
1061     d3drm_viewport2_SetPlane,
1062     d3drm_viewport2_GetCamera,
1063     d3drm_viewport2_GetDevice,
1064     d3drm_viewport2_GetPlane,
1065     d3drm_viewport2_Pick,
1066     d3drm_viewport2_GetUniformScaling,
1067     d3drm_viewport2_GetX,
1068     d3drm_viewport2_GetY,
1069     d3drm_viewport2_GetWidth,
1070     d3drm_viewport2_GetHeight,
1071     d3drm_viewport2_GetField,
1072     d3drm_viewport2_GetBack,
1073     d3drm_viewport2_GetFront,
1074     d3drm_viewport2_GetProjection,
1075     d3drm_viewport2_GetDirect3DViewport,
1076     d3drm_viewport2_TransformVectors,
1077     d3drm_viewport2_InverseTransformVectors,
1078 };
1079 
1080 static const struct IDirect3DRMViewportVtbl d3drm_viewport1_vtbl =
1081 {
1082     d3drm_viewport1_QueryInterface,
1083     d3drm_viewport1_AddRef,
1084     d3drm_viewport1_Release,
1085     d3drm_viewport1_Clone,
1086     d3drm_viewport1_AddDestroyCallback,
1087     d3drm_viewport1_DeleteDestroyCallback,
1088     d3drm_viewport1_SetAppData,
1089     d3drm_viewport1_GetAppData,
1090     d3drm_viewport1_SetName,
1091     d3drm_viewport1_GetName,
1092     d3drm_viewport1_GetClassName,
1093     d3drm_viewport1_Init,
1094     d3drm_viewport1_Clear,
1095     d3drm_viewport1_Render,
1096     d3drm_viewport1_SetFront,
1097     d3drm_viewport1_SetBack,
1098     d3drm_viewport1_SetField,
1099     d3drm_viewport1_SetUniformScaling,
1100     d3drm_viewport1_SetCamera,
1101     d3drm_viewport1_SetProjection,
1102     d3drm_viewport1_Transform,
1103     d3drm_viewport1_InverseTransform,
1104     d3drm_viewport1_Configure,
1105     d3drm_viewport1_ForceUpdate,
1106     d3drm_viewport1_SetPlane,
1107     d3drm_viewport1_GetCamera,
1108     d3drm_viewport1_GetDevice,
1109     d3drm_viewport1_GetPlane,
1110     d3drm_viewport1_Pick,
1111     d3drm_viewport1_GetUniformScaling,
1112     d3drm_viewport1_GetX,
1113     d3drm_viewport1_GetY,
1114     d3drm_viewport1_GetWidth,
1115     d3drm_viewport1_GetHeight,
1116     d3drm_viewport1_GetField,
1117     d3drm_viewport1_GetBack,
1118     d3drm_viewport1_GetFront,
1119     d3drm_viewport1_GetProjection,
1120     d3drm_viewport1_GetDirect3DViewport,
1121 };
1122 
1123 HRESULT d3drm_viewport_create(struct d3drm_viewport **viewport, IDirect3DRM *d3drm)
1124 {
1125     static const char classname[] = "Viewport";
1126     struct d3drm_viewport *object;
1127 
1128     TRACE("viewport %p, d3drm %p.\n", viewport, d3drm);
1129 
1130     if (!(object = heap_alloc_zero(sizeof(*object))))
1131         return E_OUTOFMEMORY;
1132 
1133     object->IDirect3DRMViewport_iface.lpVtbl = &d3drm_viewport1_vtbl;
1134     object->IDirect3DRMViewport2_iface.lpVtbl = &d3drm_viewport2_vtbl;
1135     object->d3drm = d3drm;
1136     d3drm_object_init(&object->obj, classname);
1137 
1138     *viewport = object;
1139 
1140     return S_OK;
1141 }
1142