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