Add DDCAPS_OVERLAY and DDCAPS_OVERLAYSTRETCH to GetCaps().
[wine] / dlls / ddraw / d3dviewport.c
1 /* Direct3D Viewport
2  * Copyright (c) 1998 Lionel ULMER
3  *
4  * This file contains the implementation of Direct3DViewport2.
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #include <stdarg.h>
24
25 #define NONAMELESSUNION
26 #define NONAMELESSSTRUCT
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winerror.h"
30 #include "objbase.h"
31 #include "wingdi.h"
32 #include "ddraw.h"
33 #include "d3d.h"
34 #include "wine/debug.h"
35
36 #include "d3d_private.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
39
40 static void activate(IDirect3DViewportImpl* This) {
41     IDirect3DLightImpl* light;
42     D3DVIEWPORT7 vp;
43     
44     /* Activate all the lights associated with this context */
45     light = This->lights;
46
47     while (light != NULL) {
48         light->activate(light);
49         light = light->next;
50     }
51
52     /* And copy the values in the structure used by the device */
53     if (This->use_vp2) {
54         vp.dwX = This->viewports.vp2.dwX;
55         vp.dwY = This->viewports.vp2.dwY;
56         vp.dwHeight = This->viewports.vp2.dwHeight;
57         vp.dwWidth = This->viewports.vp2.dwWidth;
58         vp.dvMinZ = This->viewports.vp2.dvMinZ;
59         vp.dvMaxZ = This->viewports.vp2.dvMaxZ;
60     } else {
61         vp.dwX = This->viewports.vp1.dwX;
62         vp.dwY = This->viewports.vp1.dwY;
63         vp.dwHeight = This->viewports.vp1.dwHeight;
64         vp.dwWidth = This->viewports.vp1.dwWidth;
65         vp.dvMinZ = This->viewports.vp1.dvMinZ;
66         vp.dvMaxZ = This->viewports.vp1.dvMaxZ;
67     }
68     
69     /* And also set the viewport */
70     IDirect3DDevice7_SetViewport(ICOM_INTERFACE(This->active_device, IDirect3DDevice7), &vp);
71 }
72
73
74 static void _dump_D3DVIEWPORT(D3DVIEWPORT *lpvp)
75 {
76     TRACE("    - dwSize = %ld   dwX = %ld   dwY = %ld\n",
77           lpvp->dwSize, lpvp->dwX, lpvp->dwY);
78     TRACE("    - dwWidth = %ld   dwHeight = %ld\n",
79           lpvp->dwWidth, lpvp->dwHeight);
80     TRACE("    - dvScaleX = %f   dvScaleY = %f\n",
81           lpvp->dvScaleX, lpvp->dvScaleY);
82     TRACE("    - dvMaxX = %f   dvMaxY = %f\n",
83           lpvp->dvMaxX, lpvp->dvMaxY);
84     TRACE("    - dvMinZ = %f   dvMaxZ = %f\n",
85           lpvp->dvMinZ, lpvp->dvMaxZ);
86 }
87
88 static void _dump_D3DVIEWPORT2(D3DVIEWPORT2 *lpvp)
89 {
90     TRACE("    - dwSize = %ld   dwX = %ld   dwY = %ld\n",
91           lpvp->dwSize, lpvp->dwX, lpvp->dwY);
92     TRACE("    - dwWidth = %ld   dwHeight = %ld\n",
93           lpvp->dwWidth, lpvp->dwHeight);
94     TRACE("    - dvClipX = %f   dvClipY = %f\n",
95           lpvp->dvClipX, lpvp->dvClipY);
96     TRACE("    - dvClipWidth = %f   dvClipHeight = %f\n",
97           lpvp->dvClipWidth, lpvp->dvClipHeight);
98     TRACE("    - dvMinZ = %f   dvMaxZ = %f\n",
99           lpvp->dvMinZ, lpvp->dvMaxZ);
100 }
101
102 HRESULT WINAPI
103 Main_IDirect3DViewportImpl_3_2_1_QueryInterface(LPDIRECT3DVIEWPORT3 iface,
104                                                 REFIID riid,
105                                                 LPVOID* obp)
106 {
107     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
108     TRACE("(%p/%p)->(%s,%p)\n", This, iface, debugstr_guid(riid), obp);
109
110     *obp = NULL;
111
112     if ( IsEqualGUID(&IID_IUnknown,  riid) ||
113          IsEqualGUID(&IID_IDirect3DViewport, riid) ||
114          IsEqualGUID(&IID_IDirect3DViewport2, riid) ||
115          IsEqualGUID(&IID_IDirect3DViewport3, riid) ) {
116         IDirect3DViewport3_AddRef(ICOM_INTERFACE(This, IDirect3DViewport3));
117         *obp = ICOM_INTERFACE(This, IDirect3DViewport3);
118         TRACE("  Creating IDirect3DViewport1/2/3 interface %p\n", *obp);
119         return S_OK;
120     }
121     FIXME("(%p): interface for IID %s NOT found!\n", This, debugstr_guid(riid));
122     return OLE_E_ENUM_NOMORE;
123 }
124
125 ULONG WINAPI
126 Main_IDirect3DViewportImpl_3_2_1_AddRef(LPDIRECT3DVIEWPORT3 iface)
127 {
128     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
129     ULONG ref = InterlockedIncrement(&This->ref);
130
131     TRACE("(%p/%p)->() incrementing from %lu.\n", This, iface, ref - 1);
132
133     return ref;
134 }
135
136 ULONG WINAPI
137 Main_IDirect3DViewportImpl_3_2_1_Release(LPDIRECT3DVIEWPORT3 iface)
138 {
139     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
140     ULONG ref = InterlockedDecrement(&This->ref);
141
142     TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, ref + 1);
143
144     if (!ref) {
145         HeapFree(GetProcessHeap(), 0, This);
146         return 0;
147     }
148     return ref;
149 }
150
151
152 HRESULT WINAPI
153 Main_IDirect3DViewportImpl_3_2_1_Initialize(LPDIRECT3DVIEWPORT3 iface,
154                                             LPDIRECT3D lpDirect3D)
155 {
156     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
157     TRACE("(%p/%p)->(%p) no-op...\n", This, iface, lpDirect3D);
158     return DD_OK;
159 }
160
161 HRESULT WINAPI
162 Main_IDirect3DViewportImpl_3_2_1_GetViewport(LPDIRECT3DVIEWPORT3 iface,
163                                              LPD3DVIEWPORT lpData)
164 {
165     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
166     DWORD dwSize;
167     TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
168     if (This->use_vp2 != 0) {
169         ERR("  Requesting to get a D3DVIEWPORT struct where a D3DVIEWPORT2 was set !\n");
170         return DDERR_INVALIDPARAMS;
171     }
172     dwSize = lpData->dwSize;
173     memset(lpData, 0, dwSize);
174     memcpy(lpData, &(This->viewports.vp1), dwSize);
175
176     if (TRACE_ON(ddraw)) {
177         TRACE("  returning D3DVIEWPORT :\n");
178         _dump_D3DVIEWPORT(lpData);
179     }
180     
181     return DD_OK;
182 }
183
184 HRESULT WINAPI
185 Main_IDirect3DViewportImpl_3_2_1_SetViewport(LPDIRECT3DVIEWPORT3 iface,
186                                              LPD3DVIEWPORT lpData)
187 {
188     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
189     LPDIRECT3DVIEWPORT3 current_viewport;
190     TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
191
192     if (TRACE_ON(ddraw)) {
193         TRACE("  getting D3DVIEWPORT :\n");
194         _dump_D3DVIEWPORT(lpData);
195     }
196
197     This->use_vp2 = 0;
198     memset(&(This->viewports.vp1), 0, sizeof(This->viewports.vp1));
199     memcpy(&(This->viewports.vp1), lpData, lpData->dwSize);
200
201     /* Tests on two games show that these values are never used properly so override
202        them with proper ones :-)
203     */
204     This->viewports.vp1.dvMinZ = 0.0;
205     This->viewports.vp1.dvMaxZ = 1.0;
206
207     if (This->active_device) {
208       IDirect3DDevice3_GetCurrentViewport(ICOM_INTERFACE(This->active_device, IDirect3DDevice3), &current_viewport);
209       if (ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, current_viewport) == This)
210           This->activate(This);
211       IDirect3DViewport3_Release(current_viewport);
212     }
213
214     return DD_OK;
215 }
216
217 HRESULT WINAPI
218 Main_IDirect3DViewportImpl_3_2_1_TransformVertices(LPDIRECT3DVIEWPORT3 iface,
219                                                    DWORD dwVertexCount,
220                                                    LPD3DTRANSFORMDATA lpData,
221                                                    DWORD dwFlags,
222                                                    LPDWORD lpOffScreen)
223 {
224     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
225     FIXME("(%p/%p)->(%08lx,%p,%08lx,%p): stub!\n", This, iface, dwVertexCount, lpData, dwFlags, lpOffScreen);
226     if (lpOffScreen)
227         *lpOffScreen = 0;
228     return DD_OK;
229 }
230
231 HRESULT WINAPI
232 Main_IDirect3DViewportImpl_3_2_1_LightElements(LPDIRECT3DVIEWPORT3 iface,
233                                                DWORD dwElementCount,
234                                                LPD3DLIGHTDATA lpData)
235 {
236     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
237     FIXME("(%p/%p)->(%08lx,%p): stub!\n", This, iface, dwElementCount, lpData);
238     return DD_OK;
239 }
240
241 HRESULT WINAPI
242 Main_IDirect3DViewportImpl_3_2_1_SetBackground(LPDIRECT3DVIEWPORT3 iface,
243                                                D3DMATERIALHANDLE hMat)
244 {
245     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
246     TRACE("(%p/%p)->(%08lx)\n", This, iface, (DWORD) hMat);
247     
248     This->background = (IDirect3DMaterialImpl *) hMat;
249     TRACE(" setting background color : %f %f %f %f\n",
250           This->background->mat.u.diffuse.u1.r,
251           This->background->mat.u.diffuse.u2.g,
252           This->background->mat.u.diffuse.u3.b,
253           This->background->mat.u.diffuse.u4.a);
254
255     return DD_OK;
256 }
257
258 HRESULT WINAPI
259 Main_IDirect3DViewportImpl_3_2_1_GetBackground(LPDIRECT3DVIEWPORT3 iface,
260                                                LPD3DMATERIALHANDLE lphMat,
261                                                LPBOOL lpValid)
262 {
263     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
264     FIXME("(%p/%p)->(%p,%p): stub!\n", This, iface, lphMat, lpValid);
265     return DD_OK;
266 }
267
268 HRESULT WINAPI
269 Main_IDirect3DViewportImpl_3_2_1_SetBackgroundDepth(LPDIRECT3DVIEWPORT3 iface,
270                                                     LPDIRECTDRAWSURFACE lpDDSurface)
271 {
272     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
273     FIXME("(%p/%p)->(%p): stub!\n", This, iface, lpDDSurface);
274     return DD_OK;
275 }
276
277 HRESULT WINAPI
278 Main_IDirect3DViewportImpl_3_2_1_GetBackgroundDepth(LPDIRECT3DVIEWPORT3 iface,
279                                                     LPDIRECTDRAWSURFACE* lplpDDSurface,
280                                                     LPBOOL lpValid)
281 {
282     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
283     FIXME("(%p/%p)->(%p,%p): stub!\n", This, iface, lplpDDSurface, lpValid);
284     return DD_OK;
285 }
286
287 HRESULT WINAPI
288 Main_IDirect3DViewportImpl_3_2_1_Clear(LPDIRECT3DVIEWPORT3 iface,
289                                        DWORD dwCount,
290                                        LPD3DRECT lpRects,
291                                        DWORD dwFlags)
292 {
293     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
294     DWORD color = 0x00000000;
295     
296     TRACE("(%p/%p)->(%08lx,%p,%08lx)\n", This, iface, dwCount, lpRects, dwFlags);
297     if (This->active_device == NULL) {
298         ERR(" Trying to clear a viewport not attached to a device !\n");
299         return D3DERR_VIEWPORTHASNODEVICE;
300     }
301     if (dwFlags & D3DCLEAR_TARGET) {
302         if (This->background == NULL) {
303             ERR(" Trying to clear the color buffer without background material !\n");
304         } else {
305             color = 
306               ((int) ((This->background->mat.u.diffuse.u1.r) * 255) << 16) |
307               ((int) ((This->background->mat.u.diffuse.u2.g) * 255) <<  8) |
308               ((int) ((This->background->mat.u.diffuse.u3.b) * 255) <<  0) |
309               ((int) ((This->background->mat.u.diffuse.u4.a) * 255) << 24);
310         }
311     }
312     return This->active_device->clear(This->active_device, dwCount, lpRects, 
313                                       dwFlags & (D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET),
314                                       color, 1.0, 0x00000000);
315 }
316
317 HRESULT WINAPI
318 Main_IDirect3DViewportImpl_3_2_1_AddLight(LPDIRECT3DVIEWPORT3 iface,
319                                           LPDIRECT3DLIGHT lpDirect3DLight)
320 {
321     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
322     IDirect3DLightImpl *lpDirect3DLightImpl = ICOM_OBJECT(IDirect3DLightImpl, IDirect3DLight, lpDirect3DLight);
323     DWORD i = 0;
324     DWORD map = This->map_lights;
325     
326     TRACE("(%p/%p)->(%p)\n", This, iface, lpDirect3DLight);
327     
328     if (This->num_lights >= 8)
329         return DDERR_INVALIDPARAMS;
330
331     /* Find a light number and update both light and viewports objects accordingly */
332     while(map&1) {
333         map>>=1;
334         i++;
335     }
336     lpDirect3DLightImpl->dwLightIndex = i;
337     This->num_lights++;
338     This->map_lights |= 1<<i;
339
340     /* Add the light in the 'linked' chain */
341     lpDirect3DLightImpl->next = This->lights;
342     This->lights = lpDirect3DLightImpl;
343
344     /* Attach the light to the viewport */
345     lpDirect3DLightImpl->active_viewport = This;
346     
347     /* If active, activate the light */
348     if (This->active_device != NULL) {
349         lpDirect3DLightImpl->activate(lpDirect3DLightImpl);
350     }
351     
352     return DD_OK;
353 }
354
355 HRESULT WINAPI
356 Main_IDirect3DViewportImpl_3_2_1_DeleteLight(LPDIRECT3DVIEWPORT3 iface,
357                                              LPDIRECT3DLIGHT lpDirect3DLight)
358 {
359     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
360     IDirect3DLightImpl *lpDirect3DLightImpl = ICOM_OBJECT(IDirect3DLightImpl, IDirect3DLight, lpDirect3DLight);
361     IDirect3DLightImpl *cur_light, *prev_light = NULL;
362     
363     TRACE("(%p/%p)->(%p)\n", This, iface, lpDirect3DLight);
364     cur_light = This->lights;
365     while (cur_light != NULL) {
366         if (cur_light == lpDirect3DLightImpl) {
367             lpDirect3DLightImpl->desactivate(lpDirect3DLightImpl);
368             if (prev_light == NULL) This->lights = cur_light->next;
369             else prev_light->next = cur_light->next;
370             /* Detach the light to the viewport */
371             cur_light->active_viewport = NULL;
372             This->num_lights--;
373             This->map_lights &= ~(1<<lpDirect3DLightImpl->dwLightIndex);
374             return DD_OK;
375         }
376         prev_light = cur_light;
377         cur_light = cur_light->next;
378     }
379     return DDERR_INVALIDPARAMS;
380 }
381
382 HRESULT WINAPI
383 Main_IDirect3DViewportImpl_3_2_1_NextLight(LPDIRECT3DVIEWPORT3 iface,
384                                            LPDIRECT3DLIGHT lpDirect3DLight,
385                                            LPDIRECT3DLIGHT* lplpDirect3DLight,
386                                            DWORD dwFlags)
387 {
388     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
389     FIXME("(%p/%p)->(%p,%p,%08lx): stub!\n", This, iface, lpDirect3DLight, lplpDirect3DLight, dwFlags);
390     return DD_OK;
391 }
392
393 HRESULT WINAPI
394 Main_IDirect3DViewportImpl_3_2_GetViewport2(LPDIRECT3DVIEWPORT3 iface,
395                                             LPD3DVIEWPORT2 lpData)
396 {
397     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
398     DWORD dwSize;
399     TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
400     if (This->use_vp2 != 1) {
401         ERR("  Requesting to get a D3DVIEWPORT2 struct where a D3DVIEWPORT was set !\n");
402         return DDERR_INVALIDPARAMS;
403     }
404     dwSize = lpData->dwSize;
405     memset(lpData, 0, dwSize);
406     memcpy(lpData, &(This->viewports.vp2), dwSize);
407
408     if (TRACE_ON(ddraw)) {
409         TRACE("  returning D3DVIEWPORT2 :\n");
410         _dump_D3DVIEWPORT2(lpData);
411     }
412     
413     return DD_OK;
414 }
415
416 HRESULT WINAPI
417 Main_IDirect3DViewportImpl_3_2_SetViewport2(LPDIRECT3DVIEWPORT3 iface,
418                                             LPD3DVIEWPORT2 lpData)
419 {
420     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
421     LPDIRECT3DVIEWPORT3 current_viewport;
422     TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
423
424     if (TRACE_ON(ddraw)) {
425         TRACE("  getting D3DVIEWPORT2 :\n");
426         _dump_D3DVIEWPORT2(lpData);
427     }
428
429     This->use_vp2 = 1;
430     memset(&(This->viewports.vp2), 0, sizeof(This->viewports.vp2));
431     memcpy(&(This->viewports.vp2), lpData, lpData->dwSize);
432
433     if (This->active_device) {
434       IDirect3DDevice3_GetCurrentViewport(ICOM_INTERFACE(This->active_device, IDirect3DDevice3), &current_viewport);
435       if (ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, current_viewport) == This)
436         This->activate(This);
437       IDirect3DViewport3_Release(current_viewport);
438     }
439
440     return DD_OK;
441 }
442
443 HRESULT WINAPI
444 Main_IDirect3DViewportImpl_3_SetBackgroundDepth2(LPDIRECT3DVIEWPORT3 iface,
445                                                  LPDIRECTDRAWSURFACE4 lpDDS)
446 {
447     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
448     FIXME("(%p/%p)->(%p): stub!\n", This, iface, lpDDS);
449     return DD_OK;
450 }
451
452 HRESULT WINAPI
453 Main_IDirect3DViewportImpl_3_GetBackgroundDepth2(LPDIRECT3DVIEWPORT3 iface,
454                                                  LPDIRECTDRAWSURFACE4* lplpDDS,
455                                                  LPBOOL lpValid)
456 {
457     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
458     FIXME("(%p/%p)->(%p,%p): stub!\n", This, iface, lplpDDS, lpValid);
459     return DD_OK;
460 }
461
462 HRESULT WINAPI
463 Main_IDirect3DViewportImpl_3_Clear2(LPDIRECT3DVIEWPORT3 iface,
464                                     DWORD dwCount,
465                                     LPD3DRECT lpRects,
466                                     DWORD dwFlags,
467                                     DWORD dwColor,
468                                     D3DVALUE dvZ,
469                                     DWORD dwStencil)
470 {
471     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
472     TRACE("(%p/%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, iface, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
473     if (This->active_device == NULL) {
474         ERR(" Trying to clear a viewport not attached to a device !\n");
475         return D3DERR_VIEWPORTHASNODEVICE;
476     }
477     return This->active_device->clear(This->active_device, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
478 }
479
480 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
481 # define XCAST(fun)     (typeof(VTABLE_IDirect3DViewport3.fun))
482 #else
483 # define XCAST(fun)     (void*)
484 #endif
485
486 IDirect3DViewport3Vtbl VTABLE_IDirect3DViewport3 =
487 {
488     XCAST(QueryInterface) Main_IDirect3DViewportImpl_3_2_1_QueryInterface,
489     XCAST(AddRef) Main_IDirect3DViewportImpl_3_2_1_AddRef,
490     XCAST(Release) Main_IDirect3DViewportImpl_3_2_1_Release,
491     XCAST(Initialize) Main_IDirect3DViewportImpl_3_2_1_Initialize,
492     XCAST(GetViewport) Main_IDirect3DViewportImpl_3_2_1_GetViewport,
493     XCAST(SetViewport) Main_IDirect3DViewportImpl_3_2_1_SetViewport,
494     XCAST(TransformVertices) Main_IDirect3DViewportImpl_3_2_1_TransformVertices,
495     XCAST(LightElements) Main_IDirect3DViewportImpl_3_2_1_LightElements,
496     XCAST(SetBackground) Main_IDirect3DViewportImpl_3_2_1_SetBackground,
497     XCAST(GetBackground) Main_IDirect3DViewportImpl_3_2_1_GetBackground,
498     XCAST(SetBackgroundDepth) Main_IDirect3DViewportImpl_3_2_1_SetBackgroundDepth,
499     XCAST(GetBackgroundDepth) Main_IDirect3DViewportImpl_3_2_1_GetBackgroundDepth,
500     XCAST(Clear) Main_IDirect3DViewportImpl_3_2_1_Clear,
501     XCAST(AddLight) Main_IDirect3DViewportImpl_3_2_1_AddLight,
502     XCAST(DeleteLight) Main_IDirect3DViewportImpl_3_2_1_DeleteLight,
503     XCAST(NextLight) Main_IDirect3DViewportImpl_3_2_1_NextLight,
504     XCAST(GetViewport2) Main_IDirect3DViewportImpl_3_2_GetViewport2,
505     XCAST(SetViewport2) Main_IDirect3DViewportImpl_3_2_SetViewport2,
506     XCAST(SetBackgroundDepth2) Main_IDirect3DViewportImpl_3_SetBackgroundDepth2,
507     XCAST(GetBackgroundDepth2) Main_IDirect3DViewportImpl_3_GetBackgroundDepth2,
508     XCAST(Clear2) Main_IDirect3DViewportImpl_3_Clear2,
509 };
510
511 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
512 #undef XCAST
513 #endif
514
515
516
517
518 HRESULT d3dviewport_create(IDirect3DViewportImpl **obj, IDirectDrawImpl *d3d)
519 {
520     IDirect3DViewportImpl *object;
521
522     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DViewportImpl));
523     if (object == NULL) return DDERR_OUTOFMEMORY;
524
525     object->ref = 1;
526     object->d3d = d3d;
527     object->activate = activate;
528     object->use_vp2 = 0xFF;
529     object->next = NULL;
530     object->lights = NULL;
531     object->num_lights = 0;
532     object->map_lights = 0;
533     
534     ICOM_INIT_INTERFACE(object, IDirect3DViewport3, VTABLE_IDirect3DViewport3);
535
536     *obj = object;
537
538     TRACE(" creating implementation at %p.\n", *obj);
539     
540     return D3D_OK;
541 }