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