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