user32: ClipCursor should use virtual screen resolution for empty/invalid rects.
[wine] / dlls / ddraw / viewport.c
1 /* Direct3D Viewport
2  * Copyright (c) 1998 Lionel ULMER
3  * Copyright (c) 2006 Stefan DÖSINGER
4  *
5  * This file contains the implementation of Direct3DViewport2.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include <assert.h>
26 #include <stdarg.h>
27 #include <string.h>
28 #include <stdlib.h>
29
30 #define COBJMACROS
31 #define NONAMELESSUNION
32
33 #include "windef.h"
34 #include "winbase.h"
35 #include "winnls.h"
36 #include "winerror.h"
37 #include "wingdi.h"
38 #include "wine/exception.h"
39 #include "excpt.h"
40
41 #include "ddraw.h"
42 #include "d3d.h"
43
44 #include "ddraw_private.h"
45 #include "wine/debug.h"
46
47 WINE_DEFAULT_DEBUG_CHANNEL(d3d7);
48
49 /*****************************************************************************
50  * Helper functions
51  *****************************************************************************/
52
53 /*****************************************************************************
54  * viewport_activate
55  *
56  * activates the viewport using IDirect3DDevice7::SetViewport
57  *
58  *****************************************************************************/
59 void viewport_activate(IDirect3DViewportImpl* This) {
60     IDirect3DLightImpl* light;
61     D3DVIEWPORT7 vp;
62     
63     /* Activate all the lights associated with this context */
64     light = This->lights;
65
66     while (light != NULL) {
67         light->activate(light);
68         light = light->next;
69     }
70
71     /* And copy the values in the structure used by the device */
72     if (This->use_vp2) {
73         vp.dwX = This->viewports.vp2.dwX;
74         vp.dwY = This->viewports.vp2.dwY;
75         vp.dwHeight = This->viewports.vp2.dwHeight;
76         vp.dwWidth = This->viewports.vp2.dwWidth;
77         vp.dvMinZ = This->viewports.vp2.dvMinZ;
78         vp.dvMaxZ = This->viewports.vp2.dvMaxZ;
79     } else {
80         vp.dwX = This->viewports.vp1.dwX;
81         vp.dwY = This->viewports.vp1.dwY;
82         vp.dwHeight = This->viewports.vp1.dwHeight;
83         vp.dwWidth = This->viewports.vp1.dwWidth;
84         vp.dvMinZ = This->viewports.vp1.dvMinZ;
85         vp.dvMaxZ = This->viewports.vp1.dvMaxZ;
86     }
87     
88     /* And also set the viewport */
89     IDirect3DDevice7_SetViewport(ICOM_INTERFACE(This->active_device, IDirect3DDevice7), &vp);
90 }
91
92 /*****************************************************************************
93  * _dump_D3DVIEWPORT, _dump_D3DVIEWPORT2
94  *
95  * Writes viewport information to TRACE
96  *
97  *****************************************************************************/
98 static void _dump_D3DVIEWPORT(D3DVIEWPORT *lpvp)
99 {
100     TRACE("    - dwSize = %d   dwX = %d   dwY = %d\n",
101           lpvp->dwSize, lpvp->dwX, lpvp->dwY);
102     TRACE("    - dwWidth = %d   dwHeight = %d\n",
103           lpvp->dwWidth, lpvp->dwHeight);
104     TRACE("    - dvScaleX = %f   dvScaleY = %f\n",
105           lpvp->dvScaleX, lpvp->dvScaleY);
106     TRACE("    - dvMaxX = %f   dvMaxY = %f\n",
107           lpvp->dvMaxX, lpvp->dvMaxY);
108     TRACE("    - dvMinZ = %f   dvMaxZ = %f\n",
109           lpvp->dvMinZ, lpvp->dvMaxZ);
110 }
111
112 static void _dump_D3DVIEWPORT2(D3DVIEWPORT2 *lpvp)
113 {
114     TRACE("    - dwSize = %d   dwX = %d   dwY = %d\n",
115           lpvp->dwSize, lpvp->dwX, lpvp->dwY);
116     TRACE("    - dwWidth = %d   dwHeight = %d\n",
117           lpvp->dwWidth, lpvp->dwHeight);
118     TRACE("    - dvClipX = %f   dvClipY = %f\n",
119           lpvp->dvClipX, lpvp->dvClipY);
120     TRACE("    - dvClipWidth = %f   dvClipHeight = %f\n",
121           lpvp->dvClipWidth, lpvp->dvClipHeight);
122     TRACE("    - dvMinZ = %f   dvMaxZ = %f\n",
123           lpvp->dvMinZ, lpvp->dvMaxZ);
124 }
125
126 /*****************************************************************************
127  * IUnknown Methods.
128  *****************************************************************************/
129
130 /*****************************************************************************
131  * IDirect3DViewport3::QueryInterface
132  *
133  * A normal QueryInterface. Can query all interface versions and the
134  * IUnknown interface. The VTables of the different versions
135  * are equal
136  *
137  * Params:
138  *  refiid: Interface id queried for
139  *  obj: Address to write the interface pointer to
140  *
141  * Returns:
142  *  S_OK on success.
143  *  E_NOINTERFACE if the requested interface wasn't found
144  *
145  *****************************************************************************/
146 static HRESULT WINAPI
147 IDirect3DViewportImpl_QueryInterface(IDirect3DViewport3 *iface,
148                                      REFIID riid,
149                                      void **obp)
150 {
151     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
152     TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), obp);
153
154     *obp = NULL;
155
156     if ( IsEqualGUID(&IID_IUnknown,  riid) ||
157          IsEqualGUID(&IID_IDirect3DViewport, riid) ||
158          IsEqualGUID(&IID_IDirect3DViewport2, riid) ||
159          IsEqualGUID(&IID_IDirect3DViewport3, riid) ) {
160         IDirect3DViewport3_AddRef(ICOM_INTERFACE(This, IDirect3DViewport3));
161         *obp = ICOM_INTERFACE(This, IDirect3DViewport3);
162         TRACE("  Creating IDirect3DViewport1/2/3 interface %p\n", *obp);
163         return S_OK;
164     }
165     FIXME("(%p): interface for IID %s NOT found!\n", This, debugstr_guid(riid));
166     return E_NOINTERFACE;
167 }
168
169 /*****************************************************************************
170  * IDirect3DViewport3::AddRef
171  *
172  * Increases the refcount.
173  *
174  * Returns:
175  *  The new refcount
176  *
177  *****************************************************************************/
178 static ULONG WINAPI
179 IDirect3DViewportImpl_AddRef(IDirect3DViewport3 *iface)
180 {
181     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
182     ULONG ref = InterlockedIncrement(&This->ref);
183
184     TRACE("(%p)->() incrementing from %u.\n", This, ref - 1);
185
186     return ref;
187 }
188
189 /*****************************************************************************
190  * IDirect3DViewport3::Release
191  *
192  * Reduces the refcount. If it falls to 0, the interface is released
193  *
194  * Returns:
195  *  The new refcount
196  *
197  *****************************************************************************/
198 static ULONG WINAPI
199 IDirect3DViewportImpl_Release(IDirect3DViewport3 *iface)
200 {
201     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
202     ULONG ref = InterlockedDecrement(&This->ref);
203
204     TRACE("(%p)->() decrementing from %u.\n", This, ref + 1);
205
206     if (!ref) {
207         HeapFree(GetProcessHeap(), 0, This);
208         return 0;
209     }
210     return ref;
211 }
212
213 /*****************************************************************************
214  * IDirect3DViewport Methods.
215  *****************************************************************************/
216
217 /*****************************************************************************
218  * IDirect3DViewport3::Initialize
219  *
220  * No-op initialization.
221  *
222  * Params:
223  *  Direct3D: The direct3D device this viewport is assigned to
224  *
225  * Returns:
226  *  DDERR_ALREADYINITIALIZED
227  *
228  *****************************************************************************/
229 static HRESULT WINAPI
230 IDirect3DViewportImpl_Initialize(IDirect3DViewport3 *iface,
231                                  IDirect3D *Direct3D)
232 {
233     TRACE("(%p)->(%p) no-op...\n", iface, Direct3D);
234     return DDERR_ALREADYINITIALIZED;
235 }
236
237 /*****************************************************************************
238  * IDirect3DViewport3::GetViewport
239  *
240  * Returns the viewport data assigned to this viewport interface
241  *
242  * Params:
243  *  Data: Address to store the data
244  *
245  * Returns:
246  *  D3D_OK on success
247  *  DDERR_INVALIDPARAMS if Data is NULL
248  *
249  *****************************************************************************/
250 static HRESULT WINAPI
251 IDirect3DViewportImpl_GetViewport(IDirect3DViewport3 *iface,
252                                   D3DVIEWPORT *lpData)
253 {
254     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
255     DWORD dwSize;
256     TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
257     if (This->use_vp2 != 0) {
258         ERR("  Requesting to get a D3DVIEWPORT struct where a D3DVIEWPORT2 was set !\n");
259         return DDERR_INVALIDPARAMS;
260     }
261     dwSize = lpData->dwSize;
262     memset(lpData, 0, dwSize);
263     memcpy(lpData, &(This->viewports.vp1), dwSize);
264
265     if (TRACE_ON(d3d7)) {
266         TRACE("  returning D3DVIEWPORT :\n");
267         _dump_D3DVIEWPORT(lpData);
268     }
269     
270     return DD_OK;
271 }
272
273 /*****************************************************************************
274  * IDirect3DViewport3::SetViewport
275  *
276  * Sets the viewport information for this interface
277  *
278  * Params:
279  *  lpData: Viewport to set
280  *
281  * Returns:
282  *  D3D_OK on success
283  *  DDERR_INVALIDPARAMS if Data is NULL
284  *
285  *****************************************************************************/
286 static HRESULT WINAPI
287 IDirect3DViewportImpl_SetViewport(IDirect3DViewport3 *iface,
288                                   D3DVIEWPORT *lpData)
289 {
290     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
291     LPDIRECT3DVIEWPORT3 current_viewport;
292     TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
293
294     if (TRACE_ON(d3d7)) {
295         TRACE("  getting D3DVIEWPORT :\n");
296         _dump_D3DVIEWPORT(lpData);
297     }
298
299     This->use_vp2 = 0;
300     memset(&(This->viewports.vp1), 0, sizeof(This->viewports.vp1));
301     memcpy(&(This->viewports.vp1), lpData, lpData->dwSize);
302
303     /* Tests on two games show that these values are never used properly so override
304        them with proper ones :-)
305     */
306     This->viewports.vp1.dvMinZ = 0.0;
307     This->viewports.vp1.dvMaxZ = 1.0;
308
309     if (This->active_device) {
310       IDirect3DDevice3_GetCurrentViewport(ICOM_INTERFACE(This->active_device, IDirect3DDevice3), &current_viewport);
311       if (ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, current_viewport) == This)
312           This->activate(This);
313       if(current_viewport) IDirect3DViewport3_Release(current_viewport);
314     }
315
316     return DD_OK;
317 }
318
319 /*****************************************************************************
320  * IDirect3DViewport3::TransformVertices
321  *
322  * Transforms vertices by the transformation matrix.
323  *
324  * Params:
325  *  dwVertexCount: The number of vertices to be transformed
326  *  lpData: Pointer to the vertex data
327  *  dwFlags: D3DTRANSFORM_CLIPPED or D3DTRANSFORM_UNCLIPPED
328  *  lpOffScreen: Is set to nonzero if all vertices are off-screen
329  *
330  * Returns:
331  *  D3D_OK because it's a stub
332  *
333  *****************************************************************************/
334 static HRESULT WINAPI
335 IDirect3DViewportImpl_TransformVertices(IDirect3DViewport3 *iface,
336                                         DWORD dwVertexCount,
337                                         D3DTRANSFORMDATA *lpData,
338                                         DWORD dwFlags,
339                                         DWORD *lpOffScreen)
340 {
341     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
342     FIXME("(%p)->(%08x,%p,%08x,%p): stub!\n", This, dwVertexCount, lpData, dwFlags, lpOffScreen);
343     if (lpOffScreen)
344         *lpOffScreen = 0;
345     return DD_OK;
346 }
347
348 /*****************************************************************************
349  * IDirect3DViewport3::LightElements
350  *
351  * The DirectX 5.0 sdk says that it's not implemented
352  *
353  * Params:
354  *  ?
355  *
356  * Returns:
357  *  DDERR_UNSUPPORTED
358  *
359  *****************************************************************************/
360 static HRESULT WINAPI
361 IDirect3DViewportImpl_LightElements(IDirect3DViewport3 *iface,
362                                     DWORD dwElementCount,
363                                     LPD3DLIGHTDATA lpData)
364 {
365     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
366     TRACE("(%p)->(%08x,%p): Unimplemented!\n", This, dwElementCount, lpData);
367     return DDERR_UNSUPPORTED;
368 }
369
370 /*****************************************************************************
371  * IDirect3DViewport3::SetBackground
372  *
373  * Sets tje background material
374  *
375  * Params:
376  *  hMat: Handle from a IDirect3DMaterial interface
377  *
378  * Returns:
379  *  D3D_OK on success
380  *
381  *****************************************************************************/
382 static HRESULT WINAPI
383 IDirect3DViewportImpl_SetBackground(IDirect3DViewport3 *iface,
384                                     D3DMATERIALHANDLE hMat)
385 {
386     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
387     TRACE("(%p)->(%d)\n", This, (DWORD) hMat);
388
389     if(hMat && hMat > This->ddraw->d3ddevice->numHandles)
390     {
391         WARN("Specified Handle %d out of range\n", hMat);
392         return DDERR_INVALIDPARAMS;
393     }
394     else if(hMat && This->ddraw->d3ddevice->Handles[hMat - 1].type != DDrawHandle_Material)
395     {
396         WARN("Handle %d is not a material handle\n", hMat);
397         return DDERR_INVALIDPARAMS;
398     }
399
400     if(hMat)
401     {
402         This->background = (IDirect3DMaterialImpl *) This->ddraw->d3ddevice->Handles[hMat - 1].ptr;
403         TRACE(" setting background color : %f %f %f %f\n",
404               This->background->mat.u.diffuse.u1.r,
405               This->background->mat.u.diffuse.u2.g,
406               This->background->mat.u.diffuse.u3.b,
407               This->background->mat.u.diffuse.u4.a);
408     }
409     else
410     {
411         This->background = NULL;
412         TRACE("Setting background to NULL\n");
413     }
414
415     return D3D_OK;
416 }
417
418 /*****************************************************************************
419  * IDirect3DViewport3::GetBackground
420  *
421  * Returns the material handle assigned to the background of the viewport
422  *
423  * Params:
424  *  lphMat: Address to store the handle
425  *  lpValid: is set to FALSE if no background is set, TRUE if one is set
426  *
427  * Returns:
428  *  D3D_OK
429  *
430  *****************************************************************************/
431 static HRESULT WINAPI
432 IDirect3DViewportImpl_GetBackground(IDirect3DViewport3 *iface,
433                                     D3DMATERIALHANDLE *lphMat,
434                                     BOOL *lpValid)
435 {
436     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
437     TRACE("(%p)->(%p,%p)\n", This, lphMat, lpValid);
438
439     if(lpValid)
440     {
441         *lpValid = This->background != NULL;
442     }
443     if(lphMat)
444     {
445         if(This->background)
446         {
447             *lphMat = This->background->Handle;
448         }
449         else
450         {
451             *lphMat = 0;
452         }
453     }
454
455     return D3D_OK;
456 }
457
458 /*****************************************************************************
459  * IDirect3DViewport3::SetBackgroundDepth
460  *
461  * Sets a surface that represents the background depth. It's contents are
462  * used to set the depth buffer in IDirect3DViewport3::Clear
463  *
464  * Params:
465  *  lpDDSurface: Surface to set
466  *
467  * Returns: D3D_OK, because it's a stub
468  *
469  *****************************************************************************/
470 static HRESULT WINAPI
471 IDirect3DViewportImpl_SetBackgroundDepth(IDirect3DViewport3 *iface,
472                                          IDirectDrawSurface *lpDDSurface)
473 {
474     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
475     FIXME("(%p)->(%p): stub!\n", This, lpDDSurface);
476     return D3D_OK;
477 }
478
479 /*****************************************************************************
480  * IDirect3DViewport3::GetBackgroundDepth
481  *
482  * Returns the surface that represents the depth field
483  *
484  * Params:
485  *  lplpDDSurface: Address to store the interface pointer
486  *  lpValid: Set to TRUE if a depth is asigned, FALSE otherwise
487  *
488  * Returns:
489  *  D3D_OK, because it's a stub
490  *  (DDERR_INVALIDPARAMS if DDSurface of Valid is NULL)
491  *
492  *****************************************************************************/
493 static HRESULT WINAPI
494 IDirect3DViewportImpl_GetBackgroundDepth(IDirect3DViewport3 *iface,
495                                          IDirectDrawSurface **lplpDDSurface,
496                                          LPBOOL lpValid)
497 {
498     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
499     FIXME("(%p)->(%p,%p): stub!\n", This, lplpDDSurface, lpValid);
500     return DD_OK;
501 }
502
503 /*****************************************************************************
504  * IDirect3DViewport3::Clear
505  *
506  * Clears the render target and / or the z buffer
507  *
508  * Params:
509  *  dwCount: The amount of rectangles to clear. If 0, the whole buffer is
510  *           cleared
511  *  lpRects: Pointer to the array of rectangles. If NULL, Count must be 0
512  *  dwFlags: D3DCLEAR_ZBUFFER and / or D3DCLEAR_TARGET
513  *
514  * Returns:
515  *  D3D_OK on success
516  *  D3DERR_VIEWPORTHASNODEVICE if there's no active device
517  *  The return value of IDirect3DDevice7::Clear
518  *
519  *****************************************************************************/
520 static HRESULT WINAPI
521 IDirect3DViewportImpl_Clear(IDirect3DViewport3 *iface,
522                             DWORD dwCount, 
523                             D3DRECT *lpRects,
524                             DWORD dwFlags)
525 {
526     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
527     DWORD color = 0x00000000;
528     
529     TRACE("(%p/%p)->(%08x,%p,%08x)\n", This, iface, dwCount, lpRects, dwFlags);
530     if (This->active_device == NULL) {
531         ERR(" Trying to clear a viewport not attached to a device !\n");
532         return D3DERR_VIEWPORTHASNODEVICE;
533     }
534     if (dwFlags & D3DCLEAR_TARGET) {
535         if (This->background == NULL) {
536             ERR(" Trying to clear the color buffer without background material !\n");
537         } else {
538             color = 
539               ((int) ((This->background->mat.u.diffuse.u1.r) * 255) << 16) |
540               ((int) ((This->background->mat.u.diffuse.u2.g) * 255) <<  8) |
541               ((int) ((This->background->mat.u.diffuse.u3.b) * 255) <<  0) |
542               ((int) ((This->background->mat.u.diffuse.u4.a) * 255) << 24);
543         }
544     }
545
546     return IDirect3DDevice7_Clear(ICOM_INTERFACE(This->active_device, IDirect3DDevice7),
547                                   dwCount,
548                                   lpRects,
549                                   dwFlags & (D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET),
550                                   color,
551                                   1.0,
552                                   0x00000000);
553 }
554
555 /*****************************************************************************
556  * IDirect3DViewport3::AddLight
557  *
558  * Adds an light to the viewport
559  *
560  * Params:
561  *  lpDirect3DLight: Interface of the light to add
562  *
563  * Returns:
564  *  D3D_OK on success
565  *  DDERR_INVALIDPARAMS if Direct3DLight is NULL
566  *  DDERR_INVALIDPARAMS if there are 8 lights or more
567  *
568  *****************************************************************************/
569 static HRESULT WINAPI
570 IDirect3DViewportImpl_AddLight(IDirect3DViewport3 *iface,
571                                IDirect3DLight *lpDirect3DLight)
572 {
573     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
574     IDirect3DLightImpl *lpDirect3DLightImpl = ICOM_OBJECT(IDirect3DLightImpl, IDirect3DLight, lpDirect3DLight);
575     DWORD i = 0;
576     DWORD map = This->map_lights;
577     
578     TRACE("(%p)->(%p)\n", This, lpDirect3DLight);
579     
580     if (This->num_lights >= 8)
581         return DDERR_INVALIDPARAMS;
582
583     /* Find a light number and update both light and viewports objects accordingly */
584     while(map&1) {
585         map>>=1;
586         i++;
587     }
588     lpDirect3DLightImpl->dwLightIndex = i;
589     This->num_lights++;
590     This->map_lights |= 1<<i;
591
592     /* Add the light in the 'linked' chain */
593     lpDirect3DLightImpl->next = This->lights;
594     This->lights = lpDirect3DLightImpl;
595
596     /* Attach the light to the viewport */
597     lpDirect3DLightImpl->active_viewport = This;
598     
599     /* If active, activate the light */
600     if (This->active_device != NULL) {
601         lpDirect3DLightImpl->activate(lpDirect3DLightImpl);
602     }
603     
604     return D3D_OK;
605 }
606
607 /*****************************************************************************
608  * IDirect3DViewport3::DeleteLight
609  *
610  * Deletes a light from the viewports' light list
611  *
612  * Params:
613  *  lpDirect3DLight: Light to delete
614  *
615  * Returns:
616  *  D3D_OK on success
617  *  DDERR_INVALIDPARAMS if the light wasn't found
618  *
619  *****************************************************************************/
620 static HRESULT WINAPI
621 IDirect3DViewportImpl_DeleteLight(IDirect3DViewport3 *iface,
622                                   IDirect3DLight *lpDirect3DLight)
623 {
624     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
625     IDirect3DLightImpl *lpDirect3DLightImpl = ICOM_OBJECT(IDirect3DLightImpl, IDirect3DLight, lpDirect3DLight);
626     IDirect3DLightImpl *cur_light, *prev_light = NULL;
627     
628     TRACE("(%p)->(%p)\n", This, lpDirect3DLight);
629     cur_light = This->lights;
630     while (cur_light != NULL) {
631         if (cur_light == lpDirect3DLightImpl) {
632             lpDirect3DLightImpl->desactivate(lpDirect3DLightImpl);
633             if (prev_light == NULL) This->lights = cur_light->next;
634             else prev_light->next = cur_light->next;
635             /* Detach the light to the viewport */
636             cur_light->active_viewport = NULL;
637             This->num_lights--;
638             This->map_lights &= ~(1<<lpDirect3DLightImpl->dwLightIndex);
639             return D3D_OK;
640         }
641         prev_light = cur_light;
642         cur_light = cur_light->next;
643     }
644     return DDERR_INVALIDPARAMS;
645 }
646
647 /*****************************************************************************
648  * IDirect3DViewport::NextLight
649  *
650  * Enumerates the lights associated with the viewport
651  *
652  * Params:
653  *  lpDirect3DLight: Light to start with
654  *  lplpDirect3DLight: Address to store the successor to
655  *
656  * Returns:
657  *  D3D_OK, because it's a stub
658  *
659  *****************************************************************************/
660 static HRESULT WINAPI
661 IDirect3DViewportImpl_NextLight(IDirect3DViewport3 *iface,
662                                 IDirect3DLight *lpDirect3DLight,
663                                 IDirect3DLight **lplpDirect3DLight,
664                                 DWORD dwFlags)
665 {
666     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
667     FIXME("(%p)->(%p,%p,%08x): stub!\n", This, lpDirect3DLight, lplpDirect3DLight, dwFlags);
668     return D3D_OK;
669 }
670
671 /*****************************************************************************
672  * IDirect3DViewport2 Methods.
673  *****************************************************************************/
674
675 /*****************************************************************************
676  * IDirect3DViewport3::GetViewport2
677  *
678  * Returns the currently set viewport in a D3DVIEWPORT2 structure.
679  * Similar to IDirect3DViewport3::GetViewport
680  *
681  * Params:
682  *  lpData: Pointer to the structure to fill
683  *
684  * Returns:
685  *  D3D_OK on success
686  *  DDERR_INVALIDPARAMS if the viewport was set with
687  *                      IDirect3DViewport3::SetViewport
688  *  DDERR_INVALIDPARAMS if Data is NULL
689  *
690  *****************************************************************************/
691 static HRESULT WINAPI
692 IDirect3DViewportImpl_GetViewport2(IDirect3DViewport3 *iface,
693                                    D3DVIEWPORT2 *lpData)
694 {
695     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
696     DWORD dwSize;
697     TRACE("(%p)->(%p)\n", This, lpData);
698     if (This->use_vp2 != 1) {
699         ERR("  Requesting to get a D3DVIEWPORT2 struct where a D3DVIEWPORT was set !\n");
700         return DDERR_INVALIDPARAMS;
701     }
702     dwSize = lpData->dwSize;
703     memset(lpData, 0, dwSize);
704     memcpy(lpData, &(This->viewports.vp2), dwSize);
705
706     if (TRACE_ON(d3d7)) {
707         TRACE("  returning D3DVIEWPORT2 :\n");
708         _dump_D3DVIEWPORT2(lpData);
709     }
710     
711     return D3D_OK;
712 }
713
714 /*****************************************************************************
715  * IDirect3DViewport3::SetViewport2
716  *
717  * Sets the viewport from a D3DVIEWPORT2 structure
718  *
719  * Params:
720  *  lpData: Viewport to set
721  *
722  * Returns:
723  *  D3D_OK on success
724  *
725  *****************************************************************************/
726 static HRESULT WINAPI
727 IDirect3DViewportImpl_SetViewport2(IDirect3DViewport3 *iface,
728                                    D3DVIEWPORT2 *lpData)
729 {
730     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
731     LPDIRECT3DVIEWPORT3 current_viewport;
732     TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
733
734     if (TRACE_ON(d3d7)) {
735         TRACE("  getting D3DVIEWPORT2 :\n");
736         _dump_D3DVIEWPORT2(lpData);
737     }
738
739     This->use_vp2 = 1;
740     memset(&(This->viewports.vp2), 0, sizeof(This->viewports.vp2));
741     memcpy(&(This->viewports.vp2), lpData, lpData->dwSize);
742
743     if (This->active_device) {
744       IDirect3DDevice3_GetCurrentViewport(ICOM_INTERFACE(This->active_device, IDirect3DDevice3), &current_viewport);
745       if (ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, current_viewport) == This)
746         This->activate(This);
747       IDirect3DViewport3_Release(current_viewport);
748     }
749
750     return D3D_OK;
751 }
752
753 /*****************************************************************************
754  * IDirect3DViewport3 Methods.
755  *****************************************************************************/
756
757 /*****************************************************************************
758  * IDirect3DViewport3::SetBackgroundDepth2
759  *
760  * Sets a IDirectDrawSurface4 surface as the background depth surface
761  *
762  * Params:
763  *  lpDDS: Surface to set
764  *
765  * Returns:
766  *  D3D_OK, because it's stub
767  *
768  *****************************************************************************/
769 static HRESULT WINAPI
770 IDirect3DViewportImpl_SetBackgroundDepth2(IDirect3DViewport3 *iface,
771                                           IDirectDrawSurface4 *lpDDS)
772 {
773     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
774     FIXME("(%p)->(%p): stub!\n", This, lpDDS);
775     return D3D_OK;
776 }
777
778 /*****************************************************************************
779  * IDirect3DViewport3::GetBackgroundDepth2
780  *
781  * Returns the IDirect3DSurface4 interface to the background depth surface
782  *
783  * Params:
784  *  lplpDDS: Address to store the interface pointer at
785  *  lpValid: Set to true if a surface is assigned
786  *
787  * Returns:
788  *  D3D_OK because it's a stub
789  *
790  *****************************************************************************/
791 static HRESULT WINAPI
792 IDirect3DViewportImpl_GetBackgroundDepth2(IDirect3DViewport3 *iface,
793                                           IDirectDrawSurface4 **lplpDDS,
794                                           BOOL *lpValid)
795 {
796     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
797     FIXME("(%p/%p)->(%p,%p): stub!\n", This, iface, lplpDDS, lpValid);
798     return D3D_OK;
799 }
800
801 /*****************************************************************************
802  * IDirect3DViewport3::Clear2
803  *
804  * Another clearing method
805  *
806  * Params:
807  *  Count: Number of rectangles to clear
808  *  Rects: Rectangle array to clear
809  *  Flags: Some flags :)
810  *  Color: Color to fill the render target with
811  *  Z: Value to fill the depth buffer with
812  *  Stencil: Value to fill the stencil bits with
813  *
814  * Returns:
815  *
816  *****************************************************************************/
817 static HRESULT WINAPI
818 IDirect3DViewportImpl_Clear2(IDirect3DViewport3 *iface,
819                              DWORD dwCount,
820                              LPD3DRECT lpRects,
821                              DWORD dwFlags,
822                              DWORD dwColor,
823                              D3DVALUE dvZ,
824                              DWORD dwStencil)
825 {
826     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
827     TRACE("(%p)->(%08x,%p,%08x,%08x,%f,%08x)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
828     if (This->active_device == NULL) {
829         ERR(" Trying to clear a viewport not attached to a device !\n");
830         return D3DERR_VIEWPORTHASNODEVICE;
831     }
832     return IDirect3DDevice7_Clear(ICOM_INTERFACE(This->active_device, IDirect3DDevice7),
833                                   dwCount,
834                                   lpRects,
835                                   dwFlags,
836                                   dwColor,
837                                   dvZ,
838                                   dwStencil);
839 }
840
841 /*****************************************************************************
842  * The VTable
843  *****************************************************************************/
844
845 const IDirect3DViewport3Vtbl IDirect3DViewport3_Vtbl =
846 {
847     /*** IUnknown Methods ***/
848     IDirect3DViewportImpl_QueryInterface,
849     IDirect3DViewportImpl_AddRef,
850     IDirect3DViewportImpl_Release,
851     /*** IDirect3DViewport Methods */
852     IDirect3DViewportImpl_Initialize,
853     IDirect3DViewportImpl_GetViewport,
854     IDirect3DViewportImpl_SetViewport,
855     IDirect3DViewportImpl_TransformVertices,
856     IDirect3DViewportImpl_LightElements,
857     IDirect3DViewportImpl_SetBackground,
858     IDirect3DViewportImpl_GetBackground,
859     IDirect3DViewportImpl_SetBackgroundDepth,
860     IDirect3DViewportImpl_GetBackgroundDepth,
861     IDirect3DViewportImpl_Clear,
862     IDirect3DViewportImpl_AddLight,
863     IDirect3DViewportImpl_DeleteLight,
864     IDirect3DViewportImpl_NextLight,
865     /*** IDirect3DViewport2 Methods ***/
866     IDirect3DViewportImpl_GetViewport2,
867     IDirect3DViewportImpl_SetViewport2,
868     /*** IDirect3DViewport3 Methods ***/
869     IDirect3DViewportImpl_SetBackgroundDepth2,
870     IDirect3DViewportImpl_GetBackgroundDepth2,
871     IDirect3DViewportImpl_Clear2,
872 };