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