ddraw: Hold the lock in IDirect3DDevice methods.
[wine] / dlls / ddraw / device.c
1 /*
2  * Copyright (c) 1998-2004 Lionel Ulmer
3  * Copyright (c) 2002-2005 Christian Costa
4  * Copyright (c) 2006 Stefan Dösinger
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  * IDirect3DDevice implementation, version 1, 2, 3 and 7. Rendering is relayed
21  * to WineD3D, some minimal DirectDraw specific management is handled here.
22  * The Direct3DDevice is NOT the parent of the WineD3DDevice, because d3d
23  * is initialized when DirectDraw creates the primary surface.
24  * Some type management is necessary, because some D3D types changed between
25  * D3D7 and D3D9.
26  *
27  */
28
29 #include "config.h"
30 #include "wine/port.h"
31 #include "wine/debug.h"
32
33 #include <assert.h>
34 #include <stdarg.h>
35 #include <string.h>
36 #include <stdlib.h>
37
38 #define COBJMACROS
39
40 #include "windef.h"
41 #include "winbase.h"
42 #include "winerror.h"
43 #include "wingdi.h"
44 #include "wine/exception.h"
45
46 #include "ddraw.h"
47 #include "d3d.h"
48
49 #include "ddraw_private.h"
50
51 WINE_DEFAULT_DEBUG_CHANNEL(d3d7);
52 WINE_DECLARE_DEBUG_CHANNEL(ddraw_thunk);
53
54 /* The device ID */
55 const GUID IID_D3DDEVICE_WineD3D = {
56   0xaef72d43,
57   0xb09a,
58   0x4b7b,
59   { 0xb7,0x98,0xc6,0x8a,0x77,0x2d,0x72,0x2a }
60 };
61
62 /*****************************************************************************
63  * IUnknown Methods. Common for Version 1, 2, 3 and 7 
64  *****************************************************************************/
65
66 /*****************************************************************************
67  * IDirect3DDevice7::QueryInterface
68  *
69  * Used to query other interfaces from a Direct3DDevice interface.
70  * It can return interface pointers to all Direct3DDevice versions as well
71  * as IDirectDraw and IDirect3D. For a link to QueryInterface
72  * rules see ddraw.c, IDirectDraw7::QueryInterface
73  *
74  * Exists in Version 1, 2, 3 and 7
75  *
76  * Params:
77  *  refiid: Interface ID queried for
78  *  obj: Used to return the interface pointer
79  *
80  * Returns:
81  *  D3D_OK or E_NOINTERFACE
82  *
83  *****************************************************************************/
84 static HRESULT WINAPI
85 IDirect3DDeviceImpl_7_QueryInterface(IDirect3DDevice7 *iface,
86                                      REFIID refiid,
87                                      void **obj)
88 {
89     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
90     TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(refiid), obj);
91
92     /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
93     *obj = NULL;
94
95     if(!refiid)
96         return DDERR_INVALIDPARAMS;
97
98     if ( IsEqualGUID( &IID_IUnknown, refiid ) )
99     {
100         *obj = ICOM_INTERFACE(This, IDirect3DDevice7);
101     }
102
103     /* Check DirectDraw Interfac\ 1s */
104     else if( IsEqualGUID( &IID_IDirectDraw7, refiid ) )
105     {
106         *obj = ICOM_INTERFACE(This->ddraw, IDirectDraw7);
107         TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
108     }
109     else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
110     {
111         *obj = ICOM_INTERFACE(This->ddraw, IDirectDraw4);
112         TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
113     }
114     else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
115     {
116         *obj = ICOM_INTERFACE(This->ddraw, IDirectDraw2);
117         TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
118     }
119     else if( IsEqualGUID( &IID_IDirectDraw, refiid ) )
120     {
121         *obj = ICOM_INTERFACE(This->ddraw, IDirectDraw);
122         TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
123     }
124
125     /* Direct3D */
126     else if ( IsEqualGUID( &IID_IDirect3D  , refiid ) )
127     {
128         *obj = ICOM_INTERFACE(This->ddraw, IDirect3D);
129         TRACE("(%p) Returning IDirect3D interface at %p\n", This, *obj);
130     }
131     else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) )
132     {
133         *obj = ICOM_INTERFACE(This->ddraw, IDirect3D2);
134         TRACE("(%p) Returning IDirect3D2 interface at %p\n", This, *obj);
135     }
136     else if ( IsEqualGUID( &IID_IDirect3D3 , refiid ) )
137     {
138         *obj = ICOM_INTERFACE(This->ddraw, IDirect3D3);
139         TRACE("(%p) Returning IDirect3D3 interface at %p\n", This, *obj);
140     }
141     else if ( IsEqualGUID( &IID_IDirect3D7 , refiid ) )
142     {
143         *obj = ICOM_INTERFACE(This->ddraw, IDirect3D7);
144         TRACE("(%p) Returning IDirect3D7 interface at %p\n", This, *obj);
145     }
146
147     /* Direct3DDevice */
148     else if ( IsEqualGUID( &IID_IDirect3DDevice  , refiid ) )
149     {
150         *obj = ICOM_INTERFACE(This, IDirect3DDevice);
151         TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
152     }
153     else if ( IsEqualGUID( &IID_IDirect3DDevice2  , refiid ) ) {
154         *obj = ICOM_INTERFACE(This, IDirect3DDevice2);
155         TRACE("(%p) Returning IDirect3DDevice2 interface at %p\n", This, *obj);
156     }
157     else if ( IsEqualGUID( &IID_IDirect3DDevice3  , refiid ) ) {
158         *obj = ICOM_INTERFACE(This, IDirect3DDevice3);
159         TRACE("(%p) Returning IDirect3DDevice3 interface at %p\n", This, *obj);
160     }
161     else if ( IsEqualGUID( &IID_IDirect3DDevice7  , refiid ) ) {
162         *obj = ICOM_INTERFACE(This, IDirect3DDevice7);
163         TRACE("(%p) Returning IDirect3DDevice7 interface at %p\n", This, *obj);
164     }
165
166     /* Unknown interface */
167     else
168     {
169         ERR("(%p)->(%s, %p): No interface found\n", This, debugstr_guid(refiid), obj);
170         return E_NOINTERFACE;
171     }
172
173     /* AddRef the returned interface */
174     IUnknown_AddRef( (IUnknown *) *obj);
175     return D3D_OK;
176 }
177
178 static HRESULT WINAPI
179 Thunk_IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface,
180                                            REFIID riid,
181                                            void **obj)
182 {
183     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
184     TRACE_(ddraw_thunk)("(%p)->(%s,%p) thunking to IDirect3DDevice7 interface.\n", This, debugstr_guid(riid), obj);
185     return IDirect3DDevice7_QueryInterface(ICOM_INTERFACE(This, IDirect3DDevice7),
186                                            riid,
187                                            obj);
188 }
189
190 static HRESULT WINAPI
191 Thunk_IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface,
192                                            REFIID riid,
193                                            void **obj)
194 {
195     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
196     TRACE_(ddraw_thunk)("(%p)->(%s,%p) thunking to IDirect3DDevice7 interface.\n", This, debugstr_guid(riid), obj);
197     return IDirect3DDevice7_QueryInterface(ICOM_INTERFACE(This, IDirect3DDevice7),
198                                            riid,
199                                            obj);
200 }
201
202 static HRESULT WINAPI
203 Thunk_IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface,
204                                            REFIID riid,
205                                            void **obp)
206 {
207     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
208     TRACE_(ddraw_thunk)("(%p)->(%s,%p) thunking to IDirect3DDevice7 interface.\n", This, debugstr_guid(riid), obp);
209     return IDirect3DDevice7_QueryInterface(ICOM_INTERFACE(This, IDirect3DDevice7),
210                                            riid,
211                                            obp);
212 }
213
214 /*****************************************************************************
215  * IDirect3DDevice7::AddRef
216  *
217  * Increases the refcount....
218  * The most exciting Method, definitely
219  *
220  * Exists in Version 1, 2, 3 and 7
221  *
222  * Returns:
223  *  The new refcount
224  *
225  *****************************************************************************/
226 static ULONG WINAPI
227 IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
228 {
229     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
230     ULONG ref = InterlockedIncrement(&This->ref);
231
232     TRACE("(%p) : incrementing from %u.\n", This, ref -1);
233
234     return ref;
235 }
236
237 static ULONG WINAPI
238 Thunk_IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
239 {
240     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
241     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
242     return IDirect3DDevice7_AddRef(ICOM_INTERFACE(This, IDirect3DDevice7));
243 }
244
245 static ULONG WINAPI
246 Thunk_IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
247 {
248     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
249     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
250     return IDirect3DDevice7_AddRef(ICOM_INTERFACE(This, IDirect3DDevice7));
251 }
252
253 static ULONG WINAPI
254 Thunk_IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
255 {
256     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", iface);
257     return IDirect3DDevice7_AddRef(COM_INTERFACE_CAST(IDirect3DDeviceImpl, IDirect3DDevice, IDirect3DDevice7, iface));
258 }
259
260 /*****************************************************************************
261  * IDirect3DDevice7::Release
262  *
263  * Decreases the refcount of the interface
264  * When the refcount is reduced to 0, the object is destroyed.
265  *
266  * Exists in Version 1, 2, 3 and 7
267  *
268  * Returns:d
269  *  The new refcount
270  *
271  *****************************************************************************/
272 static ULONG WINAPI
273 IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
274 {
275     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
276     ULONG ref = InterlockedDecrement(&This->ref);
277
278     TRACE("(%p)->() decrementing from %u.\n", This, ref +1);
279
280     /* This method doesn't destroy the WineD3DDevice, because it's still in use for
281      * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
282      * when the render target is released
283      */
284     if (ref == 0)
285     {
286         IParent *IndexBufferParent;
287         DWORD i;
288
289         EnterCriticalSection(&ddraw_cs);
290         /* Free the index buffer. */
291         IWineD3DDevice_SetIndices(This->wineD3DDevice,
292                                   NULL,
293                                   0);
294         IWineD3DIndexBuffer_GetParent(This->indexbuffer,
295                                       (IUnknown **) &IndexBufferParent);
296         IParent_Release(IndexBufferParent); /* Once for the getParent */
297         if( IParent_Release(IndexBufferParent) != 0)  /* And now to destroy it */
298         {
299             ERR(" (%p) Something is still holding the index buffer parent %p\n", This, IndexBufferParent);
300         }
301
302         /* There is no need to unset the vertex buffer here, IWineD3DDevice_Uninit3D will do that when
303          * destroying the primary stateblock. If a vertex buffer is destroyed while it is bound
304          * IDirect3DVertexBuffer::Release will unset it.
305          */
306
307         /* Restore the render targets */
308         if(This->OffScreenTarget)
309         {
310             WINED3DVIEWPORT vp;
311
312             vp.X = 0;
313             vp.Y = 0;
314             vp.Width = This->ddraw->d3d_target->surface_desc.dwWidth;
315             vp.Height = This->ddraw->d3d_target->surface_desc.dwHeight;
316             vp.MinZ = 0.0;
317             vp.MaxZ = 1.0;
318             IWineD3DDevice_SetViewport(This->wineD3DDevice,
319                                        &vp);
320
321             /* Set the device up to render to the front buffer since the back buffer will
322              * vanish soon.
323              */
324             IWineD3DDevice_SetRenderTarget(This->wineD3DDevice, 0,
325                                            This->ddraw->d3d_target->WineD3DSurface);
326             /* This->target is the offscreen target.
327              * This->ddraw->d3d_target is the target used by DDraw
328              */
329             TRACE("(%p) Release: Using %p as front buffer, %p as back buffer\n", This, This->ddraw->d3d_target, NULL);
330             IWineD3DDevice_SetFrontBackBuffers(This->wineD3DDevice,
331                                                This->ddraw->d3d_target->WineD3DSurface,
332                                                NULL);
333         }
334
335         /* Release the WineD3DDevice. This won't destroy it */
336         if(IWineD3DDevice_Release(This->wineD3DDevice) <= 0)
337         {
338             ERR(" (%p) The wineD3D device %p was destroyed unexpectadely. Prepare for trouble\n", This, This->wineD3DDevice);
339         }
340
341         /* The texture handles should be unset by now, but there might be some bits
342          * missing in our reference counting(needs test). Do a sanity check
343          */
344         for(i = 0; i < This->numHandles; i++)
345         {
346             if(This->Handles[i].ptr)
347             {
348                 switch(This->Handles[i].type)
349                 {
350                     case DDrawHandle_Texture:
351                     {
352                         IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *) This->Handles[i].ptr;
353                         FIXME("Texture Handle %d not unset properly\n", i + 1);
354                         surf->Handle = 0;
355                     }
356                     break;
357
358                     case DDrawHandle_Material:
359                     {
360                         IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) This->Handles[i].ptr;
361                         FIXME("Material handle %d not unset properly\n", i + 1);
362                         mat->Handle = 0;
363                     }
364                     break;
365
366                     case DDrawHandle_Matrix:
367                     {
368                         /* No fixme here because this might happen because of sloppy apps */
369                         WARN("Leftover matrix handle %d, deleting\n", i + 1);
370                         IDirect3DDevice_DeleteMatrix(ICOM_INTERFACE(This, IDirect3DDevice),
371                                                      i + 1);
372                     }
373                     break;
374
375                     case DDrawHandle_StateBlock:
376                     {
377                         /* No fixme here because this might happen because of sloppy apps */
378                         WARN("Leftover stateblock handle %d, deleting\n", i + 1);
379                         IDirect3DDevice7_DeleteStateBlock(ICOM_INTERFACE(This, IDirect3DDevice7),
380                                                           i + 1);
381                     }
382                     break;
383
384                     default:
385                         FIXME("Unknown handle %d not unset properly\n", i + 1);
386                 }
387             }
388         }
389
390         HeapFree(GetProcessHeap(), 0, This->Handles);
391
392         TRACE("Releasing target %p %p\n", This->target, This->ddraw->d3d_target);
393         /* Release the render target and the WineD3D render target
394          * (See IDirect3D7::CreateDevice for more comments on this)
395          */
396         IDirectDrawSurface7_Release(ICOM_INTERFACE(This->target, IDirectDrawSurface7));
397         IDirectDrawSurface7_Release(ICOM_INTERFACE(This->ddraw->d3d_target,IDirectDrawSurface7));
398         TRACE("Target release done\n");
399
400         This->ddraw->d3ddevice = NULL;
401
402         /* Now free the structure */
403         HeapFree(GetProcessHeap(), 0, This);
404         LeaveCriticalSection(&ddraw_cs);
405     }
406
407     TRACE("Done\n");
408     return ref;
409 }
410
411 static ULONG WINAPI
412 Thunk_IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
413 {
414     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
415     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
416     return IDirect3DDevice7_Release(ICOM_INTERFACE(This, IDirect3DDevice7));
417 }
418
419 static ULONG WINAPI
420 Thunk_IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
421 {
422     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
423     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
424     return IDirect3DDevice7_Release(ICOM_INTERFACE(This, IDirect3DDevice7));
425 }
426
427 static ULONG WINAPI
428 Thunk_IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
429 {
430     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
431     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
432     return IDirect3DDevice7_Release(ICOM_INTERFACE(This, IDirect3DDevice7));
433 }
434
435 /*****************************************************************************
436  * IDirect3DDevice Methods
437  *****************************************************************************/
438
439 /*****************************************************************************
440  * IDirect3DDevice::Initialize
441  *
442  * Initializes a Direct3DDevice. This implementation is a no-op, as all
443  * initialization is done at create time.
444  *
445  * Exists in Version 1
446  *
447  * Parameters:
448  *  No idea what they mean, as the MSDN page is gone
449  *
450  * Returns: DD_OK
451  *
452  *****************************************************************************/
453 static HRESULT WINAPI
454 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
455                                  IDirect3D *Direct3D, GUID *guid,
456                                  D3DDEVICEDESC *Desc)
457 {
458     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
459
460     /* It shouldn't be crucial, but print a FIXME, I'm interested if
461      * any game calls it and when
462      */
463     FIXME("(%p)->(%p,%p,%p): No-op!\n", This, Direct3D, guid, Desc);
464
465     return D3D_OK;
466 }
467
468 /*****************************************************************************
469  * IDirect3DDevice7::GetCaps
470  *
471  * Retrieves the device's capabilities
472  *
473  * This implementation is used for Version 7 only, the older versions have
474  * their own implementation.
475  *
476  * Parameters:
477  *  Desc: Pointer to a D3DDEVICEDESC7 structure to fill
478  *
479  * Returns:
480  *  D3D_OK on success
481  *  D3DERR_* if a problem occurs. See WineD3D
482  *
483  *****************************************************************************/
484 static HRESULT WINAPI
485 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
486                               D3DDEVICEDESC7 *Desc)
487 {
488     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
489     D3DDEVICEDESC OldDesc;
490     TRACE("(%p)->(%p)\n", This, Desc);
491
492     /* Call the same function used by IDirect3D, this saves code */
493     return IDirect3DImpl_GetCaps(This->ddraw->wineD3D, &OldDesc, Desc);
494 }
495
496 /*****************************************************************************
497  * IDirect3DDevice3::GetCaps
498  *
499  * Retrieves the capabilities of the hardware device and the emulation
500  * device. For Wine, hardware and emulation are the same (it's all HW).
501  *
502  * This implementation is used for Version 1, 2, and 3. Version 7 has its own
503  *
504  * Parameters:
505  *  HWDesc: Structure to fill with the HW caps
506  *  HelDesc: Structure to fill with the hardare emulation caps
507  *
508  * Returns:
509  *  D3D_OK on success
510  *  D3DERR_* if a problem occurs. See WineD3D
511  *
512  *****************************************************************************/
513 static HRESULT WINAPI
514 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
515                               D3DDEVICEDESC *HWDesc,
516                               D3DDEVICEDESC *HelDesc)
517 {
518     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
519     D3DDEVICEDESC7 newDesc;
520     HRESULT hr;
521     TRACE("(%p)->(%p,%p)\n", iface, HWDesc, HelDesc);
522
523     hr = IDirect3DImpl_GetCaps(This->ddraw->wineD3D, HWDesc, &newDesc);
524     if(hr != D3D_OK) return hr;
525
526     *HelDesc = *HWDesc;
527     return D3D_OK;
528 }
529
530 static HRESULT WINAPI
531 Thunk_IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
532                                     D3DDEVICEDESC *D3DHWDevDesc,
533                                     D3DDEVICEDESC *D3DHELDevDesc)
534 {
535     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
536     TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice3 interface.\n", This, D3DHWDevDesc, D3DHELDevDesc);
537     return IDirect3DDevice3_GetCaps(ICOM_INTERFACE(This, IDirect3DDevice3),
538                                     D3DHWDevDesc,
539                                     D3DHELDevDesc);
540 }
541
542 static HRESULT WINAPI
543 Thunk_IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
544                                     D3DDEVICEDESC *D3DHWDevDesc,
545                                     D3DDEVICEDESC *D3DHELDevDesc)
546 {
547     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
548     TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice3 interface.\n", This, D3DHWDevDesc, D3DHELDevDesc);
549     return IDirect3DDevice3_GetCaps(ICOM_INTERFACE(This, IDirect3DDevice3),
550                                     D3DHWDevDesc,
551                                     D3DHELDevDesc);
552 }
553
554 /*****************************************************************************
555  * IDirect3DDevice2::SwapTextureHandles
556  *
557  * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
558  *
559  * Parameters:
560  *  Tex1, Tex2: The 2 Textures to swap
561  *
562  * Returns:
563  *  D3D_OK
564  *
565  *****************************************************************************/
566 static HRESULT WINAPI
567 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
568                                          IDirect3DTexture2 *Tex1,
569                                          IDirect3DTexture2 *Tex2)
570 {
571     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
572     DWORD swap;
573     IDirectDrawSurfaceImpl *surf1 = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture2, Tex1);
574     IDirectDrawSurfaceImpl *surf2 = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture2, Tex2);
575     TRACE("(%p)->(%p,%p)\n", This, surf1, surf2);
576
577     EnterCriticalSection(&ddraw_cs);
578     This->Handles[surf1->Handle - 1].ptr = surf2;
579     This->Handles[surf2->Handle - 1].ptr = surf1;
580
581     swap = surf2->Handle;
582     surf2->Handle = surf1->Handle;
583     surf1->Handle = swap;
584     LeaveCriticalSection(&ddraw_cs);
585
586     return D3D_OK;
587 }
588
589 static HRESULT WINAPI
590 Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
591                                                IDirect3DTexture *D3DTex1,
592                                                IDirect3DTexture *D3DTex2)
593 {
594     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
595     IDirectDrawSurfaceImpl *surf1 = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture, D3DTex1);
596     IDirectDrawSurfaceImpl *surf2 = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture, D3DTex2);
597     TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice2 interface.\n", This, surf1, surf2);
598     return IDirect3DDevice2_SwapTextureHandles(ICOM_INTERFACE(This, IDirect3DDevice2),
599                                                ICOM_INTERFACE(surf1, IDirect3DTexture2),
600                                                ICOM_INTERFACE(surf2, IDirect3DTexture2));
601 }
602
603 /*****************************************************************************
604  * IDirect3DDevice3::GetStats
605  *
606  * This method seems to retrieve some stats from the device.
607  * The MSDN documentation doesn't exist any more, but the D3DSTATS
608  * structure suggests that the amout of drawn primitives and processed
609  * vertices is returned.
610  *
611  * Exists in Version 1, 2 and 3
612  *
613  * Parameters:
614  *  Stats: Pointer to a D3DSTATS structure to be filled
615  *
616  * Returns:
617  *  D3D_OK on success
618  *  DDERR_INVALIDPARAMS if Stats == NULL
619  *
620  *****************************************************************************/
621 static HRESULT WINAPI
622 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
623                                D3DSTATS *Stats)
624 {
625     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
626     FIXME("(%p)->(%p): Stub!\n", This, Stats);
627
628     if(!Stats)
629         return DDERR_INVALIDPARAMS;
630
631     /* Fill the Stats with 0 */
632     Stats->dwTrianglesDrawn = 0;
633     Stats->dwLinesDrawn = 0;
634     Stats->dwPointsDrawn = 0;
635     Stats->dwSpansDrawn = 0;
636     Stats->dwVerticesProcessed = 0;
637
638     return D3D_OK;
639 }
640
641 static HRESULT WINAPI
642 Thunk_IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface,
643                                      D3DSTATS *Stats)
644 {
645     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
646     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, Stats);
647     return IDirect3DDevice3_GetStats(ICOM_INTERFACE(This, IDirect3DDevice3),
648                                      Stats);
649 }
650
651 static HRESULT WINAPI
652 Thunk_IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface,
653                                      D3DSTATS *Stats)
654 {
655     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
656     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, Stats);
657     return IDirect3DDevice3_GetStats(ICOM_INTERFACE(This, IDirect3DDevice3),
658                                      Stats);
659 }
660
661 /*****************************************************************************
662  * IDirect3DDevice::CreateExecuteBuffer
663  *
664  * Creates an IDirect3DExecuteBuffer, used for rendering with a
665  * Direct3DDevice.
666  *
667  * Version 1 only.
668  *
669  * Params:
670  *  Desc: Buffer description
671  *  ExecuteBuffer: Address to return the Interface pointer at
672  *  UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
673  *            support
674  *
675  * Returns:
676  *  CLASS_E_NOAGGREGATION if UnkOuter != NULL
677  *  DDERR_OUTOFMEMORY if we ran out of memory
678  *  D3D_OK on success
679  *
680  *****************************************************************************/
681 static HRESULT WINAPI
682 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
683                                           D3DEXECUTEBUFFERDESC *Desc,
684                                           IDirect3DExecuteBuffer **ExecuteBuffer,
685                                           IUnknown *UnkOuter)
686 {
687     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
688     IDirect3DExecuteBufferImpl* object;
689     TRACE("(%p)->(%p,%p,%p)!\n", This, Desc, ExecuteBuffer, UnkOuter);
690
691     if(UnkOuter)
692         return CLASS_E_NOAGGREGATION;
693
694     /* Allocate the new Execute Buffer */
695     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
696     if(!object)
697     {
698         ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
699         return DDERR_OUTOFMEMORY;
700     }
701
702     ICOM_INIT_INTERFACE(object, IDirect3DExecuteBuffer, IDirect3DExecuteBuffer_Vtbl);
703
704     object->ref = 1;
705     object->d3ddev = This;
706
707     /* Initializes memory */
708     memcpy(&object->desc, Desc, Desc->dwSize);
709
710     /* No buffer given */
711     if ((object->desc.dwFlags & D3DDEB_LPDATA) == 0)
712         object->desc.lpData = NULL;
713
714     /* No buffer size given */
715     if ((object->desc.dwFlags & D3DDEB_BUFSIZE) == 0)
716         object->desc.dwBufferSize = 0;
717
718     /* Create buffer if asked */
719     if ((object->desc.lpData == NULL) && (object->desc.dwBufferSize > 0))
720     {
721         object->need_free = TRUE;
722         object->desc.lpData = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,object->desc.dwBufferSize);
723         if(!object->desc.lpData)
724         {
725             ERR("Out of memory when allocating the execute buffer data\n");
726             HeapFree(GetProcessHeap(), 0, object);
727             return DDERR_OUTOFMEMORY;
728         }
729     }
730     else
731     {
732         object->need_free = FALSE;
733     }
734
735     /* No vertices for the moment */
736     object->vertex_data = NULL;
737
738     object->desc.dwFlags |= D3DDEB_LPDATA;
739
740     object->indices = NULL;
741     object->nb_indices = 0;
742
743     *ExecuteBuffer = ICOM_INTERFACE(object, IDirect3DExecuteBuffer);
744
745     TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
746
747     return D3D_OK;
748 }
749
750 /*****************************************************************************
751  * IDirect3DDevice::Execute
752  *
753  * Executes all the stuff in an execute buffer.
754  *
755  * Params:
756  *  ExecuteBuffer: The buffer to execute
757  *  Viewport: The viewport used for rendering
758  *  Flags: Some flags
759  *
760  * Returns:
761  *  DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
762  *  D3D_OK on success
763  *
764  *****************************************************************************/
765 static HRESULT WINAPI
766 IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
767                               IDirect3DExecuteBuffer *ExecuteBuffer,
768                               IDirect3DViewport *Viewport,
769                               DWORD Flags)
770 {
771     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
772     IDirect3DExecuteBufferImpl *Direct3DExecuteBufferImpl = ICOM_OBJECT(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, ExecuteBuffer);
773     IDirect3DViewportImpl *Direct3DViewportImpl = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Viewport);
774
775     TRACE("(%p)->(%p,%p,%08x)\n", This, Direct3DExecuteBufferImpl, Direct3DViewportImpl, Flags);
776
777     if(!Direct3DExecuteBufferImpl)
778         return DDERR_INVALIDPARAMS;
779
780     /* Execute... */
781     EnterCriticalSection(&ddraw_cs);
782     IDirect3DExecuteBufferImpl_Execute(Direct3DExecuteBufferImpl, This, Direct3DViewportImpl);
783     LeaveCriticalSection(&ddraw_cs);
784
785     return D3D_OK;
786 }
787
788 /*****************************************************************************
789  * IDirect3DDevice3::AddViewport
790  *
791  * Add a Direct3DViewport to the device's viewport list. These viewports
792  * are wrapped to IDirect3DDevice7 viewports in viewport.c
793  *
794  * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
795  * are the same interfaces.
796  *
797  * Params:
798  *  Viewport: The viewport to add
799  *
800  * Returns:
801  *  DDERR_INVALIDPARAMS if Viewport == NULL
802  *  D3D_OK on success
803  *
804  *****************************************************************************/
805 static HRESULT WINAPI
806 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
807                                   IDirect3DViewport3 *Viewport)
808 {
809     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
810     IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Viewport);
811
812     TRACE("(%p)->(%p)\n", This, vp);
813
814     /* Sanity check */
815     if(!vp)
816         return DDERR_INVALIDPARAMS;
817
818     EnterCriticalSection(&ddraw_cs);
819     vp->next = This->viewport_list;
820     This->viewport_list = vp;
821     LeaveCriticalSection(&ddraw_cs);
822
823     return D3D_OK;
824 }
825
826 static HRESULT WINAPI
827 Thunk_IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
828                                         IDirect3DViewport2 *Direct3DViewport2)
829 {
830     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
831     IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Direct3DViewport2);
832     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
833     return IDirect3DDevice3_AddViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
834                                         ICOM_INTERFACE(vp, IDirect3DViewport3));
835 }
836
837 static HRESULT WINAPI
838 Thunk_IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
839                                         IDirect3DViewport *Direct3DViewport)
840 {
841     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
842     IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Direct3DViewport);
843     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
844     return IDirect3DDevice3_AddViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
845                                         ICOM_INTERFACE(vp, IDirect3DViewport3));
846 }
847
848 /*****************************************************************************
849  * IDirect3DDevice3::DeleteViewport
850  *
851  * Deletes a Direct3DViewport from the device's viewport list.
852  *
853  * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
854  * are equal.
855  *
856  * Params:
857  *  Viewport: The viewport to delete
858  *
859  * Returns:
860  *  D3D_OK on success
861  *  DDERR_INVALIDPARAMS if the viewport wasn't found in the list
862  *
863  *****************************************************************************/
864 static HRESULT WINAPI
865 IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface,
866                                      IDirect3DViewport3 *Viewport)
867 {
868     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
869     IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *) Viewport;
870     IDirect3DViewportImpl *cur_viewport, *prev_viewport = NULL;
871
872     TRACE("(%p)->(%p)\n", This, vp);
873
874     EnterCriticalSection(&ddraw_cs);
875     cur_viewport = This->viewport_list;
876     while (cur_viewport != NULL)
877     {
878         if (cur_viewport == vp)
879         {
880             if (prev_viewport == NULL) This->viewport_list = cur_viewport->next;
881             else prev_viewport->next = cur_viewport->next;
882             /* TODO : add desactivate of the viewport and all associated lights... */
883             LeaveCriticalSection(&ddraw_cs);
884             return D3D_OK;
885         }
886         prev_viewport = cur_viewport;
887         cur_viewport = cur_viewport->next;
888     }
889
890     LeaveCriticalSection(&ddraw_cs);
891     return DDERR_INVALIDPARAMS;
892 }
893
894 static HRESULT WINAPI
895 Thunk_IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
896                                            IDirect3DViewport2 *Direct3DViewport2)
897 {
898     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
899     IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Direct3DViewport2);
900     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
901     return IDirect3DDevice3_DeleteViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
902                                            ICOM_INTERFACE(vp, IDirect3DViewport3));
903 }
904
905 static HRESULT WINAPI
906 Thunk_IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
907                                            IDirect3DViewport *Direct3DViewport)
908 {
909     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
910     IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Direct3DViewport);
911     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
912     return IDirect3DDevice3_DeleteViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
913                                            ICOM_INTERFACE(vp, IDirect3DViewport3));
914 }
915
916 /*****************************************************************************
917  * IDirect3DDevice3::NextViewport
918  *
919  * Returns a viewport from the viewport list, depending on the
920  * passed viewport and the flags.
921  *
922  * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
923  * are equal.
924  *
925  * Params:
926  *  Viewport: Viewport to use for beginning the search
927  *  Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
928  *
929  * Returns:
930  *  D3D_OK on success
931  *  DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
932  *
933  *****************************************************************************/
934 static HRESULT WINAPI
935 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
936                                    IDirect3DViewport3 *Viewport3,
937                                    IDirect3DViewport3 **lplpDirect3DViewport3,
938                                    DWORD Flags)
939 {
940     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
941     IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Viewport3);
942     IDirect3DViewportImpl *res = NULL;
943
944     TRACE("(%p)->(%p,%p,%08x)\n", This, vp, lplpDirect3DViewport3, Flags);
945
946     if(!vp)
947     {
948         *lplpDirect3DViewport3 = NULL;
949         return DDERR_INVALIDPARAMS;
950     }
951
952
953     EnterCriticalSection(&ddraw_cs);
954     switch (Flags)
955     {
956         case D3DNEXT_NEXT:
957         {
958             res = vp->next;
959         }
960         break;
961         case D3DNEXT_HEAD:
962         {
963             res = This->viewport_list;
964         }
965         break;
966         case D3DNEXT_TAIL:
967         {
968             IDirect3DViewportImpl *cur_viewport = This->viewport_list;
969             if (cur_viewport != NULL)
970             {
971                 while (cur_viewport->next != NULL) cur_viewport = cur_viewport->next;
972             }
973             res = cur_viewport;
974         }
975         break;
976         default:
977             *lplpDirect3DViewport3 = NULL;
978             LeaveCriticalSection(&ddraw_cs);
979             return DDERR_INVALIDPARAMS;
980     }
981
982     *lplpDirect3DViewport3 = ICOM_INTERFACE(res, IDirect3DViewport3);
983     LeaveCriticalSection(&ddraw_cs);
984     return D3D_OK;
985 }
986
987 static HRESULT WINAPI
988 Thunk_IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
989                                          IDirect3DViewport2 *Viewport2,
990                                          IDirect3DViewport2 **lplpDirect3DViewport2,
991                                          DWORD Flags)
992 {
993     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
994     IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Viewport2);
995     IDirect3DViewport3 *res;
996     HRESULT hr;
997     TRACE_(ddraw_thunk)("(%p)->(%p,%p,%08x) thunking to IDirect3DDevice3 interface.\n", This, vp, lplpDirect3DViewport2, Flags);
998     hr = IDirect3DDevice3_NextViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
999                                        ICOM_INTERFACE(vp, IDirect3DViewport3),
1000                                        &res,
1001                                        Flags);
1002     *lplpDirect3DViewport2 = (IDirect3DViewport2 *) COM_INTERFACE_CAST(IDirect3DViewportImpl, IDirect3DViewport3, IDirect3DViewport3, res);
1003     return hr;
1004 }
1005
1006 static HRESULT WINAPI
1007 Thunk_IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
1008                                          IDirect3DViewport *Viewport,
1009                                          IDirect3DViewport **lplpDirect3DViewport,
1010                                          DWORD Flags)
1011 {
1012     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1013     IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Viewport);
1014     IDirect3DViewport3 *res;
1015     HRESULT hr;
1016     TRACE_(ddraw_thunk)("(%p)->(%p,%p,%08x) thunking to IDirect3DDevice3 interface.\n", This, vp, lplpDirect3DViewport, Flags);
1017     hr = IDirect3DDevice3_NextViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
1018                                        ICOM_INTERFACE(vp, IDirect3DViewport3),
1019                                        &res,
1020                                        Flags);
1021     *lplpDirect3DViewport = (IDirect3DViewport *) COM_INTERFACE_CAST(IDirect3DViewportImpl, IDirect3DViewport3, IDirect3DViewport3, res);
1022     return hr;
1023 }
1024
1025 /*****************************************************************************
1026  * IDirect3DDevice::Pick
1027  *
1028  * Executes an execute buffer without performing rendering. Instead, a
1029  * list of primitives that intersect with (x1,y1) of the passed rectangle
1030  * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
1031  * this list.
1032  *
1033  * Version 1 only
1034  *
1035  * Params:
1036  *  ExecuteBuffer: Buffer to execute
1037  *  Viewport: Viewport to use for execution
1038  *  Flags: None are defined, according to the SDK
1039  *  Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
1040  *        x2 and y2 are ignored.
1041  *
1042  * Returns:
1043  *  D3D_OK because it's a stub
1044  *
1045  *****************************************************************************/
1046 static HRESULT WINAPI
1047 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
1048                            IDirect3DExecuteBuffer *ExecuteBuffer,
1049                            IDirect3DViewport *Viewport,
1050                            DWORD Flags,
1051                            D3DRECT *Rect)
1052 {
1053     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1054     IDirect3DExecuteBufferImpl *execbuf = ICOM_OBJECT(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, ExecuteBuffer);
1055     IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Viewport);
1056     FIXME("(%p)->(%p,%p,%08x,%p): stub!\n", This, execbuf, vp, Flags, Rect);
1057
1058     return D3D_OK;
1059 }
1060
1061 /*****************************************************************************
1062  * IDirect3DDevice::GetPickRecords
1063  *
1064  * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1065  *
1066  * Version 1 only
1067  *
1068  * Params:
1069  *  Count: Pointer to a DWORD containing the numbers of pick records to
1070  *         retrieve
1071  *  D3DPickRec: Address to store the resulting D3DPICKRECORD arry.
1072  *
1073  * Returns:
1074  *  D3D_OK, because it's a stub
1075  *
1076  *****************************************************************************/
1077 static HRESULT WINAPI
1078 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1079                                      DWORD *Count,
1080                                      D3DPICKRECORD *D3DPickRec)
1081 {
1082     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1083     FIXME("(%p)->(%p,%p): stub!\n", This, Count, D3DPickRec);
1084
1085     return D3D_OK;
1086 }
1087
1088 /*****************************************************************************
1089  * IDirect3DDevice7::EnumTextureformats
1090  *
1091  * Enumerates the supported texture formats. It has a list of all possible
1092  * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1093  * WineD3D supports it. If so, then it is passed to the app.
1094  *
1095  * This is for Version 7 and 3, older versions have a different
1096  * callback function and their own implementation
1097  *
1098  * Params:
1099  *  Callback: Callback to call for each enumerated format
1100  *  Arg: Argument to pass to the callback
1101  *
1102  * Returns:
1103  *  D3D_OK on success
1104  *  DDERR_INVALIDPARAMS if Callback == NULL
1105  *
1106  *****************************************************************************/
1107 static HRESULT WINAPI
1108 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1109                                          LPD3DENUMPIXELFORMATSCALLBACK Callback,
1110                                          void *Arg)
1111 {
1112     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1113     HRESULT hr;
1114     int i;
1115
1116     WINED3DFORMAT FormatList[] = {
1117         /* 32 bit */
1118         WINED3DFMT_A8R8G8B8,
1119         WINED3DFMT_X8R8G8B8,
1120         /* 24 bit */
1121         WINED3DFMT_R8G8B8,
1122         /* 16 Bit */
1123         WINED3DFMT_A1R5G5B5,
1124         WINED3DFMT_A4R4G4B4,
1125         WINED3DFMT_R5G6B5,
1126         WINED3DFMT_X1R5G5B5,
1127         /* 8 Bit */
1128         WINED3DFMT_R3G3B2,
1129         WINED3DFMT_P8,
1130         /* FOURCC codes */
1131         WINED3DFMT_DXT1,
1132         WINED3DFMT_DXT3,
1133         WINED3DFMT_DXT5,
1134     };
1135
1136     WINED3DFORMAT BumpFormatList[] = {
1137         WINED3DFMT_V8U8,
1138         WINED3DFMT_L6V5U5,
1139         WINED3DFMT_X8L8V8U8,
1140         WINED3DFMT_Q8W8V8U8,
1141         WINED3DFMT_V16U16,
1142         WINED3DFMT_W11V11U10,
1143         WINED3DFMT_A2W10V10U10
1144     };
1145
1146     TRACE("(%p)->(%p,%p): Relay\n", This, Callback, Arg);
1147
1148     if(!Callback)
1149         return DDERR_INVALIDPARAMS;
1150
1151     EnterCriticalSection(&ddraw_cs);
1152     for(i = 0; i < sizeof(FormatList) / sizeof(WINED3DFORMAT); i++)
1153     {
1154         hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1155                                         0 /* Adapter */,
1156                                         0 /* DeviceType */,
1157                                         0 /* AdapterFormat */,
1158                                         0 /* Usage */,
1159                                         0 /* ResourceType */,
1160                                         FormatList[i]);
1161         if(hr == D3D_OK)
1162         {
1163             DDPIXELFORMAT pformat;
1164
1165             memset(&pformat, 0, sizeof(pformat));
1166             pformat.dwSize = sizeof(pformat);
1167             PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1168
1169             TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1170             hr = Callback(&pformat, Arg);
1171             if(hr != DDENUMRET_OK)
1172             {
1173                 TRACE("Format enumeration cancelled by application\n");
1174                 LeaveCriticalSection(&ddraw_cs);
1175                 return D3D_OK;
1176             }
1177         }
1178     }
1179
1180     for(i = 0; i < sizeof(BumpFormatList) / sizeof(WINED3DFORMAT); i++)
1181     {
1182         hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1183                                         0 /* Adapter */,
1184                                         0 /* DeviceType */,
1185                                         0 /* AdapterFormat */,
1186                                         WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1187                                         0 /* ResourceType */,
1188                                         BumpFormatList[i]);
1189         if(hr == D3D_OK)
1190         {
1191             DDPIXELFORMAT pformat;
1192
1193             memset(&pformat, 0, sizeof(pformat));
1194             pformat.dwSize = sizeof(pformat);
1195             PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1196
1197             TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1198             hr = Callback(&pformat, Arg);
1199             if(hr != DDENUMRET_OK)
1200             {
1201                 TRACE("Format enumeration cancelled by application\n");
1202                 LeaveCriticalSection(&ddraw_cs);
1203                 return D3D_OK;
1204             }
1205         }
1206     }
1207     TRACE("End of enumeration\n");
1208     LeaveCriticalSection(&ddraw_cs);
1209     return D3D_OK;
1210 }
1211
1212 static HRESULT WINAPI
1213 Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1214                                                LPD3DENUMPIXELFORMATSCALLBACK Callback,
1215                                                void *Arg)
1216 {
1217     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1218     TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice7 interface.\n", This, Callback, Arg);
1219     return IDirect3DDevice7_EnumTextureFormats(ICOM_INTERFACE(This, IDirect3DDevice7),
1220                                                Callback,
1221                                                Arg);
1222 }
1223
1224 /*****************************************************************************
1225  * IDirect3DDevice2::EnumTextureformats
1226  *
1227  * EnumTextureFormats for Version 1 and 2, see
1228  * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1229  *
1230  * This version has a different callback and does not enumerate FourCC
1231  * formats
1232  *
1233  *****************************************************************************/
1234 static HRESULT WINAPI
1235 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1236                                          LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1237                                          void *Arg)
1238 {
1239     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1240     HRESULT hr;
1241     int i;
1242
1243     WINED3DFORMAT FormatList[] = {
1244         /* 32 bit */
1245         WINED3DFMT_A8R8G8B8,
1246         WINED3DFMT_X8R8G8B8,
1247         /* 24 bit */
1248         WINED3DFMT_R8G8B8,
1249         /* 16 Bit */
1250         WINED3DFMT_A1R5G5B5,
1251         WINED3DFMT_A4R4G4B4,
1252         WINED3DFMT_R5G6B5,
1253         WINED3DFMT_X1R5G5B5,
1254         /* 8 Bit */
1255         WINED3DFMT_R3G3B2,
1256         WINED3DFMT_P8,
1257         /* FOURCC codes - Not in this version*/
1258     };
1259
1260     TRACE("(%p)->(%p,%p): Relay\n", This, Callback, Arg);
1261
1262     if(!Callback)
1263         return DDERR_INVALIDPARAMS;
1264
1265     EnterCriticalSection(&ddraw_cs);
1266     for(i = 0; i < sizeof(FormatList) / sizeof(WINED3DFORMAT); i++)
1267     {
1268         hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1269                                         0 /* Adapter */,
1270                                         0 /* DeviceType */,
1271                                         0 /* AdapterFormat */,
1272                                         0 /* Usage */,
1273                                         0 /* ResourceType */,
1274                                         FormatList[i]);
1275         if(hr == D3D_OK)
1276         {
1277             DDSURFACEDESC sdesc;
1278
1279             memset(&sdesc, 0, sizeof(sdesc));
1280             sdesc.dwSize = sizeof(sdesc);
1281             sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1282             sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1283             sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1284             PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1285
1286             TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1287             hr = Callback(&sdesc, Arg);
1288             if(hr != DDENUMRET_OK)
1289             {
1290                 TRACE("Format enumeration cancelled by application\n");
1291                 LeaveCriticalSection(&ddraw_cs);
1292                 return D3D_OK;
1293             }
1294         }
1295     }
1296     TRACE("End of enumeration\n");
1297     LeaveCriticalSection(&ddraw_cs);
1298     return D3D_OK;
1299 }
1300
1301 static HRESULT WINAPI
1302 Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1303                                                LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1304                                                void *Arg)
1305 {
1306     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1307     TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice2 interface.\n", This, Callback, Arg);
1308     return IDirect3DDevice2_EnumTextureFormats(ICOM_INTERFACE(This, IDirect3DDevice2),
1309                                                Callback,
1310                                                Arg);
1311 }
1312
1313 /*****************************************************************************
1314  * IDirect3DDevice::CreateMatrix
1315  *
1316  * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1317  * allocated for the handle.
1318  *
1319  * Version 1 only
1320  *
1321  * Params
1322  *  D3DMatHandle: Address to return the handle at
1323  *
1324  * Returns:
1325  *  D3D_OK on success
1326  *  DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1327  *
1328  *****************************************************************************/
1329 static HRESULT WINAPI
1330 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1331 {
1332     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1333     D3DMATRIX *Matrix;
1334     TRACE("(%p)->(%p)\n", This, D3DMatHandle);
1335
1336     if(!D3DMatHandle)
1337         return DDERR_INVALIDPARAMS;
1338
1339     Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1340     if(!Matrix)
1341     {
1342         ERR("Out of memory when allocating a D3DMATRIX\n");
1343         return DDERR_OUTOFMEMORY;
1344     }
1345
1346     EnterCriticalSection(&ddraw_cs);
1347     *D3DMatHandle = IDirect3DDeviceImpl_CreateHandle(This);
1348     if(!(*D3DMatHandle))
1349     {
1350         ERR("Failed to create a matrix handle\n");
1351         HeapFree(GetProcessHeap(), 0, Matrix);
1352         LeaveCriticalSection(&ddraw_cs);
1353         return DDERR_OUTOFMEMORY;
1354     }
1355     This->Handles[(DWORD) *D3DMatHandle - 1].ptr = Matrix;
1356     This->Handles[(DWORD) *D3DMatHandle - 1].type = DDrawHandle_Matrix;
1357     TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1358
1359     LeaveCriticalSection(&ddraw_cs);
1360     return D3D_OK;
1361 }
1362
1363 /*****************************************************************************
1364  * IDirect3DDevice::SetMatrix
1365  *
1366  * Sets a matrix for a matrix handle. The matrix is copied into the memory
1367  * allocated for the handle
1368  *
1369  * Version 1 only
1370  *
1371  * Params:
1372  *  D3DMatHandle: Handle to set the matrix to
1373  *  D3DMatrix: Matrix to set
1374  *
1375  * Returns:
1376  *  D3D_OK on success
1377  *  DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1378  *   to set is NULL
1379  *
1380  *****************************************************************************/
1381 static HRESULT WINAPI
1382 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1383                                 D3DMATRIXHANDLE D3DMatHandle,
1384                                 D3DMATRIX *D3DMatrix)
1385 {
1386     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1387     TRACE("(%p)->(%08x,%p)\n", This, (DWORD) D3DMatHandle, D3DMatrix);
1388
1389     if( (!D3DMatHandle) || (!D3DMatrix) )
1390         return DDERR_INVALIDPARAMS;
1391
1392     EnterCriticalSection(&ddraw_cs);
1393     if(D3DMatHandle > This->numHandles)
1394     {
1395         ERR("Handle %d out of range\n", D3DMatHandle);
1396         LeaveCriticalSection(&ddraw_cs);
1397         return DDERR_INVALIDPARAMS;
1398     }
1399     else if(This->Handles[D3DMatHandle - 1].type != DDrawHandle_Matrix)
1400     {
1401         ERR("Handle %d is not a matrix handle\n", D3DMatHandle);
1402         LeaveCriticalSection(&ddraw_cs);
1403         return DDERR_INVALIDPARAMS;
1404     }
1405
1406     if (TRACE_ON(d3d7))
1407         dump_D3DMATRIX(D3DMatrix);
1408
1409     *((D3DMATRIX *) This->Handles[D3DMatHandle - 1].ptr) = *D3DMatrix;
1410
1411     LeaveCriticalSection(&ddraw_cs);
1412     return D3D_OK;
1413 }
1414
1415 /*****************************************************************************
1416  * IDirect3DDevice::SetMatrix
1417  *
1418  * Returns the content of a D3DMATRIX handle
1419  *
1420  * Version 1 only
1421  *
1422  * Params:
1423  *  D3DMatHandle: Matrix handle to read the content from
1424  *  D3DMatrix: Address to store the content at
1425  *
1426  * Returns:
1427  *  D3D_OK on success
1428  *  DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1429  *
1430  *****************************************************************************/
1431 static HRESULT WINAPI
1432 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1433                                 D3DMATRIXHANDLE D3DMatHandle,
1434                                 D3DMATRIX *D3DMatrix)
1435 {
1436     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1437     TRACE("(%p)->(%08x,%p)\n", This, (DWORD) D3DMatHandle, D3DMatrix);
1438
1439     if(!D3DMatrix)
1440         return DDERR_INVALIDPARAMS;
1441     if(!D3DMatHandle)
1442         return DDERR_INVALIDPARAMS;
1443
1444     EnterCriticalSection(&ddraw_cs);
1445     if(D3DMatHandle > This->numHandles)
1446     {
1447         ERR("Handle %d out of range\n", D3DMatHandle);
1448         LeaveCriticalSection(&ddraw_cs);
1449         return DDERR_INVALIDPARAMS;
1450     }
1451     else if(This->Handles[D3DMatHandle - 1].type != DDrawHandle_Matrix)
1452     {
1453         ERR("Handle %d is not a matrix handle\n", D3DMatHandle);
1454         LeaveCriticalSection(&ddraw_cs);
1455         return DDERR_INVALIDPARAMS;
1456     }
1457
1458     /* The handle is simply a pointer to a D3DMATRIX structure */
1459     *D3DMatrix = *((D3DMATRIX *) This->Handles[D3DMatHandle - 1].ptr);
1460
1461     LeaveCriticalSection(&ddraw_cs);
1462     return D3D_OK;
1463 }
1464
1465 /*****************************************************************************
1466  * IDirect3DDevice::DeleteMatrix
1467  *
1468  * Destroys a Matrix handle. Frees the memory and unsets the handle data
1469  *
1470  * Version 1 only
1471  *
1472  * Params:
1473  *  D3DMatHandle: Handle to destroy
1474  *
1475  * Returns:
1476  *  D3D_OK on success
1477  *  DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1478  *
1479  *****************************************************************************/
1480 static HRESULT WINAPI
1481 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1482                                    D3DMATRIXHANDLE D3DMatHandle)
1483 {
1484     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1485     TRACE("(%p)->(%08x)\n", This, (DWORD) D3DMatHandle);
1486
1487     if(!D3DMatHandle)
1488         return DDERR_INVALIDPARAMS;
1489
1490     EnterCriticalSection(&ddraw_cs);
1491     if(D3DMatHandle > This->numHandles)
1492     {
1493         ERR("Handle %d out of range\n", D3DMatHandle);
1494         LeaveCriticalSection(&ddraw_cs);
1495         return DDERR_INVALIDPARAMS;
1496     }
1497     else if(This->Handles[D3DMatHandle - 1].type != DDrawHandle_Matrix)
1498     {
1499         ERR("Handle %d is not a matrix handle\n", D3DMatHandle);
1500         LeaveCriticalSection(&ddraw_cs);
1501         return DDERR_INVALIDPARAMS;
1502     }
1503
1504     HeapFree(GetProcessHeap(), 0, This->Handles[D3DMatHandle - 1].ptr);
1505     This->Handles[D3DMatHandle - 1].ptr = NULL;
1506     This->Handles[D3DMatHandle - 1].type = DDrawHandle_Unknown;
1507
1508     LeaveCriticalSection(&ddraw_cs);
1509     return D3D_OK;
1510 }
1511
1512 /*****************************************************************************
1513  * IDirect3DDevice7::BeginScene
1514  *
1515  * This method must be called before any rendering is performed.
1516  * IDirect3DDevice::EndScene has to be called after the scene is complete
1517  *
1518  * Version 1, 2, 3 and 7
1519  *
1520  * Returns:
1521  *  D3D_OK on success, for details see IWineD3DDevice::BeginScene
1522  *  D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1523  *  started scene).
1524  *
1525  *****************************************************************************/
1526 static HRESULT WINAPI
1527 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1528 {
1529     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1530     HRESULT hr;
1531     TRACE("(%p): Relay\n", This);
1532
1533     EnterCriticalSection(&ddraw_cs);
1534     hr = IWineD3DDevice_BeginScene(This->wineD3DDevice);
1535     LeaveCriticalSection(&ddraw_cs);
1536     if(hr == WINED3D_OK) return D3D_OK;
1537     else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1538 }
1539
1540 static HRESULT WINAPI
1541 Thunk_IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1542 {
1543     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1544     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1545     return IDirect3DDevice7_BeginScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1546 }
1547
1548 static HRESULT WINAPI
1549 Thunk_IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1550 {
1551     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1552     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1553     return IDirect3DDevice7_BeginScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1554 }
1555
1556 static HRESULT WINAPI
1557 Thunk_IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1558 {
1559     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1560     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1561     return IDirect3DDevice7_BeginScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1562 }
1563
1564 /*****************************************************************************
1565  * IDirect3DDevice7::EndScene
1566  *
1567  * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1568  * This method must be called after rendering is finished.
1569  *
1570  * Version 1, 2, 3 and 7
1571  *
1572  * Returns:
1573  *  D3D_OK on success, for details see IWineD3DDevice::EndScene
1574  *  D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1575  *  that only if the scene was already ended.
1576  *
1577  *****************************************************************************/
1578 static HRESULT WINAPI
1579 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1580 {
1581     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1582     HRESULT hr;
1583     TRACE("(%p): Relay\n", This);
1584
1585     EnterCriticalSection(&ddraw_cs);
1586     hr = IWineD3DDevice_EndScene(This->wineD3DDevice);
1587     LeaveCriticalSection(&ddraw_cs);
1588     if(hr == WINED3D_OK) return D3D_OK;
1589     else return D3DERR_SCENE_NOT_IN_SCENE;
1590 }
1591
1592 static HRESULT WINAPI
1593 Thunk_IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1594 {
1595     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1596     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1597     return IDirect3DDevice7_EndScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1598 }
1599
1600 static HRESULT WINAPI
1601 Thunk_IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1602 {
1603     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1604     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1605     return IDirect3DDevice7_EndScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1606 }
1607
1608 static HRESULT WINAPI
1609 Thunk_IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1610 {
1611     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1612     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1613     return IDirect3DDevice7_EndScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1614 }
1615
1616 /*****************************************************************************
1617  * IDirect3DDevice7::GetDirect3D
1618  *
1619  * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1620  * this device.
1621  *
1622  * Params:
1623  *  Direct3D7: Address to store the interface pointer at
1624  *
1625  * Returns:
1626  *  D3D_OK on success
1627  *  DDERR_INVALIDPARAMS if Direct3D7 == NULL
1628  *
1629  *****************************************************************************/
1630 static HRESULT WINAPI
1631 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1632                                   IDirect3D7 **Direct3D7)
1633 {
1634     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1635     TRACE("(%p)->(%p)\n", This, Direct3D7);
1636
1637     if(!Direct3D7)
1638         return DDERR_INVALIDPARAMS;
1639
1640     *Direct3D7 = ICOM_INTERFACE(This->ddraw, IDirect3D7);
1641     IDirect3D7_AddRef(*Direct3D7);
1642
1643     TRACE(" returning interface %p\n", *Direct3D7);
1644     return D3D_OK;
1645 }
1646
1647 static HRESULT WINAPI
1648 Thunk_IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1649                                         IDirect3D3 **Direct3D3)
1650 {
1651     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1652     HRESULT ret;
1653     IDirect3D7 *ret_ptr;
1654
1655     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Direct3D3);
1656     ret = IDirect3DDevice7_GetDirect3D(ICOM_INTERFACE(This, IDirect3DDevice7),
1657                                        &ret_ptr);
1658     if(ret != D3D_OK)
1659         return ret;
1660     *Direct3D3 = COM_INTERFACE_CAST(IDirectDrawImpl, IDirect3D7, IDirect3D3, ret_ptr);
1661     TRACE(" returning interface %p\n", *Direct3D3);
1662     return D3D_OK;
1663 }
1664
1665 static HRESULT WINAPI
1666 Thunk_IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1667                                         IDirect3D2 **Direct3D2)
1668 {
1669     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1670     HRESULT ret;
1671     IDirect3D7 *ret_ptr;
1672
1673     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Direct3D2);
1674     ret = IDirect3DDevice7_GetDirect3D(ICOM_INTERFACE(This, IDirect3DDevice7),
1675                                        &ret_ptr);
1676     if(ret != D3D_OK)
1677         return ret;
1678     *Direct3D2 = COM_INTERFACE_CAST(IDirectDrawImpl, IDirect3D7, IDirect3D2, ret_ptr);
1679     TRACE(" returning interface %p\n", *Direct3D2);
1680     return D3D_OK;
1681 }
1682
1683 static HRESULT WINAPI
1684 Thunk_IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1685                                         IDirect3D **Direct3D)
1686 {
1687     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1688     HRESULT ret;
1689     IDirect3D7 *ret_ptr;
1690
1691     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Direct3D);
1692     ret = IDirect3DDevice7_GetDirect3D(ICOM_INTERFACE(This, IDirect3DDevice7),
1693                                        &ret_ptr);
1694     if(ret != D3D_OK)
1695         return ret;
1696     *Direct3D = COM_INTERFACE_CAST(IDirectDrawImpl, IDirect3D7, IDirect3D, ret_ptr);
1697     TRACE(" returning interface %p\n", *Direct3D);
1698     return D3D_OK;
1699 }
1700
1701 /*****************************************************************************
1702  * IDirect3DDevice3::SetCurrentViewport
1703  *
1704  * Sets a Direct3DViewport as the current viewport.
1705  * For the thunks note that all viewport interface versions are equal
1706  *
1707  * Params:
1708  *  Direct3DViewport3: The viewport to set
1709  *
1710  * Version 2 and 3
1711  *
1712  * Returns:
1713  *  D3D_OK on success
1714  *  (Is a NULL viewport valid?)
1715  *
1716  *****************************************************************************/
1717 static HRESULT WINAPI
1718 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1719                                          IDirect3DViewport3 *Direct3DViewport3)
1720 {
1721     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1722     IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Direct3DViewport3);
1723     TRACE("(%p)->(%p)\n", This, Direct3DViewport3);
1724
1725     EnterCriticalSection(&ddraw_cs);
1726     /* Do nothing if the specified viewport is the same as the current one */
1727     if (This->current_viewport == vp )
1728     {
1729         LeaveCriticalSection(&ddraw_cs);
1730         return D3D_OK;
1731     }
1732
1733     /* Should check if the viewport was added or not */
1734
1735     /* Release previous viewport and AddRef the new one */
1736     if (This->current_viewport)
1737     {
1738         TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport, ICOM_INTERFACE(This->current_viewport, IDirect3DViewport3));
1739         IDirect3DViewport3_Release( ICOM_INTERFACE(This->current_viewport, IDirect3DViewport3) );
1740     }
1741     IDirect3DViewport3_AddRef(Direct3DViewport3);
1742
1743     /* Set this viewport as the current viewport */
1744     This->current_viewport = vp;
1745
1746     /* Activate this viewport */
1747     This->current_viewport->active_device = This;
1748     This->current_viewport->activate(This->current_viewport);
1749
1750     LeaveCriticalSection(&ddraw_cs);
1751     return D3D_OK;
1752 }
1753
1754 static HRESULT WINAPI
1755 Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1756                                                IDirect3DViewport2 *Direct3DViewport2)
1757 {
1758     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1759     IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Direct3DViewport2);
1760     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
1761     return IDirect3DDevice3_SetCurrentViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
1762                                                ICOM_INTERFACE(vp, IDirect3DViewport3));
1763 }
1764
1765 /*****************************************************************************
1766  * IDirect3DDevice3::GetCurrentViewport
1767  *
1768  * Returns the currently active viewport.
1769  *
1770  * Version 2 and 3
1771  *
1772  * Params:
1773  *  Direct3DViewport3: Address to return the interface pointer at
1774  *
1775  * Returns:
1776  *  D3D_OK on success
1777  *  DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1778  *
1779  *****************************************************************************/
1780 static HRESULT WINAPI
1781 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1782                                          IDirect3DViewport3 **Direct3DViewport3)
1783 {
1784     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1785     TRACE("(%p)->(%p)\n", This, Direct3DViewport3);
1786
1787     if(!Direct3DViewport3)
1788         return DDERR_INVALIDPARAMS;
1789
1790     EnterCriticalSection(&ddraw_cs);
1791     *Direct3DViewport3 = ICOM_INTERFACE(This->current_viewport, IDirect3DViewport3);
1792
1793     /* AddRef the returned viewport */
1794     if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1795
1796     TRACE(" returning interface %p\n", *Direct3DViewport3);
1797
1798     LeaveCriticalSection(&ddraw_cs);
1799     return D3D_OK;
1800 }
1801
1802 static HRESULT WINAPI
1803 Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1804                                                IDirect3DViewport2 **Direct3DViewport2)
1805 {
1806     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1807     HRESULT hr;
1808     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, Direct3DViewport2);
1809     hr = IDirect3DDevice3_GetCurrentViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
1810                                             (IDirect3DViewport3 **) Direct3DViewport2);
1811     if(hr != D3D_OK) return hr;
1812     *Direct3DViewport2 = (IDirect3DViewport2 *) COM_INTERFACE_CAST(IDirect3DViewportImpl, IDirect3DViewport3, IDirect3DViewport3, *Direct3DViewport2);
1813     return D3D_OK;
1814 }
1815
1816 /*****************************************************************************
1817  * IDirect3DDevice7::SetRenderTarget
1818  *
1819  * Sets the render target for the Direct3DDevice.
1820  * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1821  * IDirectDrawSurface3 == IDirectDrawSurface
1822  *
1823  * Version 2, 3 and 7
1824  *
1825  * Params:
1826  *  NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1827  *             render target
1828  *  Flags: Some flags
1829  *
1830  * Returns:
1831  *  D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1832  *
1833  *****************************************************************************/
1834 static HRESULT WINAPI
1835 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1836                                       IDirectDrawSurface7 *NewTarget,
1837                                       DWORD Flags)
1838 {
1839     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1840     IDirectDrawSurfaceImpl *Target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, NewTarget);
1841     HRESULT hr;
1842     TRACE("(%p)->(%p,%08x): Relay\n", This, NewTarget, Flags);
1843
1844     EnterCriticalSection(&ddraw_cs);
1845     /* Flags: Not used */
1846
1847     hr = IWineD3DDevice_SetRenderTarget(This->wineD3DDevice,
1848                                         0,
1849                                         Target ? Target->WineD3DSurface : NULL);
1850     if(hr != D3D_OK)
1851     {
1852         LeaveCriticalSection(&ddraw_cs);
1853         return hr;
1854     }
1855     IDirectDrawSurface7_AddRef(NewTarget);
1856     IDirectDrawSurface7_Release(ICOM_INTERFACE(This->target, IDirectDrawSurface7));
1857     This->target = Target;
1858     IDirect3DDeviceImpl_UpdateDepthStencil(This);
1859     LeaveCriticalSection(&ddraw_cs);
1860     return D3D_OK;
1861 }
1862
1863 static HRESULT WINAPI
1864 Thunk_IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
1865                                             IDirectDrawSurface4 *NewRenderTarget,
1866                                             DWORD Flags)
1867 {
1868     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1869     IDirectDrawSurfaceImpl *Target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, NewRenderTarget);
1870     TRACE_(ddraw_thunk)("(%p)->(%p,%08x) thunking to IDirect3DDevice7 interface.\n", This, Target, Flags);
1871     return IDirect3DDevice7_SetRenderTarget(ICOM_INTERFACE(This, IDirect3DDevice7),
1872                                             ICOM_INTERFACE(Target, IDirectDrawSurface7),
1873                                             Flags);
1874 }
1875
1876 static HRESULT WINAPI
1877 Thunk_IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
1878                                             IDirectDrawSurface *NewRenderTarget,
1879                                             DWORD Flags)
1880 {
1881     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1882     IDirectDrawSurfaceImpl *Target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface3, NewRenderTarget);
1883     TRACE_(ddraw_thunk)("(%p)->(%p,%08x) thunking to IDirect3DDevice7 interface.\n", This, Target, Flags);
1884     return IDirect3DDevice7_SetRenderTarget(ICOM_INTERFACE(This, IDirect3DDevice7),
1885                                             ICOM_INTERFACE(Target, IDirectDrawSurface7),
1886                                             Flags);
1887 }
1888
1889 /*****************************************************************************
1890  * IDirect3DDevice7::GetRenderTarget
1891  *
1892  * Returns the current render target.
1893  * This is handled locally, because the WineD3D render target's parent
1894  * is an IParent
1895  *
1896  * Version 2, 3 and 7
1897  *
1898  * Params:
1899  *  RenderTarget: Address to store the surface interface pointer
1900  *
1901  * Returns:
1902  *  D3D_OK on success
1903  *  DDERR_INVALIDPARAMS if RenderTarget == NULL
1904  *
1905  *****************************************************************************/
1906 static HRESULT WINAPI
1907 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
1908                                       IDirectDrawSurface7 **RenderTarget)
1909 {
1910     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1911     TRACE("(%p)->(%p): Relay\n", This, RenderTarget);
1912
1913     if(!RenderTarget)
1914         return DDERR_INVALIDPARAMS;
1915
1916     EnterCriticalSection(&ddraw_cs);
1917     *RenderTarget = ICOM_INTERFACE(This->target, IDirectDrawSurface7);
1918     IDirectDrawSurface7_AddRef(*RenderTarget);
1919
1920     LeaveCriticalSection(&ddraw_cs);
1921     return D3D_OK;
1922 }
1923
1924 static HRESULT WINAPI
1925 Thunk_IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
1926                                             IDirectDrawSurface4 **RenderTarget)
1927 {
1928     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1929     HRESULT hr;
1930     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, RenderTarget);
1931     hr = IDirect3DDevice7_GetRenderTarget(ICOM_INTERFACE(This, IDirect3DDevice7),
1932                                           (IDirectDrawSurface7 **) RenderTarget);
1933     if(hr != D3D_OK) return hr;
1934     *RenderTarget = (IDirectDrawSurface4 *) COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirectDrawSurface7, IDirectDrawSurface7, *RenderTarget);
1935     return D3D_OK;
1936 }
1937
1938 static HRESULT WINAPI
1939 Thunk_IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
1940                                             IDirectDrawSurface **RenderTarget)
1941 {
1942     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1943     HRESULT hr;
1944     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, RenderTarget);
1945     hr = IDirect3DDevice7_GetRenderTarget(ICOM_INTERFACE(This, IDirect3DDevice7),
1946                                           (IDirectDrawSurface7 **) RenderTarget);
1947     if(hr != D3D_OK) return hr;
1948     *RenderTarget = (IDirectDrawSurface *) COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirectDrawSurface7, IDirectDrawSurface3, *RenderTarget);
1949     return D3D_OK;
1950 }
1951
1952 /*****************************************************************************
1953  * IDirect3DDevice3::Begin
1954  *
1955  * Begins a description block of vertices. This is similar to glBegin()
1956  * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
1957  * described with IDirect3DDevice::Vertex are drawn.
1958  *
1959  * Version 2 and 3
1960  *
1961  * Params:
1962  *  PrimitiveType: The type of primitives to draw
1963  *  VertexTypeDesc: A flexible vertex format description of the vertices
1964  *  Flags: Some flags..
1965  *
1966  * Returns:
1967  *  D3D_OK on success
1968  *
1969  *****************************************************************************/
1970 static HRESULT WINAPI
1971 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
1972                             D3DPRIMITIVETYPE PrimitiveType,
1973                             DWORD VertexTypeDesc,
1974                             DWORD Flags)
1975 {
1976     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1977     TRACE("(%p)->(%d,%d,%08x)\n", This, PrimitiveType, VertexTypeDesc, Flags);
1978
1979     EnterCriticalSection(&ddraw_cs);
1980     This->primitive_type = PrimitiveType;
1981     This->vertex_type = VertexTypeDesc;
1982     This->render_flags = Flags;
1983     This->vertex_size = get_flexible_vertex_size(This->vertex_type);
1984     This->nb_vertices = 0;
1985     LeaveCriticalSection(&ddraw_cs);
1986
1987     return D3D_OK;
1988 }
1989
1990 static HRESULT WINAPI
1991 Thunk_IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface,
1992                                   D3DPRIMITIVETYPE d3dpt,
1993                                   D3DVERTEXTYPE dwVertexTypeDesc,
1994                                   DWORD dwFlags)
1995 {
1996     DWORD FVF;
1997     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1998     TRACE_(ddraw_thunk)("(%p/%p)->(%08x,%08x,%08x): Thunking to IDirect3DDevice3\n", This, iface, d3dpt, dwVertexTypeDesc, dwFlags);
1999
2000     switch(dwVertexTypeDesc)
2001     {
2002         case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2003         case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2004         case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2005         default:
2006             ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2007             return DDERR_INVALIDPARAMS;  /* Should never happen */
2008     };
2009
2010     return IDirect3DDevice3_Begin(ICOM_INTERFACE(This, IDirect3DDevice3),
2011                                   d3dpt,
2012                                   FVF,
2013                                   dwFlags);
2014 }
2015
2016 /*****************************************************************************
2017  * IDirect3DDevice3::BeginIndexed
2018  *
2019  * Draws primitives based on vertices in a vertex array which are specified
2020  * by indices.
2021  *
2022  * Version 2 and 3
2023  *
2024  * Params:
2025  *  PrimitiveType: Primitive type to draw
2026  *  VertexType: A FVF description of the vertex format
2027  *  Vertices: pointer to an array containing the vertices
2028  *  NumVertices: The number of vertices in the vertex array
2029  *  Flags: Some flags ...
2030  *
2031  * Returns:
2032  *  D3D_OK, because it's a stub
2033  *
2034  *****************************************************************************/
2035 static HRESULT WINAPI
2036 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2037                                    D3DPRIMITIVETYPE PrimitiveType,
2038                                    DWORD VertexType,
2039                                    void *Vertices,
2040                                    DWORD NumVertices,
2041                                    DWORD Flags)
2042 {
2043     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2044     FIXME("(%p)->(%08x,%08x,%p,%08x,%08x): stub!\n", This, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2045     return D3D_OK;
2046 }
2047
2048
2049 static HRESULT WINAPI
2050 Thunk_IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2051                                          D3DPRIMITIVETYPE d3dptPrimitiveType,
2052                                          D3DVERTEXTYPE d3dvtVertexType,
2053                                          void *lpvVertices,
2054                                          DWORD dwNumVertices,
2055                                          DWORD dwFlags)
2056 {
2057     DWORD FVF;
2058     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2059     TRACE_(ddraw_thunk)("(%p/%p)->(%08x,%08x,%p,%08x,%08x): Thunking to IDirect3DDevice3\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2060
2061     switch(d3dvtVertexType)
2062     {
2063         case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2064         case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2065         case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2066         default:
2067             ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2068             return DDERR_INVALIDPARAMS;  /* Should never happen */
2069     };
2070
2071     return IDirect3DDevice3_BeginIndexed(ICOM_INTERFACE(This,IDirect3DDevice3),
2072                                          d3dptPrimitiveType,
2073                                          FVF,
2074                                          lpvVertices,
2075                                          dwNumVertices,
2076                                          dwFlags);
2077 }
2078
2079 /*****************************************************************************
2080  * IDirect3DDevice3::Vertex
2081  *
2082  * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2083  * drawn vertices in a vertex buffer. If the buffer is too small, its
2084  * size is increased.
2085  *
2086  * Version 2 and 3
2087  *
2088  * Params:
2089  *  Vertex: Pointer to the vertex
2090  *
2091  * Returns:
2092  *  D3D_OK, on success
2093  *  DDERR_INVALIDPARAMS if Vertex is NULL
2094  *
2095  *****************************************************************************/
2096 static HRESULT WINAPI
2097 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2098                              void *Vertex)
2099 {
2100     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2101     TRACE("(%p)->(%p)\n", This, Vertex);
2102
2103     if(!Vertex)
2104         return DDERR_INVALIDPARAMS;
2105
2106     EnterCriticalSection(&ddraw_cs);
2107     if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2108     {
2109         BYTE *old_buffer;
2110         This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2111         old_buffer = This->vertex_buffer;
2112         This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2113         if (old_buffer)
2114         {
2115             CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2116             HeapFree(GetProcessHeap(), 0, old_buffer);
2117         }
2118     }
2119
2120     CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2121
2122     LeaveCriticalSection(&ddraw_cs);
2123     return D3D_OK;
2124 }
2125
2126 static HRESULT WINAPI
2127 Thunk_IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface,
2128                                    void *lpVertexType)
2129 {
2130     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2131     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, lpVertexType);
2132     return IDirect3DDevice3_Vertex(ICOM_INTERFACE(This, IDirect3DDevice3),
2133                                                   lpVertexType);
2134 }
2135
2136 /*****************************************************************************
2137  * IDirect3DDevice3::Index
2138  *
2139  * Specifies an index to a vertex to be drawn. The vertex array has to
2140  * be specified with BeginIndexed first.
2141  *
2142  * Parameters:
2143  *  VertexIndex: The index of the vertex to draw
2144  *
2145  * Returns:
2146  *  D3D_OK because it's a stub
2147  *
2148  *****************************************************************************/
2149 static HRESULT WINAPI
2150 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2151                             WORD VertexIndex)
2152 {
2153     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2154     FIXME("(%p)->(%04x): stub!\n", This, VertexIndex);
2155     return D3D_OK;
2156 }
2157
2158 static HRESULT WINAPI
2159 Thunk_IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface,
2160                                   WORD wVertexIndex)
2161 {
2162     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2163     TRACE_(ddraw_thunk)("(%p)->(%04x) thunking to IDirect3DDevice3 interface.\n", This, wVertexIndex);
2164     return IDirect3DDevice3_Index(ICOM_INTERFACE(This, IDirect3DDevice3),
2165                                   wVertexIndex);
2166 }
2167
2168 /*****************************************************************************
2169  * IDirect3DDevice3::End
2170  *
2171  * Ends a draw begun with IDirect3DDevice3::Begin or
2172  * IDirect3DDevice::BeginIndexed. The vertices specified with
2173  * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2174  * the IDirect3DDevice7::DrawPrimitive method. So far only
2175  * non-indexed mode is supported
2176  *
2177  * Version 2 and 3
2178  *
2179  * Params:
2180  *  Flags: Some flags, as usual. Don't know which are defined
2181  *
2182  * Returns:
2183  *  The return value of IDirect3DDevice7::DrawPrimitive
2184  *
2185  *****************************************************************************/
2186 static HRESULT WINAPI
2187 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2188                           DWORD Flags)
2189 {
2190     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2191     TRACE("(%p)->(%08x)\n", This, Flags);
2192
2193     return IDirect3DDevice7_DrawPrimitive(ICOM_INTERFACE(This, IDirect3DDevice7),
2194                                           This->primitive_type, This->vertex_type,
2195                                           This->vertex_buffer, This->nb_vertices,
2196                                           This->render_flags);
2197 }
2198
2199 static HRESULT WINAPI
2200 Thunk_IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface,
2201                                 DWORD dwFlags)
2202 {
2203     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2204     TRACE_(ddraw_thunk)("(%p)->(%08x) thunking to IDirect3DDevice3 interface.\n", This, dwFlags);
2205     return IDirect3DDevice3_End(ICOM_INTERFACE(This, IDirect3DDevice3),
2206                                 dwFlags);
2207 }
2208
2209 /*****************************************************************************
2210  * IDirect3DDevice7::GetRenderState
2211  *
2212  * Returns the value of a render state. The possible render states are
2213  * defined in include/d3dtypes.h
2214  *
2215  * Version 2, 3 and 7
2216  *
2217  * Params:
2218  *  RenderStateType: Render state to return the current setting of
2219  *  Value: Address to store the value at
2220  *
2221  * Returns:
2222  *  D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2223  *  DDERR_INVALIDPARAMS if Value == NULL
2224  *
2225  *****************************************************************************/
2226 static HRESULT WINAPI
2227 IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2228                                      D3DRENDERSTATETYPE RenderStateType,
2229                                      DWORD *Value)
2230 {
2231     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2232     HRESULT hr;
2233     TRACE("(%p)->(%08x,%p): Relay\n", This, RenderStateType, Value);
2234
2235     if(!Value)
2236         return DDERR_INVALIDPARAMS;
2237
2238     EnterCriticalSection(&ddraw_cs);
2239     switch(RenderStateType)
2240     {
2241         case D3DRENDERSTATE_TEXTUREHANDLE:
2242         {
2243             /* This state is wrapped to SetTexture in SetRenderState, so
2244              * it has to be wrapped to GetTexture here
2245              */
2246             IWineD3DBaseTexture *tex = NULL;
2247             *Value = 0;
2248
2249             hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2250                                            0,
2251                                            &tex);
2252
2253             if(hr == WINED3D_OK && tex)
2254             {
2255                 IDirectDrawSurface7 *parent = NULL;
2256                 hr = IWineD3DBaseTexture_GetParent(tex,
2257                                                    (IUnknown **) &parent);
2258                 if(parent)
2259                 {
2260                     /* The parent of the texture is the IDirectDrawSurface7 interface
2261                      * of the ddraw surface
2262                      */
2263                     IDirectDrawSurfaceImpl *texImpl = ICOM_OBJECT(IDirectDrawSurfaceImpl,
2264                                                                   IDirectDrawSurface7,
2265                                                                   parent);
2266                     *Value = texImpl->Handle;
2267                     IDirectDrawSurface7_Release(parent);
2268                 }
2269                 IWineD3DBaseTexture_Release(tex);
2270             }
2271             break;
2272         }
2273
2274         case D3DRENDERSTATE_TEXTUREMAG:
2275         {
2276             WINED3DTEXTUREFILTERTYPE tex_mag;
2277
2278             hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2279                                                 0, WINED3DSAMP_MAGFILTER,
2280                                                 &tex_mag);
2281
2282             switch (tex_mag)
2283             {
2284                 case WINED3DTEXF_POINT:
2285                     *Value = D3DFILTER_NEAREST;
2286                     break;
2287                 case WINED3DTEXF_LINEAR:
2288                     *Value = D3DFILTER_LINEAR;
2289                     break;
2290                 default:
2291                     ERR("Unhandled texture mag %d !\n",tex_mag);
2292                     *Value = 0;
2293             }
2294             break;
2295         }
2296
2297         case D3DRENDERSTATE_TEXTUREMIN:
2298         {
2299             WINED3DTEXTUREFILTERTYPE tex_min;
2300
2301             hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2302                                                 0, WINED3DSAMP_MINFILTER,
2303                                                 &tex_min);
2304
2305             switch (tex_min)
2306             {
2307                 case WINED3DTEXF_POINT:
2308                     *Value = D3DFILTER_NEAREST;
2309                     break;
2310                 case WINED3DTEXF_LINEAR:
2311                     *Value = D3DFILTER_LINEAR;
2312                     break;
2313                 default:
2314                     ERR("Unhandled texture mag %d !\n",tex_min);
2315                     *Value = 0;
2316             }
2317             break;
2318         }
2319
2320         case D3DRENDERSTATE_TEXTUREADDRESS:
2321         case D3DRENDERSTATE_TEXTUREADDRESSU:
2322             hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2323                                                 0, WINED3DSAMP_ADDRESSU,
2324                                                 Value);
2325             break;
2326         case D3DRENDERSTATE_TEXTUREADDRESSV:
2327             hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2328                                                 0, WINED3DSAMP_ADDRESSV,
2329                                                 Value);
2330             break;
2331
2332         default:
2333             /* FIXME: Unhandled: D3DRENDERSTATE_STIPPLEPATTERN00 - 31 */
2334             hr = IWineD3DDevice_GetRenderState(This->wineD3DDevice,
2335                                                RenderStateType,
2336                                                Value);
2337     }
2338     LeaveCriticalSection(&ddraw_cs);
2339     return hr;
2340 }
2341
2342 static HRESULT WINAPI
2343 Thunk_IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2344                                            D3DRENDERSTATETYPE dwRenderStateType,
2345                                            DWORD *lpdwRenderState)
2346 {
2347     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2348     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, dwRenderStateType, lpdwRenderState);
2349     return IDirect3DDevice7_GetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
2350                                            dwRenderStateType,
2351                                            lpdwRenderState);
2352 }
2353
2354 static HRESULT WINAPI
2355 Thunk_IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2356                                            D3DRENDERSTATETYPE dwRenderStateType,
2357                                            DWORD *lpdwRenderState)
2358 {
2359     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2360     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, dwRenderStateType, lpdwRenderState);
2361     return IDirect3DDevice7_GetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
2362                                            dwRenderStateType,
2363                                            lpdwRenderState);
2364 }
2365
2366 /*****************************************************************************
2367  * IDirect3DDevice7::SetRenderState
2368  *
2369  * Sets a render state. The possible render states are defined in
2370  * include/d3dtypes.h
2371  *
2372  * Version 2, 3 and 7
2373  *
2374  * Params:
2375  *  RenderStateType: State to set
2376  *  Value: Value to assign to that state
2377  *
2378  * Returns:
2379  *  D3D_OK on success,
2380  *  for details see IWineD3DDevice::SetRenderState
2381  *
2382  *****************************************************************************/
2383 static HRESULT WINAPI
2384 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2385                                      D3DRENDERSTATETYPE RenderStateType,
2386                                      DWORD Value)
2387 {
2388     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2389     HRESULT hr;
2390     TRACE("(%p)->(%08x,%d): Relay\n", This, RenderStateType, Value);
2391
2392     EnterCriticalSection(&ddraw_cs);
2393     /* Some render states need special care */
2394     switch(RenderStateType)
2395     {
2396         case D3DRENDERSTATE_TEXTUREHANDLE:
2397         {
2398             if(Value == 0)
2399             {
2400                 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
2401                                                0,
2402                                                NULL);
2403                 break;
2404             }
2405
2406             if(Value > This->numHandles)
2407             {
2408                 FIXME("Specified handle %d out of range\n", Value);
2409                 hr = DDERR_INVALIDPARAMS;
2410                 break;
2411             }
2412             if(This->Handles[Value - 1].type != DDrawHandle_Texture)
2413             {
2414                 FIXME("Handle %d isn't a texture handle\n", Value);
2415                 hr = DDERR_INVALIDPARAMS;
2416                 break;
2417             }
2418             else
2419             {
2420                 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *) This->Handles[Value - 1].ptr;
2421                 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
2422                                                0,
2423                                                surf->wineD3DTexture);
2424                 break;
2425             }
2426         }
2427
2428         case D3DRENDERSTATE_TEXTUREMAG:
2429         {
2430             WINED3DTEXTUREFILTERTYPE tex_mag = WINED3DTEXF_NONE;
2431
2432             switch ((D3DTEXTUREFILTER) Value)
2433             {
2434                 case D3DFILTER_NEAREST:
2435                 case D3DFILTER_LINEARMIPNEAREST:
2436                     tex_mag = WINED3DTEXF_POINT;
2437                     break;
2438                 case D3DFILTER_LINEAR:
2439                 case D3DFILTER_LINEARMIPLINEAR:
2440                     tex_mag = WINED3DTEXF_LINEAR;
2441                     break;
2442                 default:
2443                     ERR("Unhandled texture mag %d !\n",Value);
2444             }
2445
2446             hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2447                                                 0, WINED3DSAMP_MAGFILTER,
2448                                                 tex_mag);
2449             break;
2450         }
2451
2452         case D3DRENDERSTATE_TEXTUREMIN:
2453         {
2454             WINED3DTEXTUREFILTERTYPE tex_min = WINED3DTEXF_NONE;
2455             WINED3DTEXTUREFILTERTYPE tex_mip = WINED3DTEXF_NONE;
2456
2457             switch ((D3DTEXTUREFILTER) Value)
2458             {
2459                 case D3DFILTER_NEAREST:
2460                     tex_min = WINED3DTEXF_POINT;
2461                     break;
2462                 case D3DFILTER_LINEAR:
2463                     tex_min = WINED3DTEXF_LINEAR;
2464                     break;
2465                 case D3DFILTER_MIPNEAREST:
2466                     tex_min = WINED3DTEXF_NONE;
2467                     tex_mip = WINED3DTEXF_POINT;
2468                     break;
2469                 case D3DFILTER_MIPLINEAR:
2470                     tex_min = WINED3DTEXF_NONE;
2471                     tex_mip = WINED3DTEXF_LINEAR;
2472                     break;
2473                 case D3DFILTER_LINEARMIPNEAREST:
2474                     tex_min = WINED3DTEXF_POINT;
2475                     tex_mip = WINED3DTEXF_LINEAR;
2476                     break;
2477                 case D3DFILTER_LINEARMIPLINEAR:
2478                     tex_min = WINED3DTEXF_LINEAR;
2479                     tex_mip = WINED3DTEXF_LINEAR;
2480                     break;
2481
2482                 default:
2483                     ERR("Unhandled texture min %d !\n",Value);
2484             }
2485
2486                    IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2487                                                   0, WINED3DSAMP_MIPFILTER,
2488                                                   tex_mip);
2489             hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2490                                                 0, WINED3DSAMP_MINFILTER,
2491                                                 tex_min);
2492             break;
2493         }
2494
2495         case D3DRENDERSTATE_TEXTUREADDRESS:
2496                    IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2497                                                   0, WINED3DSAMP_ADDRESSV,
2498                                                   Value);
2499             /* Drop through */
2500         case D3DRENDERSTATE_TEXTUREADDRESSU:
2501             hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2502                                                 0, WINED3DSAMP_ADDRESSU,
2503                                                 Value);
2504             break;
2505         case D3DRENDERSTATE_TEXTUREADDRESSV:
2506             hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2507                                                 0, WINED3DSAMP_ADDRESSV,
2508                                                 Value);
2509             break;
2510
2511         case D3DRENDERSTATE_TEXTUREMAPBLEND:
2512         {
2513             /* Old texture combine setup style, superseded by texture stage states
2514              * in D3D7. It is safe for us to wrap it to texture stage states.
2515              */
2516             switch ( (D3DTEXTUREBLEND) Value)
2517             {
2518                 case D3DTBLEND_MODULATE:
2519                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2520                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2521                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2522                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2523                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2524                     break;
2525
2526                 case D3DTBLEND_MODULATEALPHA:
2527                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2528                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2529                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2530                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2531                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2532                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2533                     break;
2534
2535                 case D3DTBLEND_DECAL:
2536                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2537                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2538                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2539                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2540                     break;
2541
2542                 case D3DTBLEND_DECALALPHA:
2543                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2544                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2545                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2546                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2547                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2548                     break;
2549
2550                 default:
2551                     ERR("Unhandled texture environment %d !\n",Value);
2552                 }
2553                 hr = D3D_OK;
2554             break;
2555         }
2556
2557         default:
2558
2559             /* FIXME: Unhandled: D3DRENDERSTATE_STIPPLEPATTERN00 - 31 */
2560
2561             hr = IWineD3DDevice_SetRenderState(This->wineD3DDevice,
2562                                                RenderStateType,
2563                                                Value);
2564             break;
2565     }
2566     LeaveCriticalSection(&ddraw_cs);
2567     return hr;
2568 }
2569
2570 static HRESULT WINAPI
2571 Thunk_IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2572                                            D3DRENDERSTATETYPE RenderStateType,
2573                                            DWORD Value)
2574 {
2575     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2576     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, RenderStateType, Value);
2577     return IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
2578                                            RenderStateType,
2579                                            Value);
2580 }
2581
2582 static HRESULT WINAPI
2583 Thunk_IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2584                                            D3DRENDERSTATETYPE RenderStateType,
2585                                            DWORD Value)
2586 {
2587     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2588     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, RenderStateType, Value);
2589     return IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
2590                                            RenderStateType,
2591                                            Value);
2592 }
2593
2594 /*****************************************************************************
2595  * Direct3DDevice3::SetLightState
2596  *
2597  * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2598  * light states are forwarded to Direct3DDevice7 render states
2599  *
2600  * Version 2 and 3
2601  *
2602  * Params:
2603  *  LightStateType: The light state to change
2604  *  Value: The value to assign to that light state
2605  *
2606  * Returns:
2607  *  D3D_OK on success
2608  *  DDERR_INVALIDPARAMS if the parameters were incorrect
2609  *  Also check IDirect3DDevice7::SetRenderState
2610  *
2611  *****************************************************************************/
2612 static HRESULT WINAPI
2613 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
2614                                     D3DLIGHTSTATETYPE LightStateType,
2615                                     DWORD Value)
2616 {
2617     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2618     HRESULT hr;
2619
2620     TRACE("(%p)->(%08x,%08x)\n", This, LightStateType, Value);
2621
2622     if (!LightStateType && (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2623     {
2624         TRACE("Unexpected Light State Type\n");
2625         return DDERR_INVALIDPARAMS;
2626     }
2627
2628     EnterCriticalSection(&ddraw_cs);
2629     if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
2630     {
2631         IDirect3DMaterialImpl *mat;
2632
2633         if(Value == 0) mat = NULL;
2634         else if(Value > This->numHandles)
2635         {
2636             ERR("Material handle out of range(%d)\n", Value);
2637             LeaveCriticalSection(&ddraw_cs);
2638             return DDERR_INVALIDPARAMS;
2639         }
2640         else if(This->Handles[Value - 1].type != DDrawHandle_Material)
2641         {
2642             ERR("Invalid handle %d\n", Value);
2643             LeaveCriticalSection(&ddraw_cs);
2644             return DDERR_INVALIDPARAMS;
2645         }
2646         else
2647         {
2648             mat = (IDirect3DMaterialImpl *) This->Handles[Value - 1].ptr;
2649         }
2650
2651         if (mat != NULL)
2652         {
2653             TRACE(" activating material %p.\n", mat);
2654             mat->activate(mat);
2655         }
2656         else
2657         {
2658             FIXME(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
2659         }
2660         This->material = Value;
2661     }
2662     else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
2663     {
2664         switch (Value)
2665         {
2666             case D3DCOLOR_MONO:
2667                 ERR("DDCOLOR_MONO should not happen!\n");
2668                 break;
2669             case D3DCOLOR_RGB:
2670                 /* We are already in this mode */
2671                 TRACE("Setting color model to RGB (no-op).\n");
2672                 break;
2673             default:
2674                 ERR("Unknown color model!\n");
2675                 LeaveCriticalSection(&ddraw_cs);
2676                 return DDERR_INVALIDPARAMS;
2677         }
2678     }
2679     else
2680     {
2681         D3DRENDERSTATETYPE rs;
2682         switch (LightStateType)
2683         {
2684             case D3DLIGHTSTATE_AMBIENT:       /* 2 */
2685                 rs = D3DRENDERSTATE_AMBIENT;
2686                 break;          
2687             case D3DLIGHTSTATE_FOGMODE:       /* 4 */
2688                 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2689                 break;
2690             case D3DLIGHTSTATE_FOGSTART:      /* 5 */
2691                 rs = D3DRENDERSTATE_FOGSTART;
2692                 break;
2693             case D3DLIGHTSTATE_FOGEND:        /* 6 */
2694                 rs = D3DRENDERSTATE_FOGEND;
2695                 break;
2696             case D3DLIGHTSTATE_FOGDENSITY:    /* 7 */
2697                 rs = D3DRENDERSTATE_FOGDENSITY;
2698                 break;
2699             case D3DLIGHTSTATE_COLORVERTEX:   /* 8 */
2700                 rs = D3DRENDERSTATE_COLORVERTEX;
2701                 break;
2702             default:
2703                 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
2704                 LeaveCriticalSection(&ddraw_cs);
2705                 return DDERR_INVALIDPARAMS;
2706         }
2707
2708         hr = IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
2709                                              rs,
2710                                              Value);
2711         LeaveCriticalSection(&ddraw_cs);
2712         return hr;
2713     }
2714
2715     LeaveCriticalSection(&ddraw_cs);
2716     return D3D_OK;
2717 }
2718
2719 static HRESULT WINAPI
2720 Thunk_IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
2721                                           D3DLIGHTSTATETYPE LightStateType,
2722                                           DWORD Value)
2723 {
2724     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2725     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x) thunking to IDirect3DDevice3 interface.\n", This, LightStateType, Value);
2726     return IDirect3DDevice3_SetLightState(ICOM_INTERFACE(This, IDirect3DDevice3),
2727                                           LightStateType,
2728                                           Value);
2729 }
2730
2731 /*****************************************************************************
2732  * IDirect3DDevice3::GetLightState
2733  *
2734  * Returns the current setting of a light state. The state is read from
2735  * the Direct3DDevice7 render state.
2736  *
2737  * Version 2 and 3
2738  *
2739  * Params:
2740  *  LightStateType: The light state to return
2741  *  Value: The address to store the light state setting at
2742  *
2743  * Returns:
2744  *  D3D_OK on success
2745  *  DDDERR_INVALIDPARAMS if the parameters were incorrect
2746  *  Also see IDirect3DDevice7::GetRenderState
2747  *
2748  *****************************************************************************/
2749 static HRESULT WINAPI
2750 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
2751                                     D3DLIGHTSTATETYPE LightStateType,
2752                                     DWORD *Value)
2753 {
2754     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2755     HRESULT hr;
2756
2757     TRACE("(%p)->(%08x,%p)\n", This, LightStateType, Value);
2758
2759     if (!LightStateType && (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2760     {
2761         TRACE("Unexpected Light State Type\n");
2762         return DDERR_INVALIDPARAMS;
2763     }
2764
2765     if(!Value)
2766         return DDERR_INVALIDPARAMS;
2767
2768     EnterCriticalSection(&ddraw_cs);
2769     if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
2770     {
2771         *Value = This->material;
2772     }
2773     else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
2774     {
2775         *Value = D3DCOLOR_RGB;
2776     }
2777     else
2778     {
2779         D3DRENDERSTATETYPE rs;
2780         switch (LightStateType)
2781         {
2782             case D3DLIGHTSTATE_AMBIENT:       /* 2 */
2783                 rs = D3DRENDERSTATE_AMBIENT;
2784                 break;          
2785             case D3DLIGHTSTATE_FOGMODE:       /* 4 */
2786                 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2787                 break;
2788             case D3DLIGHTSTATE_FOGSTART:      /* 5 */
2789                 rs = D3DRENDERSTATE_FOGSTART;
2790                 break;
2791             case D3DLIGHTSTATE_FOGEND:        /* 6 */
2792                 rs = D3DRENDERSTATE_FOGEND;
2793                 break;
2794             case D3DLIGHTSTATE_FOGDENSITY:    /* 7 */
2795                 rs = D3DRENDERSTATE_FOGDENSITY;
2796                 break;
2797             case D3DLIGHTSTATE_COLORVERTEX:   /* 8 */
2798                 rs = D3DRENDERSTATE_COLORVERTEX;
2799                 break;
2800             default:
2801                 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
2802                 LeaveCriticalSection(&ddraw_cs);
2803                 return DDERR_INVALIDPARAMS;
2804         }
2805
2806         hr = IDirect3DDevice7_GetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
2807                                              rs,
2808                                              Value);
2809         LeaveCriticalSection(&ddraw_cs);
2810         return hr;
2811     }
2812
2813     LeaveCriticalSection(&ddraw_cs);
2814     return D3D_OK;
2815 }
2816
2817 static HRESULT WINAPI
2818 Thunk_IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
2819                                           D3DLIGHTSTATETYPE LightStateType,
2820                                           DWORD *Value)
2821 {
2822     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2823     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice3 interface.\n", This, LightStateType, Value);
2824     return IDirect3DDevice3_GetLightState(ICOM_INTERFACE(This, IDirect3DDevice3),
2825                                           LightStateType,
2826                                           Value);
2827 }
2828
2829 /*****************************************************************************
2830  * IDirect3DDevice7::SetTransform
2831  *
2832  * Assigns a D3DMATRIX to a transform type. The transform types are defined
2833  * in include/d3dtypes.h.
2834  * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
2835  * (=255) for wined3d, because the 1 transform state was removed in d3d8
2836  * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
2837  *
2838  * Version 2, 3 and 7
2839  *
2840  * Params:
2841  *  TransformStateType: transform state to set
2842  *  Matrix: Matrix to assign to the state
2843  *
2844  * Returns:
2845  *  D3D_OK on success
2846  *  DDERR_INVALIDPARAMS if Matrix == NULL
2847  *  For details see IWineD3DDevice::SetTransform
2848  *
2849  *****************************************************************************/
2850 static HRESULT WINAPI
2851 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
2852                                    D3DTRANSFORMSTATETYPE TransformStateType,
2853                                    D3DMATRIX *Matrix)
2854 {
2855     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2856     D3DTRANSFORMSTATETYPE type = TransformStateType;
2857     HRESULT hr;
2858     TRACE("(%p)->(%08x,%p): Relay\n", This, TransformStateType, Matrix);
2859
2860     switch(TransformStateType)
2861     {
2862         case D3DTRANSFORMSTATE_WORLD :  type = WINED3DTS_WORLDMATRIX(0); break;
2863         case D3DTRANSFORMSTATE_WORLD1:  type = WINED3DTS_WORLDMATRIX(1); break;
2864         case D3DTRANSFORMSTATE_WORLD2:  type = WINED3DTS_WORLDMATRIX(2); break;
2865         case D3DTRANSFORMSTATE_WORLD3:  type = WINED3DTS_WORLDMATRIX(3); break;
2866         default:                        type = TransformStateType;
2867     }
2868
2869     if(!Matrix)
2870        return DDERR_INVALIDPARAMS;
2871
2872     /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
2873     EnterCriticalSection(&ddraw_cs);
2874     hr = IWineD3DDevice_SetTransform(This->wineD3DDevice,
2875                                      type,
2876                                      (WINED3DMATRIX*) Matrix);
2877     LeaveCriticalSection(&ddraw_cs);
2878     return hr;
2879 }
2880
2881 static HRESULT WINAPI
2882 Thunk_IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
2883                                          D3DTRANSFORMSTATETYPE TransformStateType,
2884                                          D3DMATRIX *D3DMatrix)
2885 {
2886     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2887     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
2888     return IDirect3DDevice7_SetTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
2889                                          TransformStateType,
2890                                          D3DMatrix);
2891 }
2892
2893 static HRESULT WINAPI
2894 Thunk_IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
2895                                          D3DTRANSFORMSTATETYPE TransformStateType,
2896                                          D3DMATRIX *D3DMatrix)
2897 {
2898     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2899     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
2900     return IDirect3DDevice7_SetTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
2901                                          TransformStateType,
2902                                          D3DMatrix);
2903 }
2904
2905 /*****************************************************************************
2906  * IDirect3DDevice7::GetTransform
2907  *
2908  * Returns the matrix assigned to a transform state
2909  * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
2910  * SetTransform
2911  *
2912  * Params:
2913  *  TransformStateType: State to read the matrix from
2914  *  Matrix: Address to store the matrix at
2915  *
2916  * Returns:
2917  *  D3D_OK on success
2918  *  DDERR_INVALIDPARAMS if Matrix == NULL
2919  *  For details, see IWineD3DDevice::GetTransform
2920  *
2921  *****************************************************************************/
2922 static HRESULT WINAPI
2923 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
2924                                    D3DTRANSFORMSTATETYPE TransformStateType,
2925                                    D3DMATRIX *Matrix)
2926 {
2927     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2928     D3DTRANSFORMSTATETYPE type = TransformStateType;
2929     HRESULT hr;
2930     TRACE("(%p)->(%08x,%p): Relay\n", This, TransformStateType, Matrix);
2931
2932     switch(TransformStateType)
2933     {
2934         case D3DTRANSFORMSTATE_WORLD :  type = WINED3DTS_WORLDMATRIX(0); break;
2935         case D3DTRANSFORMSTATE_WORLD1:  type = WINED3DTS_WORLDMATRIX(1); break;
2936         case D3DTRANSFORMSTATE_WORLD2:  type = WINED3DTS_WORLDMATRIX(2); break;
2937         case D3DTRANSFORMSTATE_WORLD3:  type = WINED3DTS_WORLDMATRIX(3); break;
2938         default:                        type = TransformStateType;
2939     }
2940
2941     if(!Matrix)
2942         return DDERR_INVALIDPARAMS;
2943
2944     /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
2945     EnterCriticalSection(&ddraw_cs);
2946     hr = IWineD3DDevice_GetTransform(This->wineD3DDevice, type, (WINED3DMATRIX*) Matrix);
2947     LeaveCriticalSection(&ddraw_cs);
2948     return hr;
2949 }
2950
2951 static HRESULT WINAPI
2952 Thunk_IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
2953                                          D3DTRANSFORMSTATETYPE TransformStateType,
2954                                          D3DMATRIX *D3DMatrix)
2955 {
2956     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2957     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
2958     return IDirect3DDevice7_GetTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
2959                                          TransformStateType,
2960                                          D3DMatrix);
2961 }
2962
2963 static HRESULT WINAPI
2964 Thunk_IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
2965                                          D3DTRANSFORMSTATETYPE TransformStateType,
2966                                          D3DMATRIX *D3DMatrix)
2967 {
2968     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2969     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
2970     return IDirect3DDevice7_GetTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
2971                                          TransformStateType,
2972                                          D3DMatrix);
2973 }
2974
2975 /*****************************************************************************
2976  * IDirect3DDevice7::MultiplyTransform
2977  *
2978  * Multiplies the already-set transform matrix of a transform state
2979  * with another matrix. For the world matrix, see SetTransform
2980  *
2981  * Version 2, 3 and 7
2982  *
2983  * Params:
2984  *  TransformStateType: Transform state to multiply
2985  *  D3DMatrix Matrix to multiply with.
2986  *
2987  * Returns
2988  *  D3D_OK on success
2989  *  DDERR_INVALIDPARAMS if D3DMatrix is NULL
2990  *  For details, see IWineD3DDevice::MultiplyTransform
2991  *
2992  *****************************************************************************/
2993 static HRESULT WINAPI
2994 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
2995                                         D3DTRANSFORMSTATETYPE TransformStateType,
2996                                         D3DMATRIX *D3DMatrix)
2997 {
2998     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2999     HRESULT hr;
3000     D3DTRANSFORMSTATETYPE type;
3001     TRACE("(%p)->(%08x,%p): Relay\n", This, TransformStateType, D3DMatrix);
3002
3003     switch(TransformStateType)
3004     {
3005         case D3DTRANSFORMSTATE_WORLD :  type = WINED3DTS_WORLDMATRIX(0); break;
3006         case D3DTRANSFORMSTATE_WORLD1:  type = WINED3DTS_WORLDMATRIX(1); break;
3007         case D3DTRANSFORMSTATE_WORLD2:  type = WINED3DTS_WORLDMATRIX(2); break;
3008         case D3DTRANSFORMSTATE_WORLD3:  type = WINED3DTS_WORLDMATRIX(3); break;
3009         default:                        type = TransformStateType;
3010     }
3011
3012     /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3013     EnterCriticalSection(&ddraw_cs);
3014     hr = IWineD3DDevice_MultiplyTransform(This->wineD3DDevice,
3015                                           type,
3016                                           (WINED3DMATRIX*) D3DMatrix);
3017     LeaveCriticalSection(&ddraw_cs);
3018     return hr;
3019 }
3020
3021 static HRESULT WINAPI
3022 Thunk_IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3023                                               D3DTRANSFORMSTATETYPE TransformStateType,
3024                                               D3DMATRIX *D3DMatrix)
3025 {
3026     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3027     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3028     return IDirect3DDevice7_MultiplyTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
3029                                               TransformStateType,
3030                                               D3DMatrix);
3031 }
3032
3033 static HRESULT WINAPI
3034 Thunk_IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3035                                               D3DTRANSFORMSTATETYPE TransformStateType,
3036                                               D3DMATRIX *D3DMatrix)
3037 {
3038     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3039     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3040     return IDirect3DDevice7_MultiplyTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
3041                                               TransformStateType,
3042                                               D3DMatrix);
3043 }
3044
3045 /*****************************************************************************
3046  * IDirect3DDevice7::DrawPrimitive
3047  *
3048  * Draws primitives based on vertices in an application-provided pointer
3049  *
3050  * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3051  * an FVF format for D3D7
3052  *
3053  * Params:
3054  *  PrimitiveType: The type of the primitives to draw
3055  *  Vertex type: Flexible vertex format vertex description
3056  *  Vertices: Pointer to the vertex array
3057  *  VertexCount: The number of vertices to draw
3058  *  Flags: As usual a few flags
3059  *
3060  * Returns:
3061  *  D3D_OK on success
3062  *  DDERR_INVALIDPARAMS if Vertices is NULL
3063  *  For details, see IWineD3DDevice::DrawPrimitiveUP
3064  *
3065  *****************************************************************************/
3066 static HRESULT WINAPI
3067 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3068                                     D3DPRIMITIVETYPE PrimitiveType,
3069                                     DWORD VertexType,
3070                                     void *Vertices,
3071                                     DWORD VertexCount,
3072                                     DWORD Flags)
3073 {
3074     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3075     UINT PrimitiveCount, stride;
3076     HRESULT hr;
3077     TRACE("(%p)->(%08x,%08x,%p,%08x,%08x): Relay!\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3078
3079     if(!Vertices)
3080         return DDERR_INVALIDPARAMS;
3081
3082     /* Get the vertex count */
3083     switch(PrimitiveType)
3084     {
3085       case D3DPT_POINTLIST: 
3086         PrimitiveCount = VertexCount;
3087         break;
3088
3089       case D3DPT_LINELIST: 
3090         PrimitiveCount = VertexCount / 2;
3091         break;
3092
3093       case D3DPT_LINESTRIP:
3094         PrimitiveCount = VertexCount - 1;
3095         break;
3096
3097       case D3DPT_TRIANGLELIST:
3098         PrimitiveCount = VertexCount / 3;
3099         break;
3100
3101       case D3DPT_TRIANGLESTRIP:
3102         PrimitiveCount = VertexCount - 2;
3103         break;
3104
3105       case D3DPT_TRIANGLEFAN:
3106         PrimitiveCount = VertexCount - 2;
3107         break;
3108
3109       default:
3110         return DDERR_INVALIDPARAMS;
3111     }
3112
3113     /* Get the stride */
3114     stride = get_flexible_vertex_size(VertexType);
3115
3116     /* Set the FVF */
3117     EnterCriticalSection(&ddraw_cs);
3118     hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
3119                                              IDirectDrawImpl_FindDecl(This->ddraw, VertexType));
3120     if(hr != D3D_OK)
3121     {
3122         LeaveCriticalSection(&ddraw_cs);
3123         return hr;
3124     }
3125
3126     /* This method translates to the user pointer draw of WineD3D */
3127     hr = IWineD3DDevice_DrawPrimitiveUP(This->wineD3DDevice,
3128                                         PrimitiveType,
3129                                         PrimitiveCount,
3130                                         Vertices,
3131                                         stride);
3132     LeaveCriticalSection(&ddraw_cs);
3133     return hr;
3134 }
3135
3136 static HRESULT WINAPI
3137 Thunk_IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3138                                           D3DPRIMITIVETYPE PrimitiveType,
3139                                           DWORD VertexType,
3140                                           void *Vertices,
3141                                           DWORD VertexCount,
3142                                           DWORD Flags)
3143 {
3144     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3145     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3146     return IDirect3DDevice7_DrawPrimitive(ICOM_INTERFACE(This, IDirect3DDevice7),
3147                                           PrimitiveType,
3148                                           VertexType,
3149                                           Vertices,
3150                                           VertexCount,
3151                                           Flags);
3152 }
3153
3154 static HRESULT WINAPI
3155 Thunk_IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3156                                           D3DPRIMITIVETYPE PrimitiveType,
3157                                           D3DVERTEXTYPE VertexType,
3158                                           void *Vertices,
3159                                           DWORD VertexCount,
3160                                           DWORD Flags)
3161 {
3162     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3163     DWORD FVF;
3164     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3165
3166     switch(VertexType)
3167     {
3168         case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3169         case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3170         case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3171         default:
3172             ERR("Unexpected vertex type %d\n", VertexType);
3173             return DDERR_INVALIDPARAMS;  /* Should never happen */
3174     }
3175
3176     return IDirect3DDevice7_DrawPrimitive(ICOM_INTERFACE(This, IDirect3DDevice7),
3177                                           PrimitiveType,
3178                                           FVF,
3179                                           Vertices,
3180                                           VertexCount,
3181                                           Flags);
3182 }
3183
3184 /*****************************************************************************
3185  * IDirect3DDevice7::DrawIndexedPrimitive
3186  *
3187  * Draws vertices from an application-provided pointer, based on the index
3188  * numbers in a WORD array.
3189  *
3190  * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3191  * an FVF format for D3D7
3192  *
3193  * Params:
3194  *  PrimitiveType: The primitive type to draw
3195  *  VertexType: The FVF vertex description
3196  *  Vertices: Pointer to the vertex array
3197  *  VertexCount: ?
3198  *  Indices: Pointer to the index array
3199  *  IndexCount: Number of indices = Number of vertices to draw
3200  *  Flags: As usual, some flags
3201  *
3202  * Returns:
3203  *  D3D_OK on success
3204  *  DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3205  *  For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3206  *
3207  *****************************************************************************/
3208 static HRESULT WINAPI
3209 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3210                                            D3DPRIMITIVETYPE PrimitiveType,
3211                                            DWORD VertexType,
3212                                            void *Vertices,
3213                                            DWORD VertexCount,
3214                                            WORD *Indices,
3215                                            DWORD IndexCount,
3216                                            DWORD Flags)
3217 {
3218     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3219     UINT PrimitiveCount = 0;
3220     HRESULT hr;
3221     TRACE("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x): Relay!\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3222
3223     /* Get the primitive number */
3224     switch(PrimitiveType)
3225     {
3226       case D3DPT_POINTLIST: 
3227         PrimitiveCount = IndexCount;
3228         break;
3229
3230       case D3DPT_LINELIST: 
3231         PrimitiveCount = IndexCount / 2;
3232         break;
3233
3234       case D3DPT_LINESTRIP:
3235         PrimitiveCount = IndexCount - 1;
3236         break;
3237
3238       case D3DPT_TRIANGLELIST:
3239         PrimitiveCount = IndexCount / 3;
3240         break;
3241
3242       case D3DPT_TRIANGLESTRIP:
3243         PrimitiveCount = IndexCount - 2;
3244         break;
3245
3246       case D3DPT_TRIANGLEFAN:
3247         PrimitiveCount = IndexCount - 2;
3248         break;
3249
3250       default:
3251         return DDERR_INVALIDPARAMS;
3252     }
3253
3254     /* Set the D3DDevice's FVF */
3255     EnterCriticalSection(&ddraw_cs);
3256     hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
3257                                              IDirectDrawImpl_FindDecl(This->ddraw, VertexType));
3258     if(FAILED(hr))
3259     {
3260         ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3261         LeaveCriticalSection(&ddraw_cs);
3262         return hr;
3263     }
3264
3265     hr = IWineD3DDevice_DrawIndexedPrimitiveUP(This->wineD3DDevice,
3266                                                PrimitiveType,
3267                                                0 /* MinVertexIndex */,
3268                                                VertexCount /* UINT NumVertexIndex */,
3269                                                PrimitiveCount,
3270                                                Indices,
3271                                                WINED3DFMT_INDEX16,
3272                                                Vertices,
3273                                                get_flexible_vertex_size(VertexType));
3274     LeaveCriticalSection(&ddraw_cs);
3275     return hr;
3276 }
3277
3278 static HRESULT WINAPI
3279 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3280                                                  D3DPRIMITIVETYPE PrimitiveType,
3281                                                  DWORD VertexType,
3282                                                  void *Vertices,
3283                                                  DWORD VertexCount,
3284                                                  WORD *Indices,
3285                                                  DWORD IndexCount,
3286                                                  DWORD Flags)
3287 {
3288     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3289     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3290     return IDirect3DDevice7_DrawIndexedPrimitive(ICOM_INTERFACE(This, IDirect3DDevice7),
3291                                                  PrimitiveType,
3292                                                  VertexType,
3293                                                  Vertices,
3294                                                  VertexCount,
3295                                                  Indices,
3296                                                  IndexCount,
3297                                                  Flags);
3298 }
3299
3300 static HRESULT WINAPI
3301 Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3302                                                  D3DPRIMITIVETYPE PrimitiveType,
3303                                                  D3DVERTEXTYPE VertexType,
3304                                                  void *Vertices,
3305                                                  DWORD VertexCount,
3306                                                  WORD *Indices,
3307                                                  DWORD IndexCount,
3308                                                  DWORD Flags)
3309 {
3310     DWORD FVF;
3311     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3312     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3313
3314     switch(VertexType)
3315     {
3316         case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3317         case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3318         case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3319         default:
3320             ERR("Unexpected vertex type %d\n", VertexType);
3321             return DDERR_INVALIDPARAMS;  /* Should never happen */
3322     }
3323
3324     return IDirect3DDevice7_DrawIndexedPrimitive(ICOM_INTERFACE(This, IDirect3DDevice7),
3325                                                  PrimitiveType,
3326                                                  FVF,
3327                                                  Vertices,
3328                                                  VertexCount,
3329                                                  Indices,
3330                                                  IndexCount,
3331                                                  Flags);
3332 }
3333
3334 /*****************************************************************************
3335  * IDirect3DDevice7::SetClipStatus
3336  *
3337  * Sets the clip status. This defines things as clipping conditions and
3338  * the extents of the clipping region.
3339  *
3340  * Version 2, 3 and 7
3341  *
3342  * Params:
3343  *  ClipStatus:
3344  *
3345  * Returns:
3346  *  D3D_OK because it's a stub
3347  *  (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3348  *
3349  *****************************************************************************/
3350 static HRESULT WINAPI
3351 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3352                                     D3DCLIPSTATUS *ClipStatus)
3353 {
3354     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3355     FIXME("(%p)->(%p): Stub!\n", This, ClipStatus);
3356
3357     /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3358      * Perhaps this needs a new data type and an additional IWineD3DDevice method
3359      */
3360     /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3361     return D3D_OK;
3362 }
3363
3364 static HRESULT WINAPI
3365 Thunk_IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3366                                           D3DCLIPSTATUS *ClipStatus)
3367 {
3368     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3369     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3370     return IDirect3DDevice7_SetClipStatus(ICOM_INTERFACE(This, IDirect3DDevice7),
3371                                           ClipStatus);
3372 }
3373
3374 static HRESULT WINAPI
3375 Thunk_IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3376                                           D3DCLIPSTATUS *ClipStatus)
3377 {
3378     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3379     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3380     return IDirect3DDevice7_SetClipStatus(ICOM_INTERFACE(This, IDirect3DDevice7),
3381                                           ClipStatus);
3382 }
3383
3384 /*****************************************************************************
3385  * IDirect3DDevice7::GetClipStatus
3386  *
3387  * Returns the clip status
3388  *
3389  * Params:
3390  *  ClipStatus: Address to write the clip status to
3391  *
3392  * Returns:
3393  *  D3D_OK because it's a stub
3394  *
3395  *****************************************************************************/
3396 static HRESULT WINAPI
3397 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3398                                     D3DCLIPSTATUS *ClipStatus)
3399 {
3400     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3401     FIXME("(%p)->(%p): Stub!\n", This, ClipStatus);
3402
3403     /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3404     /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3405     return D3D_OK;
3406 }
3407
3408 static HRESULT WINAPI
3409 Thunk_IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3410                                           D3DCLIPSTATUS *ClipStatus)
3411 {
3412     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3413     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3414     return IDirect3DDevice7_GetClipStatus(ICOM_INTERFACE(This, IDirect3DDevice7),
3415                                           ClipStatus);
3416 }
3417
3418 static HRESULT WINAPI
3419 Thunk_IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3420                                           D3DCLIPSTATUS *ClipStatus)
3421 {
3422     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3423     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3424     return IDirect3DDevice7_GetClipStatus(ICOM_INTERFACE(This, IDirect3DDevice7),
3425                                           ClipStatus);
3426 }
3427
3428 /*****************************************************************************
3429  * IDirect3DDevice::DrawPrimitiveStrided
3430  *
3431  * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3432  *
3433  * Version 3 and 7
3434  *
3435  * Params:
3436  *  PrimitiveType: The primitive type to draw
3437  *  VertexType: The FVF description of the vertices to draw (for the stride??)
3438  *  D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3439  *                         the vertex data locations
3440  *  VertexCount: The number of vertices to draw
3441  *  Flags: Some flags
3442  *
3443  * Returns:
3444  *  D3D_OK, because it's a stub
3445  *  (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3446  *  (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3447  *
3448  *****************************************************************************/
3449 static HRESULT WINAPI
3450 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3451                                            D3DPRIMITIVETYPE PrimitiveType,
3452                                            DWORD VertexType,
3453                                            D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3454                                            DWORD VertexCount,
3455                                            DWORD Flags)
3456 {
3457     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3458     WineDirect3DVertexStridedData WineD3DStrided;
3459     int i;
3460     UINT PrimitiveCount;
3461     HRESULT hr;
3462
3463     TRACE("(%p)->(%08x,%08x,%p,%08x,%08x): stub!\n", This, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3464
3465     memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3466     /* Get the strided data right. the wined3d structure is a bit bigger
3467      * Watch out: The contents of the strided data are determined by the fvf,
3468      * not by the members set in D3DDrawPrimStrideData. So it's valid
3469      * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3470      * not set in the fvf.
3471      */
3472     if(VertexType & D3DFVF_POSITION_MASK)
3473     {
3474         WineD3DStrided.u.s.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3475         WineD3DStrided.u.s.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3476         WineD3DStrided.u.s.position.dwType = WINED3DDECLTYPE_FLOAT3;
3477         if (VertexType & D3DFVF_XYZRHW)
3478         {
3479             WineD3DStrided.u.s.position.dwType = WINED3DDECLTYPE_FLOAT4;
3480             WineD3DStrided.u.s.position_transformed = TRUE;
3481         } else
3482             WineD3DStrided.u.s.position_transformed = FALSE;
3483     }
3484
3485     if(VertexType & D3DFVF_NORMAL)
3486     {
3487         WineD3DStrided.u.s.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3488         WineD3DStrided.u.s.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3489         WineD3DStrided.u.s.normal.dwType = WINED3DDECLTYPE_FLOAT3;
3490     }
3491
3492     if(VertexType & D3DFVF_DIFFUSE)
3493     {
3494         WineD3DStrided.u.s.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3495         WineD3DStrided.u.s.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3496         WineD3DStrided.u.s.diffuse.dwType = WINED3DDECLTYPE_SHORT4;
3497     }
3498
3499     if(VertexType & D3DFVF_SPECULAR)
3500     {
3501         WineD3DStrided.u.s.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3502         WineD3DStrided.u.s.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3503         WineD3DStrided.u.s.specular.dwType = WINED3DDECLTYPE_SHORT4;
3504     }
3505
3506     for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3507     {
3508         WineD3DStrided.u.s.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3509         WineD3DStrided.u.s.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3510         switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3511         {
3512             case 1: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT1; break;
3513             case 2: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT2; break;
3514             case 3: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT3; break;
3515             case 4: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT4; break;
3516             default: ERR("Unexpected texture coordinate size %d\n",
3517                          GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3518         }
3519     }
3520
3521     /* Get the primitive count */
3522     switch(PrimitiveType)
3523     {
3524         case D3DPT_POINTLIST: 
3525           PrimitiveCount = VertexCount;
3526           break;
3527
3528         case D3DPT_LINELIST: 
3529           PrimitiveCount = VertexCount / 2;
3530           break;
3531
3532         case D3DPT_LINESTRIP:
3533           PrimitiveCount = VertexCount - 1;
3534           break;
3535
3536         case D3DPT_TRIANGLELIST:
3537           PrimitiveCount = VertexCount / 3;
3538           break;
3539
3540         case D3DPT_TRIANGLESTRIP:
3541           PrimitiveCount = VertexCount - 2;
3542           break;
3543
3544         case D3DPT_TRIANGLEFAN:
3545           PrimitiveCount = VertexCount - 2;
3546           break;
3547
3548         default: return DDERR_INVALIDPARAMS;
3549     }
3550
3551     /* WineD3D doesn't need the FVF here */
3552     EnterCriticalSection(&ddraw_cs);
3553     hr = IWineD3DDevice_DrawPrimitiveStrided(This->wineD3DDevice,
3554                                              PrimitiveType,
3555                                              PrimitiveCount,
3556                                              &WineD3DStrided);
3557     LeaveCriticalSection(&ddraw_cs);
3558     return hr;
3559 }
3560
3561 static HRESULT WINAPI
3562 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3563                                                  D3DPRIMITIVETYPE PrimitiveType,
3564                                                  DWORD VertexType,
3565                                                  D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3566                                                  DWORD VertexCount,
3567                                                  DWORD Flags)
3568 {
3569     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3570     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3571     return IDirect3DDevice7_DrawPrimitiveStrided(ICOM_INTERFACE(This, IDirect3DDevice7),
3572                                                  PrimitiveType,
3573                                                  VertexType,
3574                                                  D3DDrawPrimStrideData,
3575                                                  VertexCount,
3576                                                  Flags);
3577 }
3578
3579 /*****************************************************************************
3580  * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3581  *
3582  * Draws primitives specified by strided data locations based on indices
3583  *
3584  * Version 3 and 7
3585  *
3586  * Params:
3587  *  PrimitiveType:
3588  *
3589  * Returns:
3590  *  D3D_OK, because it's a stub
3591  *  (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3592  *  (DDERR_INVALIDPARAMS if Indices is NULL)
3593  *  (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3594  *
3595  *****************************************************************************/
3596 static HRESULT WINAPI
3597 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3598                                                   D3DPRIMITIVETYPE PrimitiveType,
3599                                                   DWORD VertexType,
3600                                                   D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3601                                                   DWORD VertexCount,
3602                                                   WORD *Indices,
3603                                                   DWORD IndexCount,
3604                                                   DWORD Flags)
3605 {
3606     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3607     FIXME("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x): stub!\n", This, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3608
3609     /* I'll implement it as soon as I find a app to test it.
3610      * This needs an additional method in IWineD3DDevice.
3611      */
3612     return D3D_OK;
3613 }
3614
3615 static HRESULT WINAPI
3616 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
3617                                                         D3DPRIMITIVETYPE PrimitiveType,
3618                                                         DWORD VertexType,
3619                                                         D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3620                                                         DWORD VertexCount,
3621                                                         WORD *Indices,
3622                                                         DWORD IndexCount,
3623                                                         DWORD Flags)
3624 {
3625     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3626     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3627     return IDirect3DDevice7_DrawIndexedPrimitiveStrided(ICOM_INTERFACE(This, IDirect3DDevice7),
3628                                                         PrimitiveType,
3629                                                         VertexType,
3630                                                         D3DDrawPrimStrideData,
3631                                                         VertexCount,
3632                                                         Indices,
3633                                                         IndexCount,
3634                                                         Flags);
3635 }
3636
3637 /*****************************************************************************
3638  * IDirect3DDevice7::DrawPrimitiveVB
3639  *
3640  * Draws primitives from a vertex buffer to the screen.
3641  *
3642  * Version 3 and 7
3643  *
3644  * Params:
3645  *  PrimitiveType: Type of primitive to be rendered.
3646  *  D3DVertexBuf: Source Vertex Buffer
3647  *  StartVertex: Index of the first vertex from the buffer to be rendered
3648  *  NumVertices: Number of vertices to be rendered
3649  *  Flags: Can be D3DDP_WAIT to wait until rendering has finished
3650  *
3651  * Return values
3652  *  D3D_OK on success
3653  *  DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
3654  *
3655  *****************************************************************************/
3656 static HRESULT WINAPI
3657 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
3658                                       D3DPRIMITIVETYPE PrimitiveType,
3659                                       IDirect3DVertexBuffer7 *D3DVertexBuf,
3660                                       DWORD StartVertex,
3661                                       DWORD NumVertices,
3662                                       DWORD Flags)
3663 {
3664     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3665     IDirect3DVertexBufferImpl *vb = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, D3DVertexBuf);
3666     UINT PrimitiveCount;
3667     HRESULT hr;
3668     DWORD stride;
3669     WINED3DVERTEXBUFFER_DESC Desc;
3670
3671     TRACE("(%p)->(%08x,%p,%08x,%08x,%08x)\n", This, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
3672
3673     /* Sanity checks */
3674     if(!vb)
3675     {
3676         ERR("(%p) No Vertex buffer specified\n", This);
3677         return DDERR_INVALIDPARAMS;
3678     }
3679
3680     /* Get the primitive count */
3681     switch(PrimitiveType)
3682     {
3683         case D3DPT_POINTLIST: 
3684           PrimitiveCount = NumVertices;
3685           break;
3686
3687         case D3DPT_LINELIST: 
3688           PrimitiveCount = NumVertices / 2;
3689           break;
3690
3691         case D3DPT_LINESTRIP:
3692           PrimitiveCount = NumVertices - 1;
3693           break;
3694
3695         case D3DPT_TRIANGLELIST:
3696           PrimitiveCount = NumVertices / 3;
3697           break;
3698
3699         case D3DPT_TRIANGLESTRIP:
3700           PrimitiveCount = NumVertices - 2;
3701           break;
3702
3703         case D3DPT_TRIANGLEFAN:
3704           PrimitiveCount = NumVertices - 2;
3705           break;
3706
3707         default:
3708           return DDERR_INVALIDPARAMS;
3709     }
3710
3711     /* Get the FVF of the vertex buffer, and its stride */
3712     EnterCriticalSection(&ddraw_cs);
3713     hr = IWineD3DVertexBuffer_GetDesc(vb->wineD3DVertexBuffer,
3714                                       &Desc);
3715     if(hr != D3D_OK)
3716     {
3717         ERR("(%p) IWineD3DVertexBuffer::GetDesc failed with hr = %08x\n", This, hr);
3718         LeaveCriticalSection(&ddraw_cs);
3719         return hr;
3720     }
3721     stride = get_flexible_vertex_size(Desc.FVF);
3722
3723     hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
3724                                              vb->wineD3DVertexDeclaration);
3725     if(FAILED(hr))
3726     {
3727         ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3728         LeaveCriticalSection(&ddraw_cs);
3729         return hr;
3730     }
3731
3732     /* Set the vertex stream source */
3733     hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
3734                                         0 /* StreamNumber */,
3735                                         vb->wineD3DVertexBuffer,
3736                                         0 /* StartVertex - we pass this to DrawPrimitive */,
3737                                         stride);
3738     if(hr != D3D_OK)
3739     {
3740         ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
3741         LeaveCriticalSection(&ddraw_cs);
3742         return hr;
3743     }
3744
3745     /* Now draw the primitives */
3746     hr = IWineD3DDevice_DrawPrimitive(This->wineD3DDevice,
3747                                       PrimitiveType,
3748                                       StartVertex,
3749                                       PrimitiveCount);
3750     LeaveCriticalSection(&ddraw_cs);
3751     return hr;
3752 }
3753
3754 static HRESULT WINAPI
3755 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
3756                                             D3DPRIMITIVETYPE PrimitiveType,
3757                                             IDirect3DVertexBuffer *D3DVertexBuf,
3758                                             DWORD StartVertex,
3759                                             DWORD NumVertices,
3760                                             DWORD Flags)
3761 {
3762     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3763     IDirect3DVertexBufferImpl *vb = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, D3DVertexBuf);
3764     TRACE_(ddraw_thunk)("(%p)->(%08x,%p,%08x,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This,  PrimitiveType, vb, StartVertex, NumVertices, Flags);
3765     return IDirect3DDevice7_DrawPrimitiveVB(ICOM_INTERFACE(This, IDirect3DDevice7),
3766                                             PrimitiveType,
3767                                             ICOM_INTERFACE(vb, IDirect3DVertexBuffer7),
3768                                             StartVertex,
3769                                             NumVertices,
3770                                             Flags);
3771 }
3772
3773
3774 /*****************************************************************************
3775  * IDirect3DDevice7::DrawIndexedPrimitiveVB
3776  *
3777  * Draws primitives from a vertex buffer to the screen
3778  *
3779  * Params:
3780  *  PrimitiveType: Type of primitive to be rendered.
3781  *  D3DVertexBuf: Source Vertex Buffer
3782  *  StartVertex: Index of the first vertex from the buffer to be rendered
3783  *  NumVertices: Number of vertices to be rendered
3784  *  Indices: Array of DWORDs used to index into the Vertices
3785  *  IndexCount: Number of indices in Indices
3786  *  Flags: Can be D3DDP_WAIT to wait until rendering has finished
3787  *
3788  * Return values
3789  *
3790  *****************************************************************************/
3791 static HRESULT WINAPI
3792 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
3793                                              D3DPRIMITIVETYPE PrimitiveType,
3794                                              IDirect3DVertexBuffer7 *D3DVertexBuf,
3795                                              DWORD StartVertex,
3796                                              DWORD NumVertices,
3797                                              WORD *Indices,
3798                                              DWORD IndexCount,
3799                                              DWORD Flags)
3800 {
3801     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3802     IDirect3DVertexBufferImpl *vb = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, D3DVertexBuf);
3803     DWORD stride;
3804     UINT PrimitiveCount;
3805     WORD *LockedIndices;
3806     HRESULT hr;
3807     WINED3DVERTEXBUFFER_DESC Desc;
3808
3809     TRACE("(%p)->(%08x,%p,%d,%d,%p,%d,%08x)\n", This, PrimitiveType, vb, StartVertex, NumVertices, Indices, IndexCount, Flags);
3810
3811     /* Steps:
3812      * 1) Calculate some things: Vertex count -> Primitive count, stride, ...
3813      * 2) Upload the Indices to the index buffer
3814      * 3) Set the index source
3815      * 4) Set the Vertex Buffer as the Stream source
3816      * 5) Call IWineD3DDevice::DrawIndexedPrimitive
3817      */
3818
3819     /* Get the primitive count */
3820     switch(PrimitiveType)
3821     {
3822         case D3DPT_POINTLIST: 
3823           PrimitiveCount = IndexCount;
3824           break;
3825
3826         case D3DPT_LINELIST: 
3827           PrimitiveCount = IndexCount / 2;
3828           break;
3829
3830         case D3DPT_LINESTRIP:
3831           PrimitiveCount = IndexCount - 1;
3832           break;
3833
3834         case D3DPT_TRIANGLELIST:
3835           PrimitiveCount = IndexCount / 3;
3836           break;
3837
3838         case D3DPT_TRIANGLESTRIP:
3839           PrimitiveCount = IndexCount - 2;
3840           break;
3841
3842         case D3DPT_TRIANGLEFAN:
3843           PrimitiveCount = IndexCount - 2;
3844           break;
3845
3846         default: return DDERR_INVALIDPARAMS;
3847     }
3848
3849     EnterCriticalSection(&ddraw_cs);
3850     /* Get the FVF of the vertex buffer, and its stride */
3851     hr = IWineD3DVertexBuffer_GetDesc(vb->wineD3DVertexBuffer,
3852                                       &Desc);
3853     if(hr != D3D_OK)
3854     {
3855         ERR("(%p) IWineD3DVertexBuffer::GetDesc failed with hr = %08x\n", This, hr);
3856         LeaveCriticalSection(&ddraw_cs);
3857         return hr;
3858     }
3859     stride = get_flexible_vertex_size(Desc.FVF);
3860     TRACE("Vertex buffer FVF = %08x, stride=%d\n", Desc.FVF, stride);
3861
3862     hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
3863                                              vb->wineD3DVertexDeclaration);
3864     if(FAILED(hr))
3865     {
3866         ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3867         LeaveCriticalSection(&ddraw_cs);
3868         return hr;
3869     }
3870
3871     /* copy the index stream into the index buffer.
3872      * A new IWineD3DDevice method could be created
3873      * which takes an user pointer containing the indices
3874      * or a SetData-Method for the index buffer, which
3875      * overrides the index buffer data with our pointer.
3876      */
3877     hr = IWineD3DIndexBuffer_Lock(This->indexbuffer,
3878                                   0 /* OffSetToLock */,
3879                                   IndexCount * sizeof(WORD),
3880                                   (BYTE **) &LockedIndices,
3881                                   0 /* Flags */);
3882     assert(IndexCount < 0x100000);
3883     if(hr != D3D_OK)
3884     {
3885         ERR("(%p) IWineD3DIndexBuffer::Lock failed with hr = %08x\n", This, hr);
3886         LeaveCriticalSection(&ddraw_cs);
3887         return hr;
3888     }
3889     memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
3890     hr = IWineD3DIndexBuffer_Unlock(This->indexbuffer);
3891     if(hr != D3D_OK)
3892     {
3893         ERR("(%p) IWineD3DIndexBuffer::Unlock failed with hr = %08x\n", This, hr);
3894         LeaveCriticalSection(&ddraw_cs);
3895         return hr;
3896     }
3897
3898     /* Set the index stream */
3899     hr = IWineD3DDevice_SetIndices(This->wineD3DDevice,
3900                                    This->indexbuffer,
3901                                    StartVertex);
3902
3903     /* Set the vertex stream source */
3904     hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
3905                                         0 /* StreamNumber */,
3906                                         vb->wineD3DVertexBuffer,
3907                                         0 /* offset, we pass this to DrawIndexedPrimitive */,
3908                                         stride);
3909     if(hr != D3D_OK)
3910     {
3911         ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
3912         LeaveCriticalSection(&ddraw_cs);
3913         return hr;
3914     }
3915
3916
3917     hr = IWineD3DDevice_DrawIndexedPrimitive(This->wineD3DDevice,
3918                                              PrimitiveType,
3919                                              0 /* minIndex */,
3920                                              NumVertices,
3921                                              0 /* StartIndex */,
3922                                              PrimitiveCount);
3923
3924     LeaveCriticalSection(&ddraw_cs);
3925     return hr;
3926 }
3927
3928 static HRESULT WINAPI
3929 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
3930                                                    D3DPRIMITIVETYPE PrimitiveType,
3931                                                    IDirect3DVertexBuffer *D3DVertexBuf,
3932                                                    WORD *Indices,
3933                                                    DWORD IndexCount,
3934                                                    DWORD Flags)
3935 {
3936     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3937     IDirect3DVertexBufferImpl *VB = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, D3DVertexBuf);
3938     TRACE_(ddraw_thunk)("(%p)->(%08x,%p,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VB, Indices, IndexCount, Flags);
3939
3940     return IDirect3DDevice7_DrawIndexedPrimitiveVB(ICOM_INTERFACE(This, IDirect3DDevice7),
3941                                                    PrimitiveType,
3942                                                    ICOM_INTERFACE(VB, IDirect3DVertexBuffer7),
3943                                                    0,
3944                                                    IndexCount,
3945                                                    Indices,
3946                                                    IndexCount,
3947                                                    Flags);
3948 }
3949
3950 /*****************************************************************************
3951  * IDirect3DDevice7::ComputeSphereVisibility
3952  *
3953  * Calculates the visibility of spheres in the current viewport. The spheres
3954  * are passed in the Centers and Radii arrays, the results are passed back
3955  * in the ReturnValues array. Return values are either completely visible,
3956  * partially visible or completely invisible.
3957  * The return value consist of a combination of D3DCLIP_* flags, or it's
3958  * 0 if the sphere is completely visible(according to the SDK, not checked)
3959  *
3960  * Sounds like an overdose of math ;)
3961  *
3962  * Version 3 and 7
3963  *
3964  * Params:
3965  *  Centers: Array containing the sphere centers
3966  *  Radii: Array containing the sphere radii
3967  *  NumSpheres: The number of centers and radii in the arrays
3968  *  Flags: Some flags
3969  *  ReturnValues: Array to write the results to
3970  *
3971  * Returns:
3972  *  D3D_OK because it's a stub
3973  *  (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
3974  *  (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
3975  *  is singular)
3976  *
3977  *****************************************************************************/
3978 static HRESULT WINAPI
3979 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
3980                                               D3DVECTOR *Centers,
3981                                               D3DVALUE *Radii,
3982                                               DWORD NumSpheres,
3983                                               DWORD Flags,
3984                                               DWORD *ReturnValues)
3985 {
3986     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3987     FIXME("(%p)->(%p,%p,%08x,%08x,%p): stub!\n", This, Centers, Radii, NumSpheres, Flags, ReturnValues);
3988
3989     /* the DirectX 7 sdk says that the visibility is computed by
3990      * back-transforming the viewing frustum to model space
3991      * using the inverse of the combined world, view and projection
3992      * matrix. If the matrix can't be reversed, D3DERR_INVALIDMATRIX
3993      * is returned.
3994      *
3995      * Basic implementation idea:
3996      * 1) Check if the center is in the viewing frustum
3997      * 2) Cut the sphere with the planes of the viewing
3998      *    frustum
3999      *
4000      * ->Center inside the frustum, no intersections:
4001      *    Fully visible
4002      * ->Center outside the frustum, no intersections:
4003      *    Not visible
4004      * ->Some intersections: Partially visible
4005      *
4006      * Implement this call in WineD3D. Either implement the
4007      * matrix and vector stuff in WineD3D, or use some external
4008      * math library.
4009      */
4010
4011     return D3D_OK;
4012 }
4013
4014 static HRESULT WINAPI
4015 Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4016                                                     D3DVECTOR *Centers,
4017                                                     D3DVALUE *Radii,
4018                                                     DWORD NumSpheres,
4019                                                     DWORD Flags,
4020                                                     DWORD *ReturnValues)
4021 {
4022     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4023     TRACE_(ddraw_thunk)("(%p)->(%p,%p,%08x,%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, Centers, Radii, NumSpheres, Flags, ReturnValues);
4024     return IDirect3DDevice7_ComputeSphereVisibility(ICOM_INTERFACE(This, IDirect3DDevice7),
4025                                                     Centers,
4026                                                     Radii,
4027                                                     NumSpheres,
4028                                                     Flags,
4029                                                     ReturnValues);
4030 }
4031
4032 /*****************************************************************************
4033  * IDirect3DDevice7::GetTexture
4034  *
4035  * Returns the texture interface handle assigned to a texture stage.
4036  * The returned texture is AddRefed. This is taken from old ddraw,
4037  * not checked in Windows.
4038  *
4039  * Version 3 and 7
4040  *
4041  * Params:
4042  *  Stage: Texture stage to read the texture from
4043  *  Texture: Address to store the interface pointer at
4044  *
4045  * Returns:
4046  *  D3D_OK on success
4047  *  DDERR_INVALIDPARAMS if Texture is NULL
4048  *  For details, see IWineD3DDevice::GetTexture
4049  *
4050  *****************************************************************************/
4051 static HRESULT WINAPI
4052 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4053                                  DWORD Stage,
4054                                  IDirectDrawSurface7 **Texture)
4055 {
4056     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4057     IWineD3DBaseTexture *Surf;
4058     HRESULT hr;
4059     TRACE("(%p)->(%d,%p): Relay\n", This, Stage, Texture);
4060
4061     if(!Texture)
4062     {
4063         TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4064         return DDERR_INVALIDPARAMS;
4065     }
4066
4067     EnterCriticalSection(&ddraw_cs);
4068     hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, Stage, (IWineD3DBaseTexture **) &Surf);
4069     if( (hr != D3D_OK) || (!Surf) ) 
4070     {
4071         *Texture = NULL;
4072         LeaveCriticalSection(&ddraw_cs);
4073         return hr;
4074     }
4075
4076     /* GetParent AddRef()s, which is perfectly OK.
4077      * We have passed the IDirectDrawSurface7 interface to WineD3D, so that's OK too.
4078      */
4079     hr = IWineD3DBaseTexture_GetParent(Surf,
4080                                        (IUnknown **) Texture);
4081     LeaveCriticalSection(&ddraw_cs);
4082     return hr;
4083 }
4084
4085 static HRESULT WINAPI
4086 Thunk_IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface,
4087                                        DWORD Stage,
4088                                        IDirect3DTexture2 **Texture2)
4089 {
4090     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4091     HRESULT ret;
4092     IDirectDrawSurface7 *ret_val;
4093
4094     TRACE_(ddraw_thunk)("(%p)->(%d,%p) thunking to IDirect3DDevice7 interface.\n", This, Stage, Texture2);
4095     ret = IDirect3DDevice7_GetTexture(ICOM_INTERFACE(This, IDirect3DDevice7),
4096                                       Stage,
4097                                       &ret_val);
4098
4099     *Texture2 = COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirectDrawSurface7, IDirect3DTexture2, ret_val);
4100
4101     TRACE_(ddraw_thunk)(" returning interface %p.\n", *Texture2);
4102
4103     return ret;
4104 }
4105
4106 /*****************************************************************************
4107  * IDirect3DDevice7::SetTexture
4108  *
4109  * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4110  *
4111  * Version 3 and 7
4112  *
4113  * Params:
4114  *  Stage: The stage to assign the texture to
4115  *  Texture: Interface pointer to the texture surface
4116  *
4117  * Returns
4118  * D3D_OK on success
4119  * For details, see IWineD3DDevice::SetTexture
4120  *
4121  *****************************************************************************/
4122 static HRESULT WINAPI
4123 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4124                                  DWORD Stage,
4125                                  IDirectDrawSurface7 *Texture)
4126 {
4127     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4128     IDirectDrawSurfaceImpl *surf = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, Texture);
4129     HRESULT hr;
4130     TRACE("(%p)->(%08x,%p): Relay!\n", This, Stage, surf);
4131
4132     /* Texture may be NULL here */
4133     EnterCriticalSection(&ddraw_cs);
4134     hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
4135                                    Stage,
4136                                    surf ? surf->wineD3DTexture : NULL);
4137     LeaveCriticalSection(&ddraw_cs);
4138     return hr;
4139 }
4140
4141 static HRESULT WINAPI
4142 Thunk_IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4143                                        DWORD Stage,
4144                                        IDirect3DTexture2 *Texture2)
4145 {
4146     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4147     IDirectDrawSurfaceImpl *tex = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture2, Texture2);
4148     TRACE_(ddraw_thunk)("(%p)->(%d,%p) thunking to IDirect3DDevice7 interface.\n", This, Stage, tex);
4149     return IDirect3DDevice7_SetTexture(ICOM_INTERFACE(This, IDirect3DDevice7),
4150                                        Stage,
4151                                        ICOM_INTERFACE(tex, IDirectDrawSurface7));
4152 }
4153
4154 /*****************************************************************************
4155  * IDirect3DDevice7::GetTextureStageState
4156  *
4157  * Retrieves a state from a texture stage.
4158  *
4159  * Version 3 and 7
4160  *
4161  * Params:
4162  *  Stage: The stage to retrieve the state from
4163  *  TexStageStateType: The state type to retrieve
4164  *  State: Address to store the state's value at
4165  *
4166  * Returns:
4167  *  D3D_OK on success
4168  *  DDERR_INVALIDPARAMS if State is NULL
4169  *  For details, see IWineD3DDevice::GetTextureStageState
4170  *
4171  *****************************************************************************/
4172 static HRESULT WINAPI
4173 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4174                                            DWORD Stage,
4175                                            D3DTEXTURESTAGESTATETYPE TexStageStateType,
4176                                            DWORD *State)
4177 {
4178     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4179     HRESULT hr;
4180     TRACE("(%p)->(%08x,%08x,%p): Relay!\n", This, Stage, TexStageStateType, State);
4181
4182     if(!State)
4183         return DDERR_INVALIDPARAMS;
4184
4185     EnterCriticalSection(&ddraw_cs);
4186     switch(TexStageStateType)
4187     {
4188         /* Mipfilter is a sampler state with different values */
4189         case D3DTSS_MIPFILTER:
4190         {
4191             WINED3DTEXTUREFILTERTYPE value;
4192
4193             hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
4194                                                 Stage,
4195                                                 WINED3DSAMP_MIPFILTER,
4196                                                 &value);
4197             switch(value)
4198             {
4199                 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4200                 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4201                 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4202                 default:
4203                     ERR("Unexpected mipfilter value %d\n", value);
4204                     *State = D3DTFP_NONE;
4205             }
4206             break;
4207         }
4208
4209         /* Minfilter is a sampler state too, equal values */
4210         case D3DTSS_MINFILTER:
4211             hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
4212                                                 Stage,
4213                                                 WINED3DSAMP_MINFILTER,
4214                                                 State);
4215             break;
4216
4217         /* Magfilter has slightly different values */
4218         case D3DTSS_MAGFILTER:
4219         {
4220             WINED3DTEXTUREFILTERTYPE wined3dfilter;
4221             hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
4222                                                 Stage,
4223                                                 WINED3DSAMP_MAGFILTER,
4224                                                 &wined3dfilter);
4225             switch(wined3dfilter)
4226             {
4227                 case WINED3DTEXF_POINT:             *State = D3DTFG_POINT;          break;
4228                 case WINED3DTEXF_LINEAR:            *State = D3DTFG_LINEAR;         break;
4229                 case WINED3DTEXF_ANISOTROPIC:       *State = D3DTFG_ANISOTROPIC;    break;
4230                 case WINED3DTEXF_FLATCUBIC:         *State = D3DTFG_FLATCUBIC;      break;
4231                 case WINED3DTEXF_GAUSSIANCUBIC:     *State = D3DTFG_GAUSSIANCUBIC;  break;
4232                 default:
4233                     ERR("Unexpected wined3d mag filter value %d\n", wined3dfilter);
4234                     *State = D3DTFG_POINT;
4235             }
4236             break;
4237         }
4238
4239         case D3DTSS_ADDRESS:
4240         case D3DTSS_ADDRESSU:
4241             hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
4242                                                 Stage,
4243                                                 WINED3DSAMP_ADDRESSU,
4244                                                 State);
4245             break;
4246         case D3DTSS_ADDRESSV:
4247             hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
4248                                                 Stage,
4249                                                 WINED3DSAMP_ADDRESSV,
4250                                                 State);
4251             break;
4252         default:
4253             hr = IWineD3DDevice_GetTextureStageState(This->wineD3DDevice,
4254                                                      Stage,
4255                                                      TexStageStateType,
4256                                                      State);
4257             break;
4258     }
4259     LeaveCriticalSection(&ddraw_cs);
4260     return hr;
4261 }
4262
4263 static HRESULT WINAPI
4264 Thunk_IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4265                                                  DWORD Stage,
4266                                                  D3DTEXTURESTAGESTATETYPE TexStageStateType,
4267                                                  DWORD *State)
4268 {
4269     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4270     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, Stage, TexStageStateType, State);
4271     return IDirect3DDevice7_GetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
4272                                                  Stage,
4273                                                  TexStageStateType,
4274                                                  State);
4275 }
4276
4277 /*****************************************************************************
4278  * IDirect3DDevice7::SetTextureStageState
4279  *
4280  * Sets a texture stage state. Some stage types need to be handled specially,
4281  * because they do not exist in WineD3D and were moved to another place
4282  *
4283  * Version 3 and 7
4284  *
4285  * Params:
4286  *  Stage: The stage to modify
4287  *  TexStageStateType: The state to change
4288  *  State: The new value for the state
4289  *
4290  * Returns:
4291  *  D3D_OK on success
4292  *  For details, see IWineD3DDevice::SetTextureStageState
4293  *
4294  *****************************************************************************/
4295 static HRESULT WINAPI
4296 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4297                                            DWORD Stage,
4298                                            D3DTEXTURESTAGESTATETYPE TexStageStateType,
4299                                            DWORD State)
4300 {
4301     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4302     HRESULT hr;
4303     TRACE("(%p)->(%08x,%08x,%08x): Relay!\n", This, Stage, TexStageStateType, State);
4304
4305     EnterCriticalSection(&ddraw_cs);
4306     switch(TexStageStateType)
4307     {
4308         /* Mipfilter is a sampler state with different values */
4309         case D3DTSS_MIPFILTER:
4310         {
4311             WINED3DTEXTUREFILTERTYPE value;
4312             switch(State)
4313             {
4314                 case D3DTFP_NONE: value = WINED3DTEXF_NONE; break;
4315                 case D3DTFP_POINT: value = WINED3DTEXF_POINT; break;
4316                 case 0: /* Unchecked */
4317                 case D3DTFP_LINEAR: value = WINED3DTEXF_LINEAR; break;
4318                 default:
4319                     ERR("Unexpected mipfilter value %d\n", State);
4320                     value = WINED3DTEXF_NONE;
4321             }
4322             hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
4323                                                 Stage,
4324                                                 WINED3DSAMP_MIPFILTER,
4325                                                 value);
4326             break;
4327         }
4328
4329         /* Minfilter is a sampler state too, equal values */
4330         case D3DTSS_MINFILTER:
4331             hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
4332                                                 Stage,
4333                                                 WINED3DSAMP_MINFILTER,
4334                                                 State);
4335             break;
4336
4337         /* Magfilter has slightly different values */
4338         case D3DTSS_MAGFILTER:
4339         {
4340             WINED3DTEXTUREFILTERTYPE wined3dfilter;
4341             switch((D3DTEXTUREMAGFILTER) State)
4342             {
4343                 case D3DTFG_POINT:          wined3dfilter = WINED3DTEXF_POINT;          break;
4344                 case D3DTFG_LINEAR:         wined3dfilter = WINED3DTEXF_LINEAR;         break;
4345                 case D3DTFG_FLATCUBIC:      wined3dfilter = WINED3DTEXF_FLATCUBIC;      break;
4346                 case D3DTFG_GAUSSIANCUBIC:  wined3dfilter = WINED3DTEXF_GAUSSIANCUBIC;  break;
4347                 case D3DTFG_ANISOTROPIC:    wined3dfilter = WINED3DTEXF_ANISOTROPIC;    break;
4348                 default:
4349                     ERR("Unexpected d3d7 mag filter type %d\n", State);
4350                     wined3dfilter = WINED3DTEXF_POINT;
4351             }
4352             hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
4353                                                 Stage,
4354                                                 WINED3DSAMP_MAGFILTER,
4355                                                 wined3dfilter);
4356             break;
4357         }
4358
4359         case D3DTSS_ADDRESS:
4360                    IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
4361                                                   Stage,
4362                                                   WINED3DSAMP_ADDRESSV,
4363                                                   State);
4364             /* Drop through */
4365         case D3DTSS_ADDRESSU:
4366             hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
4367                                                 Stage,
4368                                                 WINED3DSAMP_ADDRESSU,
4369                                                 State);
4370             break;
4371
4372         case D3DTSS_ADDRESSV:
4373             hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
4374                                                 Stage,
4375                                                 WINED3DSAMP_ADDRESSV,
4376                                                 State);
4377             break;
4378
4379         default:
4380             hr = IWineD3DDevice_SetTextureStageState(This->wineD3DDevice,
4381                                                      Stage,
4382                                                      TexStageStateType,
4383                                                      State);
4384             break;
4385     }
4386     LeaveCriticalSection(&ddraw_cs);
4387     return hr;
4388 }
4389
4390 static HRESULT WINAPI
4391 Thunk_IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
4392                                                  DWORD Stage,
4393                                                  D3DTEXTURESTAGESTATETYPE TexStageStateType,
4394                                                  DWORD State)
4395 {
4396     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4397     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, Stage, TexStageStateType, State);
4398     return IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
4399                                                  Stage,
4400                                                  TexStageStateType,
4401                                                  State);
4402 }
4403
4404 /*****************************************************************************
4405  * IDirect3DDevice7::ValidateDevice
4406  *
4407  * SDK: "Reports the device's ability to render the currently set
4408  * texture-blending operations in a single pass". Whatever that means
4409  * exactly...
4410  *
4411  * Version 3 and 7
4412  *
4413  * Params:
4414  *  NumPasses: Address to write the number of necessary passes for the
4415  *             desired effect to.
4416  *
4417  * Returns:
4418  *  D3D_OK on success
4419  *  See IWineD3DDevice::ValidateDevice for more details
4420  *
4421  *****************************************************************************/
4422 static HRESULT WINAPI
4423 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
4424                                      DWORD *NumPasses)
4425 {
4426     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4427     HRESULT hr;
4428     TRACE("(%p)->(%p): Relay\n", This, NumPasses);
4429
4430     EnterCriticalSection(&ddraw_cs);
4431     hr = IWineD3DDevice_ValidateDevice(This->wineD3DDevice, NumPasses);
4432     LeaveCriticalSection(&ddraw_cs);
4433     return hr;
4434 }
4435
4436 static HRESULT WINAPI
4437 Thunk_IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface,
4438                                            DWORD *Passes)
4439 {
4440     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4441     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Passes);
4442     return IDirect3DDevice7_ValidateDevice(ICOM_INTERFACE(This, IDirect3DDevice7),
4443                                            Passes);
4444 }
4445
4446 /*****************************************************************************
4447  * IDirect3DDevice7::Clear
4448  *
4449  * Fills the render target, the z buffer and the stencil buffer with a
4450  * clear color / value
4451  *
4452  * Version 7 only
4453  *
4454  * Params:
4455  *  Count: Number of rectangles in Rects must be 0 if Rects is NULL
4456  *  Rects: Rectangles to clear. If NULL, the whole surface is cleared
4457  *  Flags: Some flags, as usual
4458  *  Color: Clear color for the render target
4459  *  Z: Clear value for the Z buffer
4460  *  Stencil: Clear value to store in each stencil buffer entry
4461  *
4462  * Returns:
4463  *  D3D_OK on success
4464  *  For details, see IWineD3DDevice::Clear
4465  *
4466  *****************************************************************************/
4467 static HRESULT WINAPI
4468 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
4469                             DWORD Count,
4470                             D3DRECT *Rects,
4471                             DWORD Flags,
4472                             D3DCOLOR Color,
4473                             D3DVALUE Z,
4474                             DWORD Stencil)
4475 {
4476     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4477     HRESULT hr;
4478     TRACE("(%p)->(%08x,%p,%08x,%08x,%f,%08x): Relay\n", This, Count, Rects, Flags, (DWORD) Color, Z, Stencil);
4479
4480     /* Note; D3DRECT is compatible with WINED3DRECT */
4481     EnterCriticalSection(&ddraw_cs);
4482     hr = IWineD3DDevice_Clear(This->wineD3DDevice, Count, (WINED3DRECT*) Rects, Flags, Color, Z, Stencil);
4483     LeaveCriticalSection(&ddraw_cs);
4484     return hr;
4485 }
4486
4487 /*****************************************************************************
4488  * IDirect3DDevice7::SetViewport
4489  *
4490  * Sets the current viewport.
4491  *
4492  * Version 7 only, but IDirect3DViewport uses this call for older
4493  * versions
4494  *
4495  * Params:
4496  *  Data: The new viewport to set
4497  *
4498  * Returns:
4499  *  D3D_OK on success
4500  *  DDERR_INVALIDPARAMS if Data is NULL
4501  *  For more details, see IWineDDDevice::SetViewport
4502  *
4503  *****************************************************************************/
4504 static HRESULT WINAPI
4505 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
4506                                   D3DVIEWPORT7 *Data)
4507 {
4508     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4509     HRESULT hr;
4510     TRACE("(%p)->(%p) Relay!\n", This, Data);
4511
4512     if(!Data)
4513         return DDERR_INVALIDPARAMS;
4514
4515     /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
4516     EnterCriticalSection(&ddraw_cs);
4517     hr = IWineD3DDevice_SetViewport(This->wineD3DDevice,
4518                                     (WINED3DVIEWPORT*) Data);
4519     LeaveCriticalSection(&ddraw_cs);
4520     return hr;
4521 }
4522
4523 /*****************************************************************************
4524  * IDirect3DDevice::GetViewport
4525  *
4526  * Returns the current viewport
4527  *
4528  * Version 7
4529  *
4530  * Params:
4531  *  Data: D3D7Viewport structure to write the viewport information to
4532  *
4533  * Returns:
4534  *  D3D_OK on success
4535  *  DDERR_INVALIDPARAMS if Data is NULL
4536  *  For more details, see IWineD3DDevice::GetViewport
4537  *
4538  *****************************************************************************/
4539 static HRESULT WINAPI
4540 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
4541                                   D3DVIEWPORT7 *Data)
4542 {
4543     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4544     HRESULT hr;
4545     TRACE("(%p)->(%p) Relay!\n", This, Data);
4546
4547     if(!Data)
4548         return DDERR_INVALIDPARAMS;
4549
4550     /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
4551     EnterCriticalSection(&ddraw_cs);
4552     hr = IWineD3DDevice_GetViewport(This->wineD3DDevice,
4553                                     (WINED3DVIEWPORT*) Data);
4554
4555     LeaveCriticalSection(&ddraw_cs);
4556     return hr_ddraw_from_wined3d(hr);
4557 }
4558
4559 /*****************************************************************************
4560  * IDirect3DDevice7::SetMaterial
4561  *
4562  * Sets the Material
4563  *
4564  * Version 7
4565  *
4566  * Params:
4567  *  Mat: The material to set
4568  *
4569  * Returns:
4570  *  D3D_OK on success
4571  *  DDERR_INVALIDPARAMS if Mat is NULL.
4572  *  For more details, see IWineD3DDevice::SetMaterial
4573  *
4574  *****************************************************************************/
4575 static HRESULT WINAPI
4576 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
4577                                   D3DMATERIAL7 *Mat)
4578 {
4579     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4580     HRESULT hr;
4581     TRACE("(%p)->(%p): Relay!\n", This, Mat);
4582
4583     /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
4584     EnterCriticalSection(&ddraw_cs);
4585     hr = IWineD3DDevice_SetMaterial(This->wineD3DDevice,
4586                                     (WINED3DMATERIAL*) Mat);
4587     LeaveCriticalSection(&ddraw_cs);
4588     return hr_ddraw_from_wined3d(hr);
4589 }
4590
4591 /*****************************************************************************
4592  * IDirect3DDevice7::GetMaterial
4593  *
4594  * Returns the current material
4595  *
4596  * Version 7
4597  *
4598  * Params:
4599  *  Mat: D3DMATERIAL7 structure to write the material parameters to
4600  *
4601  * Returns:
4602  *  D3D_OK on success
4603  *  DDERR_INVALIDPARAMS if Mat is NULL
4604  *  For more details, see IWineD3DDevice::GetMaterial
4605  *
4606  *****************************************************************************/
4607 static HRESULT WINAPI
4608 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
4609                                   D3DMATERIAL7 *Mat)
4610 {
4611     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4612     HRESULT hr;
4613     TRACE("(%p)->(%p): Relay!\n", This, Mat);
4614
4615     EnterCriticalSection(&ddraw_cs);
4616     /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */ 
4617     hr = IWineD3DDevice_GetMaterial(This->wineD3DDevice,
4618                                     (WINED3DMATERIAL*) Mat);
4619     LeaveCriticalSection(&ddraw_cs);
4620     return hr_ddraw_from_wined3d(hr);
4621 }
4622
4623 /*****************************************************************************
4624  * IDirect3DDevice7::SetLight
4625  *
4626  * Assigns a light to a light index, but doesn't activate it yet.
4627  *
4628  * Version 7, IDirect3DLight uses this method for older versions
4629  *
4630  * Params:
4631  *  LightIndex: The index of the new light
4632  *  Light: A D3DLIGHT7 structure describing the light
4633  *
4634  * Returns:
4635  *  D3D_OK on success
4636  *  For more details, see IWineD3DDevice::SetLight
4637  *
4638  *****************************************************************************/
4639 static HRESULT WINAPI
4640 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
4641                                DWORD LightIndex,
4642                                D3DLIGHT7 *Light)
4643 {
4644     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4645     HRESULT hr;
4646     TRACE("(%p)->(%08x,%p): Relay!\n", This, LightIndex, Light);
4647
4648     EnterCriticalSection(&ddraw_cs);
4649     /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
4650     hr = IWineD3DDevice_SetLight(This->wineD3DDevice,
4651                                  LightIndex,
4652                                  (WINED3DLIGHT*) Light);
4653     LeaveCriticalSection(&ddraw_cs);
4654     return hr_ddraw_from_wined3d(hr);
4655 }
4656
4657 /*****************************************************************************
4658  * IDirect3DDevice7::GetLight
4659  *
4660  * Returns the light assigned to a light index
4661  *
4662  * Params:
4663  *  Light: Structure to write the light information to
4664  *
4665  * Returns:
4666  *  D3D_OK on success
4667  *  DDERR_INVALIDPARAMS if Light is NULL
4668  *  For details, see IWineD3DDevice::GetLight
4669  *
4670  *****************************************************************************/
4671 static HRESULT WINAPI
4672 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
4673                                DWORD LightIndex,
4674                                D3DLIGHT7 *Light)
4675 {
4676     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4677     HRESULT rc;
4678     TRACE("(%p)->(%08x,%p): Relay!\n", This, LightIndex, Light);
4679
4680     EnterCriticalSection(&ddraw_cs);
4681     /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
4682     rc =  IWineD3DDevice_GetLight(This->wineD3DDevice,
4683                                   LightIndex,
4684                                   (WINED3DLIGHT*) Light);
4685
4686     /* Translate the result. WineD3D returns other values than D3D7 */
4687     LeaveCriticalSection(&ddraw_cs);
4688     return hr_ddraw_from_wined3d(rc);
4689 }
4690
4691 /*****************************************************************************
4692  * IDirect3DDevice7::BeginStateBlock
4693  *
4694  * Begins recording to a stateblock
4695  *
4696  * Version 7
4697  *
4698  * Returns:
4699  *  D3D_OK on success
4700  *  For details see IWineD3DDevice::BeginStateBlock
4701  *
4702  *****************************************************************************/
4703 static HRESULT WINAPI
4704 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
4705 {
4706     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4707     HRESULT hr;
4708     TRACE("(%p)->(): Relay!\n", This);
4709
4710     EnterCriticalSection(&ddraw_cs);
4711     hr = IWineD3DDevice_BeginStateBlock(This->wineD3DDevice);
4712     LeaveCriticalSection(&ddraw_cs);
4713     return hr_ddraw_from_wined3d(hr);
4714 }
4715
4716 /*****************************************************************************
4717  * IDirect3DDevice7::EndStateBlock
4718  *
4719  * Stops recording to a state block and returns the created stateblock
4720  * handle.
4721  *
4722  * Version 7
4723  *
4724  * Params:
4725  *  BlockHandle: Address to store the stateblock's handle to
4726  *
4727  * Returns:
4728  *  D3D_OK on success
4729  *  DDERR_INVALIDPARAMS if BlockHandle is NULL
4730  *  See IWineD3DDevice::EndStateBlock for more details
4731  *
4732  *****************************************************************************/
4733 static HRESULT WINAPI
4734 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
4735                                     DWORD *BlockHandle)
4736 {
4737     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4738     HRESULT hr;
4739     TRACE("(%p)->(%p): Relay!\n", This, BlockHandle);
4740
4741     if(!BlockHandle)
4742     {
4743         WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
4744         return DDERR_INVALIDPARAMS;
4745     }
4746
4747     EnterCriticalSection(&ddraw_cs);
4748     *BlockHandle = IDirect3DDeviceImpl_CreateHandle(This);
4749     if(!*BlockHandle)
4750     {
4751         ERR("Cannot get a handle number for the stateblock\n");
4752         LeaveCriticalSection(&ddraw_cs);
4753         return DDERR_OUTOFMEMORY;
4754     }
4755     This->Handles[*BlockHandle - 1].type = DDrawHandle_StateBlock;
4756     hr = IWineD3DDevice_EndStateBlock(This->wineD3DDevice,
4757                                       (IWineD3DStateBlock **) &This->Handles[*BlockHandle - 1].ptr);
4758     LeaveCriticalSection(&ddraw_cs);
4759     return hr_ddraw_from_wined3d(hr);
4760 }
4761
4762 /*****************************************************************************
4763  * IDirect3DDevice7::PreLoad
4764  *
4765  * Allows the app to signal that a texture will be used soon, to allow
4766  * the Direct3DDevice to load it to the video card in the meantime.
4767  *
4768  * Version 7
4769  *
4770  * Params:
4771  *  Texture: The texture to preload
4772  *
4773  * Returns:
4774  *  D3D_OK on success
4775  *  DDERR_INVALIDPARAMS if Texture is NULL
4776  *  See IWineD3DSurface::PreLoad for details
4777  *
4778  *****************************************************************************/
4779 static HRESULT WINAPI
4780 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
4781                               IDirectDrawSurface7 *Texture)
4782 {
4783     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4784     IDirectDrawSurfaceImpl *surf = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, Texture);
4785
4786     TRACE("(%p)->(%p): Relay!\n", This, surf);
4787
4788     if(!Texture)
4789         return DDERR_INVALIDPARAMS;
4790
4791     EnterCriticalSection(&ddraw_cs);
4792     IWineD3DSurface_PreLoad(surf->WineD3DSurface);
4793     LeaveCriticalSection(&ddraw_cs);
4794     return D3D_OK;
4795 }
4796
4797 /*****************************************************************************
4798  * IDirect3DDevice7::ApplyStateBlock
4799  *
4800  * Activates the state stored in a state block handle.
4801  *
4802  * Params:
4803  *  BlockHandle: The stateblock handle to activate
4804  *
4805  * Returns:
4806  *  D3D_OK on success
4807  *  D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
4808  *
4809  *****************************************************************************/
4810 static HRESULT WINAPI
4811 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
4812                                       DWORD BlockHandle)
4813 {
4814     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4815     HRESULT hr;
4816     TRACE("(%p)->(%08x): Relay!\n", This, BlockHandle);
4817
4818     EnterCriticalSection(&ddraw_cs);
4819     if(!BlockHandle || BlockHandle > This->numHandles)
4820     {
4821         WARN("Out of range handle %d, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
4822         LeaveCriticalSection(&ddraw_cs);
4823         return D3DERR_INVALIDSTATEBLOCK;
4824     }
4825     if(This->Handles[BlockHandle - 1].type != DDrawHandle_StateBlock)
4826     {
4827         WARN("Handle %d is not a stateblock, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
4828         LeaveCriticalSection(&ddraw_cs);
4829         return D3DERR_INVALIDSTATEBLOCK;
4830     }
4831
4832     hr = IWineD3DStateBlock_Apply((IWineD3DStateBlock *) This->Handles[BlockHandle - 1].ptr);
4833     LeaveCriticalSection(&ddraw_cs);
4834     return hr_ddraw_from_wined3d(hr);
4835 }
4836
4837 /*****************************************************************************
4838  * IDirect3DDevice7::CaptureStateBlock
4839  *
4840  * Updates a stateblock's values to the values currently set for the device
4841  *
4842  * Version 7
4843  *
4844  * Params:
4845  *  BlockHandle: Stateblock to update
4846  *
4847  * Returns:
4848  *  D3D_OK on success
4849  *  D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
4850  *  See IWineD3DDevice::CaptureStateBlock for more details
4851  *
4852  *****************************************************************************/
4853 static HRESULT WINAPI
4854 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
4855                                         DWORD BlockHandle)
4856 {
4857     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4858     HRESULT hr;
4859     TRACE("(%p)->(%08x): Relay!\n", This, BlockHandle);
4860
4861     EnterCriticalSection(&ddraw_cs);
4862     if(BlockHandle == 0 || BlockHandle > This->numHandles)
4863     {
4864         WARN("Out of range handle %d, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
4865         LeaveCriticalSection(&ddraw_cs);
4866         return D3DERR_INVALIDSTATEBLOCK;
4867     }
4868     if(This->Handles[BlockHandle - 1].type != DDrawHandle_StateBlock)
4869     {
4870         WARN("Handle %d is not a stateblock, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
4871         LeaveCriticalSection(&ddraw_cs);
4872         return D3DERR_INVALIDSTATEBLOCK;
4873     }
4874
4875     hr = IWineD3DStateBlock_Capture((IWineD3DStateBlock *) This->Handles[BlockHandle - 1].ptr);
4876     LeaveCriticalSection(&ddraw_cs);
4877     return hr_ddraw_from_wined3d(hr);
4878 }
4879
4880 /*****************************************************************************
4881  * IDirect3DDevice7::DeleteStateBlock
4882  *
4883  * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
4884  *
4885  * Version 7
4886  *
4887  * Params:
4888  *  BlockHandle: Stateblock handle to delete
4889  *
4890  * Returns:
4891  *  D3D_OK on success
4892  *  D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
4893  *
4894  *****************************************************************************/
4895 static HRESULT WINAPI
4896 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
4897                                        DWORD BlockHandle)
4898 {
4899     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4900     ULONG ref;
4901     TRACE("(%p)->(%08x): Relay!\n", This, BlockHandle);
4902
4903     EnterCriticalSection(&ddraw_cs);
4904     if(BlockHandle == 0 || BlockHandle > This->numHandles)
4905     {
4906         WARN("Out of range handle %d, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
4907         LeaveCriticalSection(&ddraw_cs);
4908         return D3DERR_INVALIDSTATEBLOCK;
4909     }
4910     if(This->Handles[BlockHandle - 1].type != DDrawHandle_StateBlock)
4911     {
4912         WARN("Handle %d is not a stateblock, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
4913         LeaveCriticalSection(&ddraw_cs);
4914         return D3DERR_INVALIDSTATEBLOCK;
4915     }
4916
4917     ref = IWineD3DStateBlock_Release((IWineD3DStateBlock *) This->Handles[BlockHandle - 1].ptr);
4918     if(ref)
4919     {
4920         ERR("Something is still holding the stateblock %p(Handle %d). Ref = %d\n", This->Handles[BlockHandle - 1].ptr, BlockHandle, ref);
4921     }
4922     This->Handles[BlockHandle - 1].ptr = NULL;
4923     This->Handles[BlockHandle - 1].type = DDrawHandle_Unknown;
4924
4925     LeaveCriticalSection(&ddraw_cs);
4926     return D3D_OK;
4927 }
4928
4929 /*****************************************************************************
4930  * IDirect3DDevice7::CreateStateBlock
4931  *
4932  * Creates a new state block handle.
4933  *
4934  * Version 7
4935  *
4936  * Params:
4937  *  Type: The state block type
4938  *  BlockHandle: Address to write the created handle to
4939  *
4940  * Returns:
4941  *   D3D_OK on success
4942  *   DDERR_INVALIDPARAMS if BlockHandle is NULL
4943  *
4944  *****************************************************************************/
4945 static HRESULT WINAPI
4946 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
4947                                        D3DSTATEBLOCKTYPE Type,
4948                                        DWORD *BlockHandle)
4949 {
4950     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4951     HRESULT hr;
4952     TRACE("(%p)->(%08x,%p)!\n", This, Type, BlockHandle);
4953
4954     if(!BlockHandle)
4955     {
4956         WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
4957         return DDERR_INVALIDPARAMS;
4958     }
4959
4960     EnterCriticalSection(&ddraw_cs);
4961     *BlockHandle = IDirect3DDeviceImpl_CreateHandle(This);
4962     if(!*BlockHandle)
4963     {
4964         ERR("Cannot get a handle number for the stateblock\n");
4965         LeaveCriticalSection(&ddraw_cs);
4966         return DDERR_OUTOFMEMORY;
4967     }
4968     This->Handles[*BlockHandle - 1].type = DDrawHandle_StateBlock;
4969
4970     /* The D3DSTATEBLOCKTYPE enum is fine here */
4971     hr = IWineD3DDevice_CreateStateBlock(This->wineD3DDevice,
4972                                          Type,
4973                                          (IWineD3DStateBlock **) &This->Handles[*BlockHandle - 1].ptr,
4974                                          NULL /* Parent, hope that works */);
4975     LeaveCriticalSection(&ddraw_cs);
4976     return hr_ddraw_from_wined3d(hr);
4977 }
4978
4979 /*****************************************************************************
4980  * IDirect3DDevice7::Load
4981  *
4982  * Loads a rectangular area from the source into the destination texture.
4983  * It can also copy the source to the faces of a cubic environment map
4984  *
4985  * Version 7
4986  *
4987  * Params:
4988  *  DestTex: Destination texture
4989  *  DestPoint: Point in the destination where the source image should be
4990  *             written to
4991  *  SrcTex: Source texture
4992  *  SrcRect: Source rectangle
4993  *  Flags: Some flags
4994  *
4995  * Returns:
4996  *  D3D_OK on success
4997  *  DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL
4998  *  See IDirect3DTexture2::Load for details
4999  *
5000  *****************************************************************************/
5001 static HRESULT WINAPI
5002 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
5003                            IDirectDrawSurface7 *DestTex,
5004                            POINT *DestPoint,
5005                            IDirectDrawSurface7 *SrcTex,
5006                            RECT *SrcRect,
5007                            DWORD Flags)
5008 {
5009     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5010     IDirectDrawSurfaceImpl *dest = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, DestTex);
5011     IDirectDrawSurfaceImpl *src = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, SrcTex);
5012     FIXME("(%p)->(%p,%p,%p,%p,%08x): Partially Implemented!\n", This, dest, DestPoint, src, SrcRect, Flags);
5013
5014     if( (!src) || (!dest) )
5015         return DDERR_INVALIDPARAMS;
5016
5017     IDirect3DTexture2_Load(ICOM_INTERFACE(dest, IDirect3DTexture2),
5018                            ICOM_INTERFACE(src, IDirect3DTexture2));
5019     return D3D_OK;
5020 }
5021
5022 /*****************************************************************************
5023  * IDirect3DDevice7::LightEnable
5024  *
5025  * Enables or disables a light
5026  *
5027  * Version 7, IDirect3DLight uses this method too.
5028  *
5029  * Params:
5030  *  LightIndex: The index of the light to enable / disable
5031  *  Enable: Enable or disable the light
5032  *
5033  * Returns:
5034  *  D3D_OK on success
5035  *  For more details, see IWineD3DDevice::SetLightEnable
5036  *
5037  *****************************************************************************/
5038 static HRESULT WINAPI
5039 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
5040                                   DWORD LightIndex,
5041                                   BOOL Enable)
5042 {
5043     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5044     HRESULT hr;
5045     TRACE("(%p)->(%08x,%d): Relay!\n", This, LightIndex, Enable);
5046
5047     EnterCriticalSection(&ddraw_cs);
5048     hr = IWineD3DDevice_SetLightEnable(This->wineD3DDevice, LightIndex, Enable);
5049     LeaveCriticalSection(&ddraw_cs);
5050     return hr_ddraw_from_wined3d(hr);
5051 }
5052
5053 /*****************************************************************************
5054  * IDirect3DDevice7::GetLightEnable
5055  *
5056  * Retrieves if the light with the given index is enabled or not
5057  *
5058  * Version 7
5059  *
5060  * Params:
5061  *  LightIndex: Index of desired light
5062  *  Enable: Pointer to a BOOL which contains the result
5063  *
5064  * Returns:
5065  *  D3D_OK on success
5066  *  DDERR_INVALIDPARAMS if Enable is NULL
5067  *  See IWineD3DDevice::GetLightEnable for more details
5068  *
5069  *****************************************************************************/
5070 static HRESULT WINAPI
5071 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
5072                                      DWORD LightIndex,
5073                                      BOOL* Enable)
5074 {
5075     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5076     HRESULT hr;
5077     TRACE("(%p)->(%08x,%p): Relay\n", This, LightIndex, Enable);
5078
5079     if(!Enable)
5080         return DDERR_INVALIDPARAMS;
5081
5082     EnterCriticalSection(&ddraw_cs);
5083     hr = IWineD3DDevice_GetLightEnable(This->wineD3DDevice, LightIndex, Enable);
5084     LeaveCriticalSection(&ddraw_cs);
5085     return hr_ddraw_from_wined3d(hr);
5086 }
5087
5088 /*****************************************************************************
5089  * IDirect3DDevice7::SetClipPlane
5090  *
5091  * Sets custom clipping plane
5092  *
5093  * Version 7
5094  *
5095  * Params:
5096  *  Index: The index of the clipping plane
5097  *  PlaneEquation: An equation defining the clipping plane
5098  *
5099  * Returns:
5100  *  D3D_OK on success
5101  *  DDERR_INVALIDPARAMS if PlaneEquation is NULL
5102  *  See IWineD3DDevice::SetClipPlane for more details
5103  *
5104  *****************************************************************************/
5105 static HRESULT WINAPI
5106 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
5107                                    DWORD Index,
5108                                    D3DVALUE* PlaneEquation)
5109 {
5110     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5111     HRESULT hr;
5112     TRACE("(%p)->(%08x,%p): Relay!\n", This, Index, PlaneEquation);
5113
5114     if(!PlaneEquation)
5115         return DDERR_INVALIDPARAMS;
5116
5117     EnterCriticalSection(&ddraw_cs);
5118     hr = IWineD3DDevice_SetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
5119     LeaveCriticalSection(&ddraw_cs);
5120     return hr;
5121 }
5122
5123 /*****************************************************************************
5124  * IDirect3DDevice7::GetClipPlane
5125  *
5126  * Returns the clipping plane with a specific index
5127  *
5128  * Params:
5129  *  Index: The index of the desired plane
5130  *  PlaneEquation: Address to store the plane equation to
5131  *
5132  * Returns:
5133  *  D3D_OK on success
5134  *  DDERR_INVALIDPARAMS if PlaneEquation is NULL
5135  *  See IWineD3DDevice::GetClipPlane for more details
5136  *
5137  *****************************************************************************/
5138 static HRESULT WINAPI
5139 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
5140                                    DWORD Index,
5141                                    D3DVALUE* PlaneEquation)
5142 {
5143     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5144     HRESULT hr;
5145     TRACE("(%p)->(%d,%p): Relay!\n", This, Index, PlaneEquation);
5146
5147     if(!PlaneEquation)
5148         return DDERR_INVALIDPARAMS;
5149
5150     EnterCriticalSection(&ddraw_cs);
5151     hr = IWineD3DDevice_GetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
5152     LeaveCriticalSection(&ddraw_cs);
5153     return hr;
5154 }
5155
5156 /*****************************************************************************
5157  * IDirect3DDevice7::GetInfo
5158  *
5159  * Retrieves some information about the device. The DirectX sdk says that
5160  * this version returns S_FALSE for all retail builds of DirectX, that's what
5161  * this implementation does.
5162  *
5163  * Params:
5164  *  DevInfoID: Information type requested
5165  *  DevInfoStruct: Pointer to a structure to store the info to
5166  *  Size: Size of the structure
5167  *
5168  * Returns:
5169  *  S_FALSE, because it's a non-debug driver
5170  *
5171  *****************************************************************************/
5172 static HRESULT WINAPI
5173 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
5174                               DWORD DevInfoID,
5175                               void *DevInfoStruct,
5176                               DWORD Size)
5177 {
5178     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5179     TRACE("(%p)->(%08x,%p,%08x)\n", This, DevInfoID, DevInfoStruct, Size);
5180
5181     if (TRACE_ON(d3d7))
5182     {
5183         TRACE(" info requested : ");
5184         switch (DevInfoID)
5185         {
5186             case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
5187             case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
5188             case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
5189             default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
5190         }
5191     }
5192
5193     return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
5194 }
5195
5196 const IDirect3DDevice7Vtbl IDirect3DDevice7_Vtbl =
5197 {
5198     /*** IUnknown Methods ***/
5199     IDirect3DDeviceImpl_7_QueryInterface,
5200     IDirect3DDeviceImpl_7_AddRef,
5201     IDirect3DDeviceImpl_7_Release,
5202     /*** IDirect3DDevice7 ***/
5203     IDirect3DDeviceImpl_7_GetCaps,
5204     IDirect3DDeviceImpl_7_EnumTextureFormats,
5205     IDirect3DDeviceImpl_7_BeginScene,
5206     IDirect3DDeviceImpl_7_EndScene,
5207     IDirect3DDeviceImpl_7_GetDirect3D,
5208     IDirect3DDeviceImpl_7_SetRenderTarget,
5209     IDirect3DDeviceImpl_7_GetRenderTarget,
5210     IDirect3DDeviceImpl_7_Clear,
5211     IDirect3DDeviceImpl_7_SetTransform,
5212     IDirect3DDeviceImpl_7_GetTransform,
5213     IDirect3DDeviceImpl_7_SetViewport,
5214     IDirect3DDeviceImpl_7_MultiplyTransform,
5215     IDirect3DDeviceImpl_7_GetViewport,
5216     IDirect3DDeviceImpl_7_SetMaterial,
5217     IDirect3DDeviceImpl_7_GetMaterial,
5218     IDirect3DDeviceImpl_7_SetLight,
5219     IDirect3DDeviceImpl_7_GetLight,
5220     IDirect3DDeviceImpl_7_SetRenderState,
5221     IDirect3DDeviceImpl_7_GetRenderState,
5222     IDirect3DDeviceImpl_7_BeginStateBlock,
5223     IDirect3DDeviceImpl_7_EndStateBlock,
5224     IDirect3DDeviceImpl_7_PreLoad,
5225     IDirect3DDeviceImpl_7_DrawPrimitive,
5226     IDirect3DDeviceImpl_7_DrawIndexedPrimitive,
5227     IDirect3DDeviceImpl_7_SetClipStatus,
5228     IDirect3DDeviceImpl_7_GetClipStatus,
5229     IDirect3DDeviceImpl_7_DrawPrimitiveStrided,
5230     IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided,
5231     IDirect3DDeviceImpl_7_DrawPrimitiveVB,
5232     IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB,
5233     IDirect3DDeviceImpl_7_ComputeSphereVisibility,
5234     IDirect3DDeviceImpl_7_GetTexture,
5235     IDirect3DDeviceImpl_7_SetTexture,
5236     IDirect3DDeviceImpl_7_GetTextureStageState,
5237     IDirect3DDeviceImpl_7_SetTextureStageState,
5238     IDirect3DDeviceImpl_7_ValidateDevice,
5239     IDirect3DDeviceImpl_7_ApplyStateBlock,
5240     IDirect3DDeviceImpl_7_CaptureStateBlock,
5241     IDirect3DDeviceImpl_7_DeleteStateBlock,
5242     IDirect3DDeviceImpl_7_CreateStateBlock,
5243     IDirect3DDeviceImpl_7_Load,
5244     IDirect3DDeviceImpl_7_LightEnable,
5245     IDirect3DDeviceImpl_7_GetLightEnable,
5246     IDirect3DDeviceImpl_7_SetClipPlane,
5247     IDirect3DDeviceImpl_7_GetClipPlane,
5248     IDirect3DDeviceImpl_7_GetInfo
5249 };
5250
5251 const IDirect3DDevice3Vtbl IDirect3DDevice3_Vtbl =
5252 {
5253     /*** IUnknown Methods ***/
5254     Thunk_IDirect3DDeviceImpl_3_QueryInterface,
5255     Thunk_IDirect3DDeviceImpl_3_AddRef,
5256     Thunk_IDirect3DDeviceImpl_3_Release,
5257     /*** IDirect3DDevice3 ***/
5258     IDirect3DDeviceImpl_3_GetCaps,
5259     IDirect3DDeviceImpl_3_GetStats,
5260     IDirect3DDeviceImpl_3_AddViewport,
5261     IDirect3DDeviceImpl_3_DeleteViewport,
5262     IDirect3DDeviceImpl_3_NextViewport,
5263     Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
5264     Thunk_IDirect3DDeviceImpl_3_BeginScene,
5265     Thunk_IDirect3DDeviceImpl_3_EndScene,
5266     Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
5267     IDirect3DDeviceImpl_3_SetCurrentViewport,
5268     IDirect3DDeviceImpl_3_GetCurrentViewport,
5269     Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
5270     Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
5271     IDirect3DDeviceImpl_3_Begin,
5272     IDirect3DDeviceImpl_3_BeginIndexed,
5273     IDirect3DDeviceImpl_3_Vertex,
5274     IDirect3DDeviceImpl_3_Index,
5275     IDirect3DDeviceImpl_3_End,
5276     Thunk_IDirect3DDeviceImpl_3_GetRenderState,
5277     Thunk_IDirect3DDeviceImpl_3_SetRenderState,
5278     IDirect3DDeviceImpl_3_GetLightState,
5279     IDirect3DDeviceImpl_3_SetLightState,
5280     Thunk_IDirect3DDeviceImpl_3_SetTransform,
5281     Thunk_IDirect3DDeviceImpl_3_GetTransform,
5282     Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
5283     Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
5284     Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
5285     Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
5286     Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
5287     Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
5288     Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
5289     Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
5290     Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
5291     Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
5292     Thunk_IDirect3DDeviceImpl_3_GetTexture,
5293     Thunk_IDirect3DDeviceImpl_3_SetTexture,
5294     Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
5295     Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
5296     Thunk_IDirect3DDeviceImpl_3_ValidateDevice
5297 };
5298
5299 const IDirect3DDevice2Vtbl IDirect3DDevice2_Vtbl =
5300 {
5301     /*** IUnknown Methods ***/
5302     Thunk_IDirect3DDeviceImpl_2_QueryInterface,
5303     Thunk_IDirect3DDeviceImpl_2_AddRef,
5304     Thunk_IDirect3DDeviceImpl_2_Release,
5305     /*** IDirect3DDevice2 ***/
5306     Thunk_IDirect3DDeviceImpl_2_GetCaps,
5307     IDirect3DDeviceImpl_2_SwapTextureHandles,
5308     Thunk_IDirect3DDeviceImpl_2_GetStats,
5309     Thunk_IDirect3DDeviceImpl_2_AddViewport,
5310     Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
5311     Thunk_IDirect3DDeviceImpl_2_NextViewport,
5312     IDirect3DDeviceImpl_2_EnumTextureFormats,
5313     Thunk_IDirect3DDeviceImpl_2_BeginScene,
5314     Thunk_IDirect3DDeviceImpl_2_EndScene,
5315     Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
5316     Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
5317     Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
5318     Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
5319     Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
5320     Thunk_IDirect3DDeviceImpl_2_Begin,
5321     Thunk_IDirect3DDeviceImpl_2_BeginIndexed,
5322     Thunk_IDirect3DDeviceImpl_2_Vertex,
5323     Thunk_IDirect3DDeviceImpl_2_Index,
5324     Thunk_IDirect3DDeviceImpl_2_End,
5325     Thunk_IDirect3DDeviceImpl_2_GetRenderState,
5326     Thunk_IDirect3DDeviceImpl_2_SetRenderState,
5327     Thunk_IDirect3DDeviceImpl_2_GetLightState,
5328     Thunk_IDirect3DDeviceImpl_2_SetLightState,
5329     Thunk_IDirect3DDeviceImpl_2_SetTransform,
5330     Thunk_IDirect3DDeviceImpl_2_GetTransform,
5331     Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
5332     Thunk_IDirect3DDeviceImpl_2_DrawPrimitive,
5333     Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
5334     Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
5335     Thunk_IDirect3DDeviceImpl_2_GetClipStatus
5336 };
5337
5338 const IDirect3DDeviceVtbl IDirect3DDevice1_Vtbl =
5339 {
5340     /*** IUnknown Methods ***/
5341     Thunk_IDirect3DDeviceImpl_1_QueryInterface,
5342     Thunk_IDirect3DDeviceImpl_1_AddRef,
5343     Thunk_IDirect3DDeviceImpl_1_Release,
5344     /*** IDirect3DDevice1 ***/
5345     IDirect3DDeviceImpl_1_Initialize,
5346     Thunk_IDirect3DDeviceImpl_1_GetCaps,
5347     Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
5348     IDirect3DDeviceImpl_1_CreateExecuteBuffer,
5349     Thunk_IDirect3DDeviceImpl_1_GetStats,
5350     IDirect3DDeviceImpl_1_Execute,
5351     Thunk_IDirect3DDeviceImpl_1_AddViewport,
5352     Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
5353     Thunk_IDirect3DDeviceImpl_1_NextViewport,
5354     IDirect3DDeviceImpl_1_Pick,
5355     IDirect3DDeviceImpl_1_GetPickRecords,
5356     Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
5357     IDirect3DDeviceImpl_1_CreateMatrix,
5358     IDirect3DDeviceImpl_1_SetMatrix,
5359     IDirect3DDeviceImpl_1_GetMatrix,
5360     IDirect3DDeviceImpl_1_DeleteMatrix,
5361     Thunk_IDirect3DDeviceImpl_1_EndScene,
5362     Thunk_IDirect3DDeviceImpl_1_BeginScene,
5363     Thunk_IDirect3DDeviceImpl_1_GetDirect3D
5364 };
5365
5366 /*****************************************************************************
5367  * IDirect3DDeviceImpl_CreateHandle
5368  *
5369  * Not called from the VTable
5370  *
5371  * Some older interface versions operate with handles, which are basically
5372  * DWORDs which identify an interface, for example
5373  * IDirect3DDevice::SetRenderState with DIRECT3DRENDERSTATE_TEXTUREHANDLE
5374  *
5375  * Those handle could be just casts to the interface pointers or vice versa,
5376  * but that is not 64 bit safe and would mean blindly derefering a DWORD
5377  * passed by the app. Instead there is a dynamic array in the device which
5378  * keeps a DWORD to pointer information and a type for the handle.
5379  *
5380  * Basically this array only grows, when a handle is freed its pointer is
5381  * just set to NULL. There will be much more reads from the array than
5382  * insertion operations, so a dynamic array is fine.
5383  *
5384  * Params:
5385  *  This: D3DDevice implementation for which this handle should be created
5386  *
5387  * Returns:
5388  *  A free handle on success
5389  *  0 on failure
5390  *
5391  *****************************************************************************/
5392 DWORD
5393 IDirect3DDeviceImpl_CreateHandle(IDirect3DDeviceImpl *This)
5394 {
5395     DWORD i;
5396     struct HandleEntry *oldHandles = This->Handles;
5397
5398     TRACE("(%p)\n", This);
5399
5400     for(i = 0; i < This->numHandles; i++)
5401     {
5402         if(This->Handles[i].ptr == NULL &&
5403            This->Handles[i].type == DDrawHandle_Unknown)
5404         {
5405             TRACE("Reusing freed handle %d\n", i + 1);
5406             return i + 1;
5407         }
5408     }
5409
5410     TRACE("Growing the handle array\n");
5411
5412     This->numHandles++;
5413     This->Handles = HeapAlloc(GetProcessHeap(), 0, sizeof(struct HandleEntry) * This->numHandles);
5414     if(!This->Handles)
5415     {
5416         ERR("Out of memory\n");
5417         This->Handles = oldHandles;
5418         This->numHandles--;
5419         return 0;
5420     }
5421     if(oldHandles)
5422     {
5423         memcpy(This->Handles, oldHandles, (This->numHandles - 1) * sizeof(struct HandleEntry));
5424         HeapFree(GetProcessHeap(), 0, oldHandles);
5425     }
5426
5427     TRACE("Returning %d\n", This->numHandles);
5428     return This->numHandles;
5429 }
5430
5431 /*****************************************************************************
5432  * IDirect3DDeviceImpl_UpdateDepthStencil
5433  *
5434  * Checks the current render target for attached depth stencils and sets the
5435  * WineD3D depth stencil accordingly.
5436  *
5437  * Returns:
5438  *  The depth stencil state to set if creating the device
5439  *
5440  *****************************************************************************/
5441 WINED3DZBUFFERTYPE
5442 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
5443 {
5444     IDirectDrawSurface7 *depthStencil = NULL;
5445     IDirectDrawSurfaceImpl *dsi;
5446     static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
5447
5448     IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(This->target, IDirectDrawSurface7),
5449                                            &depthcaps,
5450                                            &depthStencil);
5451     if(!depthStencil)
5452     {
5453         TRACE("Setting wined3d depth stencil to NULL\n");
5454         IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
5455                                               NULL);
5456         return WINED3DZB_FALSE;
5457     }
5458
5459     dsi = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, depthStencil);
5460     TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->WineD3DSurface);
5461     IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
5462                                           dsi->WineD3DSurface);
5463
5464     IDirectDrawSurface7_Release(depthStencil);
5465     return WINED3DZB_TRUE;
5466 }