msi: Fix possible free of uninitialized pointer.
[wine] / dlls / ddraw / viewport.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
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winerror.h"
31 #include "objbase.h"
32 #include "wingdi.h"
33 #include "ddraw.h"
34 #include "d3d.h"
35 #include "wine/debug.h"
36
37 #include "d3d_private.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
40
41 static void activate(IDirect3DViewportImpl* This) {
42     IDirect3DLightImpl* light;
43     D3DVIEWPORT7 vp;
44     
45     /* Activate all the lights associated with this context */
46     light = This->lights;
47
48     while (light != NULL) {
49         light->activate(light);
50         light = light->next;
51     }
52
53     /* And copy the values in the structure used by the device */
54     if (This->use_vp2) {
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;
61     } else {
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;
68     }
69     
70     /* And also set the viewport */
71     IDirect3DDevice7_SetViewport(ICOM_INTERFACE(This->active_device, IDirect3DDevice7), &vp);
72 }
73
74
75 static void _dump_D3DVIEWPORT(D3DVIEWPORT *lpvp)
76 {
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);
87 }
88
89 static void _dump_D3DVIEWPORT2(D3DVIEWPORT2 *lpvp)
90 {
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);
101 }
102
103 HRESULT WINAPI
104 Main_IDirect3DViewportImpl_3_2_1_QueryInterface(LPDIRECT3DVIEWPORT3 iface,
105                                                 REFIID riid,
106                                                 LPVOID* obp)
107 {
108     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
109     TRACE("(%p/%p)->(%s,%p)\n", This, iface, debugstr_guid(riid), obp);
110
111     *obp = NULL;
112
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);
120         return S_OK;
121     }
122     FIXME("(%p): interface for IID %s NOT found!\n", This, debugstr_guid(riid));
123     return OLE_E_ENUM_NOMORE;
124 }
125
126 ULONG WINAPI
127 Main_IDirect3DViewportImpl_3_2_1_AddRef(LPDIRECT3DVIEWPORT3 iface)
128 {
129     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
130     ULONG ref = InterlockedIncrement(&This->ref);
131
132     TRACE("(%p/%p)->() incrementing from %lu.\n", This, iface, ref - 1);
133
134     return ref;
135 }
136
137 ULONG WINAPI
138 Main_IDirect3DViewportImpl_3_2_1_Release(LPDIRECT3DVIEWPORT3 iface)
139 {
140     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
141     ULONG ref = InterlockedDecrement(&This->ref);
142
143     TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, ref + 1);
144
145     if (!ref) {
146         HeapFree(GetProcessHeap(), 0, This);
147         return 0;
148     }
149     return ref;
150 }
151
152
153 HRESULT WINAPI
154 Main_IDirect3DViewportImpl_3_2_1_Initialize(LPDIRECT3DVIEWPORT3 iface,
155                                             LPDIRECT3D lpDirect3D)
156 {
157     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
158     TRACE("(%p/%p)->(%p) no-op...\n", This, iface, lpDirect3D);
159     return DD_OK;
160 }
161
162 HRESULT WINAPI
163 Main_IDirect3DViewportImpl_3_2_1_GetViewport(LPDIRECT3DVIEWPORT3 iface,
164                                              LPD3DVIEWPORT lpData)
165 {
166     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
167     DWORD dwSize;
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;
172     }
173     dwSize = lpData->dwSize;
174     memset(lpData, 0, dwSize);
175     memcpy(lpData, &(This->viewports.vp1), dwSize);
176
177     if (TRACE_ON(ddraw)) {
178         TRACE("  returning D3DVIEWPORT :\n");
179         _dump_D3DVIEWPORT(lpData);
180     }
181     
182     return DD_OK;
183 }
184
185 HRESULT WINAPI
186 Main_IDirect3DViewportImpl_3_2_1_SetViewport(LPDIRECT3DVIEWPORT3 iface,
187                                              LPD3DVIEWPORT lpData)
188 {
189     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
190     LPDIRECT3DVIEWPORT3 current_viewport;
191     TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
192
193     if (TRACE_ON(ddraw)) {
194         TRACE("  getting D3DVIEWPORT :\n");
195         _dump_D3DVIEWPORT(lpData);
196     }
197
198     This->use_vp2 = 0;
199     memset(&(This->viewports.vp1), 0, sizeof(This->viewports.vp1));
200     memcpy(&(This->viewports.vp1), lpData, lpData->dwSize);
201
202     /* Tests on two games show that these values are never used properly so override
203        them with proper ones :-)
204     */
205     This->viewports.vp1.dvMinZ = 0.0;
206     This->viewports.vp1.dvMaxZ = 1.0;
207
208     if (This->active_device) {
209       IDirect3DDevice3_GetCurrentViewport(ICOM_INTERFACE(This->active_device, IDirect3DDevice3), &current_viewport);
210       if (ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, current_viewport) == This)
211           This->activate(This);
212       IDirect3DViewport3_Release(current_viewport);
213     }
214
215     return DD_OK;
216 }
217
218 HRESULT WINAPI
219 Main_IDirect3DViewportImpl_3_2_1_TransformVertices(LPDIRECT3DVIEWPORT3 iface,
220                                                    DWORD dwVertexCount,
221                                                    LPD3DTRANSFORMDATA lpData,
222                                                    DWORD dwFlags,
223                                                    LPDWORD lpOffScreen)
224 {
225     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
226     FIXME("(%p/%p)->(%08lx,%p,%08lx,%p): stub!\n", This, iface, dwVertexCount, lpData, dwFlags, lpOffScreen);
227     if (lpOffScreen)
228         *lpOffScreen = 0;
229     return DD_OK;
230 }
231
232 HRESULT WINAPI
233 Main_IDirect3DViewportImpl_3_2_1_LightElements(LPDIRECT3DVIEWPORT3 iface,
234                                                DWORD dwElementCount,
235                                                LPD3DLIGHTDATA lpData)
236 {
237     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
238     FIXME("(%p/%p)->(%08lx,%p): stub!\n", This, iface, dwElementCount, lpData);
239     return DD_OK;
240 }
241
242 HRESULT WINAPI
243 Main_IDirect3DViewportImpl_3_2_1_SetBackground(LPDIRECT3DVIEWPORT3 iface,
244                                                D3DMATERIALHANDLE hMat)
245 {
246     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
247     TRACE("(%p/%p)->(%08lx)\n", This, iface, (DWORD) hMat);
248     
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);
255
256     return DD_OK;
257 }
258
259 HRESULT WINAPI
260 Main_IDirect3DViewportImpl_3_2_1_GetBackground(LPDIRECT3DVIEWPORT3 iface,
261                                                LPD3DMATERIALHANDLE lphMat,
262                                                LPBOOL lpValid)
263 {
264     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
265     FIXME("(%p/%p)->(%p,%p): stub!\n", This, iface, lphMat, lpValid);
266     return DD_OK;
267 }
268
269 HRESULT WINAPI
270 Main_IDirect3DViewportImpl_3_2_1_SetBackgroundDepth(LPDIRECT3DVIEWPORT3 iface,
271                                                     LPDIRECTDRAWSURFACE lpDDSurface)
272 {
273     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
274     FIXME("(%p/%p)->(%p): stub!\n", This, iface, lpDDSurface);
275     return DD_OK;
276 }
277
278 HRESULT WINAPI
279 Main_IDirect3DViewportImpl_3_2_1_GetBackgroundDepth(LPDIRECT3DVIEWPORT3 iface,
280                                                     LPDIRECTDRAWSURFACE* lplpDDSurface,
281                                                     LPBOOL lpValid)
282 {
283     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
284     FIXME("(%p/%p)->(%p,%p): stub!\n", This, iface, lplpDDSurface, lpValid);
285     return DD_OK;
286 }
287
288 HRESULT WINAPI
289 Main_IDirect3DViewportImpl_3_2_1_Clear(LPDIRECT3DVIEWPORT3 iface,
290                                        DWORD dwCount,
291                                        LPD3DRECT lpRects,
292                                        DWORD dwFlags)
293 {
294     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
295     DWORD color = 0x00000000;
296     
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;
301     }
302     if (dwFlags & D3DCLEAR_TARGET) {
303         if (This->background == NULL) {
304             ERR(" Trying to clear the color buffer without background material !\n");
305         } else {
306             color = 
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);
311         }
312     }
313     return This->active_device->clear(This->active_device, dwCount, lpRects, 
314                                       dwFlags & (D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET),
315                                       color, 1.0, 0x00000000);
316 }
317
318 HRESULT WINAPI
319 Main_IDirect3DViewportImpl_3_2_1_AddLight(LPDIRECT3DVIEWPORT3 iface,
320                                           LPDIRECT3DLIGHT lpDirect3DLight)
321 {
322     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
323     IDirect3DLightImpl *lpDirect3DLightImpl = ICOM_OBJECT(IDirect3DLightImpl, IDirect3DLight, lpDirect3DLight);
324     DWORD i = 0;
325     DWORD map = This->map_lights;
326     
327     TRACE("(%p/%p)->(%p)\n", This, iface, lpDirect3DLight);
328     
329     if (This->num_lights >= 8)
330         return DDERR_INVALIDPARAMS;
331
332     /* Find a light number and update both light and viewports objects accordingly */
333     while(map&1) {
334         map>>=1;
335         i++;
336     }
337     lpDirect3DLightImpl->dwLightIndex = i;
338     This->num_lights++;
339     This->map_lights |= 1<<i;
340
341     /* Add the light in the 'linked' chain */
342     lpDirect3DLightImpl->next = This->lights;
343     This->lights = lpDirect3DLightImpl;
344
345     /* Attach the light to the viewport */
346     lpDirect3DLightImpl->active_viewport = This;
347     
348     /* If active, activate the light */
349     if (This->active_device != NULL) {
350         lpDirect3DLightImpl->activate(lpDirect3DLightImpl);
351     }
352     
353     return DD_OK;
354 }
355
356 HRESULT WINAPI
357 Main_IDirect3DViewportImpl_3_2_1_DeleteLight(LPDIRECT3DVIEWPORT3 iface,
358                                              LPDIRECT3DLIGHT lpDirect3DLight)
359 {
360     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
361     IDirect3DLightImpl *lpDirect3DLightImpl = ICOM_OBJECT(IDirect3DLightImpl, IDirect3DLight, lpDirect3DLight);
362     IDirect3DLightImpl *cur_light, *prev_light = NULL;
363     
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;
373             This->num_lights--;
374             This->map_lights &= ~(1<<lpDirect3DLightImpl->dwLightIndex);
375             return DD_OK;
376         }
377         prev_light = cur_light;
378         cur_light = cur_light->next;
379     }
380     return DDERR_INVALIDPARAMS;
381 }
382
383 HRESULT WINAPI
384 Main_IDirect3DViewportImpl_3_2_1_NextLight(LPDIRECT3DVIEWPORT3 iface,
385                                            LPDIRECT3DLIGHT lpDirect3DLight,
386                                            LPDIRECT3DLIGHT* lplpDirect3DLight,
387                                            DWORD dwFlags)
388 {
389     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
390     FIXME("(%p/%p)->(%p,%p,%08lx): stub!\n", This, iface, lpDirect3DLight, lplpDirect3DLight, dwFlags);
391     return DD_OK;
392 }
393
394 HRESULT WINAPI
395 Main_IDirect3DViewportImpl_3_2_GetViewport2(LPDIRECT3DVIEWPORT3 iface,
396                                             LPD3DVIEWPORT2 lpData)
397 {
398     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
399     DWORD dwSize;
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;
404     }
405     dwSize = lpData->dwSize;
406     memset(lpData, 0, dwSize);
407     memcpy(lpData, &(This->viewports.vp2), dwSize);
408
409     if (TRACE_ON(ddraw)) {
410         TRACE("  returning D3DVIEWPORT2 :\n");
411         _dump_D3DVIEWPORT2(lpData);
412     }
413     
414     return DD_OK;
415 }
416
417 HRESULT WINAPI
418 Main_IDirect3DViewportImpl_3_2_SetViewport2(LPDIRECT3DVIEWPORT3 iface,
419                                             LPD3DVIEWPORT2 lpData)
420 {
421     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
422     LPDIRECT3DVIEWPORT3 current_viewport;
423     TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
424
425     if (TRACE_ON(ddraw)) {
426         TRACE("  getting D3DVIEWPORT2 :\n");
427         _dump_D3DVIEWPORT2(lpData);
428     }
429
430     This->use_vp2 = 1;
431     memset(&(This->viewports.vp2), 0, sizeof(This->viewports.vp2));
432     memcpy(&(This->viewports.vp2), lpData, lpData->dwSize);
433
434     if (This->active_device) {
435       IDirect3DDevice3_GetCurrentViewport(ICOM_INTERFACE(This->active_device, IDirect3DDevice3), &current_viewport);
436       if (ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, current_viewport) == This)
437         This->activate(This);
438       IDirect3DViewport3_Release(current_viewport);
439     }
440
441     return DD_OK;
442 }
443
444 HRESULT WINAPI
445 Main_IDirect3DViewportImpl_3_SetBackgroundDepth2(LPDIRECT3DVIEWPORT3 iface,
446                                                  LPDIRECTDRAWSURFACE4 lpDDS)
447 {
448     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
449     FIXME("(%p/%p)->(%p): stub!\n", This, iface, lpDDS);
450     return DD_OK;
451 }
452
453 HRESULT WINAPI
454 Main_IDirect3DViewportImpl_3_GetBackgroundDepth2(LPDIRECT3DVIEWPORT3 iface,
455                                                  LPDIRECTDRAWSURFACE4* lplpDDS,
456                                                  LPBOOL lpValid)
457 {
458     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
459     FIXME("(%p/%p)->(%p,%p): stub!\n", This, iface, lplpDDS, lpValid);
460     return DD_OK;
461 }
462
463 HRESULT WINAPI
464 Main_IDirect3DViewportImpl_3_Clear2(LPDIRECT3DVIEWPORT3 iface,
465                                     DWORD dwCount,
466                                     LPD3DRECT lpRects,
467                                     DWORD dwFlags,
468                                     DWORD dwColor,
469                                     D3DVALUE dvZ,
470                                     DWORD dwStencil)
471 {
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;
477     }
478     return This->active_device->clear(This->active_device, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
479 }
480
481 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
482 # define XCAST(fun)     (typeof(VTABLE_IDirect3DViewport3.fun))
483 #else
484 # define XCAST(fun)     (void*)
485 #endif
486
487 static const IDirect3DViewport3Vtbl VTABLE_IDirect3DViewport3 =
488 {
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,
510 };
511
512 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
513 #undef XCAST
514 #endif
515
516
517
518
519 HRESULT d3dviewport_create(IDirect3DViewportImpl **obj, IDirectDrawImpl *d3d)
520 {
521     IDirect3DViewportImpl *object;
522
523     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DViewportImpl));
524     if (object == NULL) return DDERR_OUTOFMEMORY;
525
526     object->ref = 1;
527     object->d3d = d3d;
528     object->activate = activate;
529     object->use_vp2 = 0xFF;
530     object->next = NULL;
531     object->lights = NULL;
532     object->num_lights = 0;
533     object->map_lights = 0;
534     
535     ICOM_INIT_INTERFACE(object, IDirect3DViewport3, VTABLE_IDirect3DViewport3);
536
537     *obj = object;
538
539     TRACE(" creating implementation at %p.\n", *obj);
540     
541     return D3D_OK;
542 }