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