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