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