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