2 * Copyright (c) 1998 Lionel ULMER
4 * This file contains the implementation of Direct3DViewport2.
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.
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.
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
25 #define NONAMELESSUNION
26 #define NONAMELESSSTRUCT
35 #include "wine/debug.h"
37 #include "d3d_private.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
41 static void activate(IDirect3DViewportImpl* This) {
42 IDirect3DLightImpl* light;
45 /* Activate all the lights associated with this context */
48 while (light != NULL) {
49 light->activate(light);
53 /* And copy the values in the structure used by the device */
55 vp.dwX = This->viewports.vp2.dwX;
56 vp.dwY = This->viewports.vp2.dwY;
57 vp.dwHeight = This->viewports.vp2.dwHeight;
58 vp.dwWidth = This->viewports.vp2.dwWidth;
59 vp.dvMinZ = This->viewports.vp2.dvMinZ;
60 vp.dvMaxZ = This->viewports.vp2.dvMaxZ;
62 vp.dwX = This->viewports.vp1.dwX;
63 vp.dwY = This->viewports.vp1.dwY;
64 vp.dwHeight = This->viewports.vp1.dwHeight;
65 vp.dwWidth = This->viewports.vp1.dwWidth;
66 vp.dvMinZ = This->viewports.vp1.dvMinZ;
67 vp.dvMaxZ = This->viewports.vp1.dvMaxZ;
70 /* And also set the viewport */
71 IDirect3DDevice7_SetViewport(ICOM_INTERFACE(This->active_device, IDirect3DDevice7), &vp);
75 static void _dump_D3DVIEWPORT(D3DVIEWPORT *lpvp)
77 TRACE(" - dwSize = %ld dwX = %ld dwY = %ld\n",
78 lpvp->dwSize, lpvp->dwX, lpvp->dwY);
79 TRACE(" - dwWidth = %ld dwHeight = %ld\n",
80 lpvp->dwWidth, lpvp->dwHeight);
81 TRACE(" - dvScaleX = %f dvScaleY = %f\n",
82 lpvp->dvScaleX, lpvp->dvScaleY);
83 TRACE(" - dvMaxX = %f dvMaxY = %f\n",
84 lpvp->dvMaxX, lpvp->dvMaxY);
85 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
86 lpvp->dvMinZ, lpvp->dvMaxZ);
89 static void _dump_D3DVIEWPORT2(D3DVIEWPORT2 *lpvp)
91 TRACE(" - dwSize = %ld dwX = %ld dwY = %ld\n",
92 lpvp->dwSize, lpvp->dwX, lpvp->dwY);
93 TRACE(" - dwWidth = %ld dwHeight = %ld\n",
94 lpvp->dwWidth, lpvp->dwHeight);
95 TRACE(" - dvClipX = %f dvClipY = %f\n",
96 lpvp->dvClipX, lpvp->dvClipY);
97 TRACE(" - dvClipWidth = %f dvClipHeight = %f\n",
98 lpvp->dvClipWidth, lpvp->dvClipHeight);
99 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
100 lpvp->dvMinZ, lpvp->dvMaxZ);
104 Main_IDirect3DViewportImpl_3_2_1_QueryInterface(LPDIRECT3DVIEWPORT3 iface,
108 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
109 TRACE("(%p/%p)->(%s,%p)\n", This, iface, debugstr_guid(riid), obp);
113 if ( IsEqualGUID(&IID_IUnknown, riid) ||
114 IsEqualGUID(&IID_IDirect3DViewport, riid) ||
115 IsEqualGUID(&IID_IDirect3DViewport2, riid) ||
116 IsEqualGUID(&IID_IDirect3DViewport3, riid) ) {
117 IDirect3DViewport3_AddRef(ICOM_INTERFACE(This, IDirect3DViewport3));
118 *obp = ICOM_INTERFACE(This, IDirect3DViewport3);
119 TRACE(" Creating IDirect3DViewport1/2/3 interface %p\n", *obp);
122 FIXME("(%p): interface for IID %s NOT found!\n", This, debugstr_guid(riid));
123 return OLE_E_ENUM_NOMORE;
127 Main_IDirect3DViewportImpl_3_2_1_AddRef(LPDIRECT3DVIEWPORT3 iface)
129 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
130 ULONG ref = InterlockedIncrement(&This->ref);
132 TRACE("(%p/%p)->() incrementing from %lu.\n", This, iface, ref - 1);
138 Main_IDirect3DViewportImpl_3_2_1_Release(LPDIRECT3DVIEWPORT3 iface)
140 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
141 ULONG ref = InterlockedDecrement(&This->ref);
143 TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, ref + 1);
146 HeapFree(GetProcessHeap(), 0, This);
154 Main_IDirect3DViewportImpl_3_2_1_Initialize(LPDIRECT3DVIEWPORT3 iface,
155 LPDIRECT3D lpDirect3D)
157 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
158 TRACE("(%p/%p)->(%p) no-op...\n", This, iface, lpDirect3D);
163 Main_IDirect3DViewportImpl_3_2_1_GetViewport(LPDIRECT3DVIEWPORT3 iface,
164 LPD3DVIEWPORT lpData)
166 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
168 TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
169 if (This->use_vp2 != 0) {
170 ERR(" Requesting to get a D3DVIEWPORT struct where a D3DVIEWPORT2 was set !\n");
171 return DDERR_INVALIDPARAMS;
173 dwSize = lpData->dwSize;
174 memset(lpData, 0, dwSize);
175 memcpy(lpData, &(This->viewports.vp1), dwSize);
177 if (TRACE_ON(ddraw)) {
178 TRACE(" returning D3DVIEWPORT :\n");
179 _dump_D3DVIEWPORT(lpData);
186 Main_IDirect3DViewportImpl_3_2_1_SetViewport(LPDIRECT3DVIEWPORT3 iface,
187 LPD3DVIEWPORT lpData)
189 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
190 LPDIRECT3DVIEWPORT3 current_viewport;
191 TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
193 if (TRACE_ON(ddraw)) {
194 TRACE(" getting D3DVIEWPORT :\n");
195 _dump_D3DVIEWPORT(lpData);
199 memset(&(This->viewports.vp1), 0, sizeof(This->viewports.vp1));
200 memcpy(&(This->viewports.vp1), lpData, lpData->dwSize);
202 /* Tests on two games show that these values are never used properly so override
203 them with proper ones :-)
205 This->viewports.vp1.dvMinZ = 0.0;
206 This->viewports.vp1.dvMaxZ = 1.0;
208 if (This->active_device) {
209 IDirect3DDevice3_GetCurrentViewport(ICOM_INTERFACE(This->active_device, IDirect3DDevice3), ¤t_viewport);
210 if (ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, current_viewport) == This)
211 This->activate(This);
212 IDirect3DViewport3_Release(current_viewport);
219 Main_IDirect3DViewportImpl_3_2_1_TransformVertices(LPDIRECT3DVIEWPORT3 iface,
221 LPD3DTRANSFORMDATA lpData,
225 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
226 FIXME("(%p/%p)->(%08lx,%p,%08lx,%p): stub!\n", This, iface, dwVertexCount, lpData, dwFlags, lpOffScreen);
233 Main_IDirect3DViewportImpl_3_2_1_LightElements(LPDIRECT3DVIEWPORT3 iface,
234 DWORD dwElementCount,
235 LPD3DLIGHTDATA lpData)
237 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
238 FIXME("(%p/%p)->(%08lx,%p): stub!\n", This, iface, dwElementCount, lpData);
243 Main_IDirect3DViewportImpl_3_2_1_SetBackground(LPDIRECT3DVIEWPORT3 iface,
244 D3DMATERIALHANDLE hMat)
246 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
247 TRACE("(%p/%p)->(%08lx)\n", This, iface, (DWORD) hMat);
249 This->background = (IDirect3DMaterialImpl *) hMat;
250 TRACE(" setting background color : %f %f %f %f\n",
251 This->background->mat.u.diffuse.u1.r,
252 This->background->mat.u.diffuse.u2.g,
253 This->background->mat.u.diffuse.u3.b,
254 This->background->mat.u.diffuse.u4.a);
260 Main_IDirect3DViewportImpl_3_2_1_GetBackground(LPDIRECT3DVIEWPORT3 iface,
261 LPD3DMATERIALHANDLE lphMat,
264 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
265 FIXME("(%p/%p)->(%p,%p): stub!\n", This, iface, lphMat, lpValid);
270 Main_IDirect3DViewportImpl_3_2_1_SetBackgroundDepth(LPDIRECT3DVIEWPORT3 iface,
271 LPDIRECTDRAWSURFACE lpDDSurface)
273 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
274 FIXME("(%p/%p)->(%p): stub!\n", This, iface, lpDDSurface);
279 Main_IDirect3DViewportImpl_3_2_1_GetBackgroundDepth(LPDIRECT3DVIEWPORT3 iface,
280 LPDIRECTDRAWSURFACE* lplpDDSurface,
283 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
284 FIXME("(%p/%p)->(%p,%p): stub!\n", This, iface, lplpDDSurface, lpValid);
289 Main_IDirect3DViewportImpl_3_2_1_Clear(LPDIRECT3DVIEWPORT3 iface,
294 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
295 DWORD color = 0x00000000;
297 TRACE("(%p/%p)->(%08lx,%p,%08lx)\n", This, iface, dwCount, lpRects, dwFlags);
298 if (This->active_device == NULL) {
299 ERR(" Trying to clear a viewport not attached to a device !\n");
300 return D3DERR_VIEWPORTHASNODEVICE;
302 if (dwFlags & D3DCLEAR_TARGET) {
303 if (This->background == NULL) {
304 ERR(" Trying to clear the color buffer without background material !\n");
307 ((int) ((This->background->mat.u.diffuse.u1.r) * 255) << 16) |
308 ((int) ((This->background->mat.u.diffuse.u2.g) * 255) << 8) |
309 ((int) ((This->background->mat.u.diffuse.u3.b) * 255) << 0) |
310 ((int) ((This->background->mat.u.diffuse.u4.a) * 255) << 24);
313 return This->active_device->clear(This->active_device, dwCount, lpRects,
314 dwFlags & (D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET),
315 color, 1.0, 0x00000000);
319 Main_IDirect3DViewportImpl_3_2_1_AddLight(LPDIRECT3DVIEWPORT3 iface,
320 LPDIRECT3DLIGHT lpDirect3DLight)
322 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
323 IDirect3DLightImpl *lpDirect3DLightImpl = ICOM_OBJECT(IDirect3DLightImpl, IDirect3DLight, lpDirect3DLight);
325 DWORD map = This->map_lights;
327 TRACE("(%p/%p)->(%p)\n", This, iface, lpDirect3DLight);
329 if (This->num_lights >= 8)
330 return DDERR_INVALIDPARAMS;
332 /* Find a light number and update both light and viewports objects accordingly */
337 lpDirect3DLightImpl->dwLightIndex = i;
339 This->map_lights |= 1<<i;
341 /* Add the light in the 'linked' chain */
342 lpDirect3DLightImpl->next = This->lights;
343 This->lights = lpDirect3DLightImpl;
345 /* Attach the light to the viewport */
346 lpDirect3DLightImpl->active_viewport = This;
348 /* If active, activate the light */
349 if (This->active_device != NULL) {
350 lpDirect3DLightImpl->activate(lpDirect3DLightImpl);
357 Main_IDirect3DViewportImpl_3_2_1_DeleteLight(LPDIRECT3DVIEWPORT3 iface,
358 LPDIRECT3DLIGHT lpDirect3DLight)
360 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
361 IDirect3DLightImpl *lpDirect3DLightImpl = ICOM_OBJECT(IDirect3DLightImpl, IDirect3DLight, lpDirect3DLight);
362 IDirect3DLightImpl *cur_light, *prev_light = NULL;
364 TRACE("(%p/%p)->(%p)\n", This, iface, lpDirect3DLight);
365 cur_light = This->lights;
366 while (cur_light != NULL) {
367 if (cur_light == lpDirect3DLightImpl) {
368 lpDirect3DLightImpl->desactivate(lpDirect3DLightImpl);
369 if (prev_light == NULL) This->lights = cur_light->next;
370 else prev_light->next = cur_light->next;
371 /* Detach the light to the viewport */
372 cur_light->active_viewport = NULL;
374 This->map_lights &= ~(1<<lpDirect3DLightImpl->dwLightIndex);
377 prev_light = cur_light;
378 cur_light = cur_light->next;
380 return DDERR_INVALIDPARAMS;
384 Main_IDirect3DViewportImpl_3_2_1_NextLight(LPDIRECT3DVIEWPORT3 iface,
385 LPDIRECT3DLIGHT lpDirect3DLight,
386 LPDIRECT3DLIGHT* lplpDirect3DLight,
389 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
390 FIXME("(%p/%p)->(%p,%p,%08lx): stub!\n", This, iface, lpDirect3DLight, lplpDirect3DLight, dwFlags);
395 Main_IDirect3DViewportImpl_3_2_GetViewport2(LPDIRECT3DVIEWPORT3 iface,
396 LPD3DVIEWPORT2 lpData)
398 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
400 TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
401 if (This->use_vp2 != 1) {
402 ERR(" Requesting to get a D3DVIEWPORT2 struct where a D3DVIEWPORT was set !\n");
403 return DDERR_INVALIDPARAMS;
405 dwSize = lpData->dwSize;
406 memset(lpData, 0, dwSize);
407 memcpy(lpData, &(This->viewports.vp2), dwSize);
409 if (TRACE_ON(ddraw)) {
410 TRACE(" returning D3DVIEWPORT2 :\n");
411 _dump_D3DVIEWPORT2(lpData);
418 Main_IDirect3DViewportImpl_3_2_SetViewport2(LPDIRECT3DVIEWPORT3 iface,
419 LPD3DVIEWPORT2 lpData)
421 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
422 LPDIRECT3DVIEWPORT3 current_viewport;
423 TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
425 if (TRACE_ON(ddraw)) {
426 TRACE(" getting D3DVIEWPORT2 :\n");
427 _dump_D3DVIEWPORT2(lpData);
431 memset(&(This->viewports.vp2), 0, sizeof(This->viewports.vp2));
432 memcpy(&(This->viewports.vp2), lpData, lpData->dwSize);
434 if (This->active_device) {
435 IDirect3DDevice3_GetCurrentViewport(ICOM_INTERFACE(This->active_device, IDirect3DDevice3), ¤t_viewport);
436 if (ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, current_viewport) == This)
437 This->activate(This);
438 IDirect3DViewport3_Release(current_viewport);
445 Main_IDirect3DViewportImpl_3_SetBackgroundDepth2(LPDIRECT3DVIEWPORT3 iface,
446 LPDIRECTDRAWSURFACE4 lpDDS)
448 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
449 FIXME("(%p/%p)->(%p): stub!\n", This, iface, lpDDS);
454 Main_IDirect3DViewportImpl_3_GetBackgroundDepth2(LPDIRECT3DVIEWPORT3 iface,
455 LPDIRECTDRAWSURFACE4* lplpDDS,
458 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
459 FIXME("(%p/%p)->(%p,%p): stub!\n", This, iface, lplpDDS, lpValid);
464 Main_IDirect3DViewportImpl_3_Clear2(LPDIRECT3DVIEWPORT3 iface,
472 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
473 TRACE("(%p/%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, iface, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
474 if (This->active_device == NULL) {
475 ERR(" Trying to clear a viewport not attached to a device !\n");
476 return D3DERR_VIEWPORTHASNODEVICE;
478 return This->active_device->clear(This->active_device, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
481 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
482 # define XCAST(fun) (typeof(VTABLE_IDirect3DViewport3.fun))
484 # define XCAST(fun) (void*)
487 static const IDirect3DViewport3Vtbl VTABLE_IDirect3DViewport3 =
489 XCAST(QueryInterface) Main_IDirect3DViewportImpl_3_2_1_QueryInterface,
490 XCAST(AddRef) Main_IDirect3DViewportImpl_3_2_1_AddRef,
491 XCAST(Release) Main_IDirect3DViewportImpl_3_2_1_Release,
492 XCAST(Initialize) Main_IDirect3DViewportImpl_3_2_1_Initialize,
493 XCAST(GetViewport) Main_IDirect3DViewportImpl_3_2_1_GetViewport,
494 XCAST(SetViewport) Main_IDirect3DViewportImpl_3_2_1_SetViewport,
495 XCAST(TransformVertices) Main_IDirect3DViewportImpl_3_2_1_TransformVertices,
496 XCAST(LightElements) Main_IDirect3DViewportImpl_3_2_1_LightElements,
497 XCAST(SetBackground) Main_IDirect3DViewportImpl_3_2_1_SetBackground,
498 XCAST(GetBackground) Main_IDirect3DViewportImpl_3_2_1_GetBackground,
499 XCAST(SetBackgroundDepth) Main_IDirect3DViewportImpl_3_2_1_SetBackgroundDepth,
500 XCAST(GetBackgroundDepth) Main_IDirect3DViewportImpl_3_2_1_GetBackgroundDepth,
501 XCAST(Clear) Main_IDirect3DViewportImpl_3_2_1_Clear,
502 XCAST(AddLight) Main_IDirect3DViewportImpl_3_2_1_AddLight,
503 XCAST(DeleteLight) Main_IDirect3DViewportImpl_3_2_1_DeleteLight,
504 XCAST(NextLight) Main_IDirect3DViewportImpl_3_2_1_NextLight,
505 XCAST(GetViewport2) Main_IDirect3DViewportImpl_3_2_GetViewport2,
506 XCAST(SetViewport2) Main_IDirect3DViewportImpl_3_2_SetViewport2,
507 XCAST(SetBackgroundDepth2) Main_IDirect3DViewportImpl_3_SetBackgroundDepth2,
508 XCAST(GetBackgroundDepth2) Main_IDirect3DViewportImpl_3_GetBackgroundDepth2,
509 XCAST(Clear2) Main_IDirect3DViewportImpl_3_Clear2,
512 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
519 HRESULT d3dviewport_create(IDirect3DViewportImpl **obj, IDirectDrawImpl *d3d)
521 IDirect3DViewportImpl *object;
523 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DViewportImpl));
524 if (object == NULL) return DDERR_OUTOFMEMORY;
528 object->activate = activate;
529 object->use_vp2 = 0xFF;
531 object->lights = NULL;
532 object->num_lights = 0;
533 object->map_lights = 0;
535 ICOM_INIT_INTERFACE(object, IDirect3DViewport3, VTABLE_IDirect3DViewport3);
539 TRACE(" creating implementation at %p.\n", *obj);