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