winex11: When a mask picture is active, the source offsets should be relative to...
[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 == (tex_alpha ? WINED3DTOP_SELECTARG1 : WINED3DTOP_SELECTARG2) &&
2584                       alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2585                 {
2586                     ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2587                 }
2588
2589                 *lpdwRenderState = D3DTBLEND_MODULATE;
2590             }
2591
2592             LeaveCriticalSection(&ddraw_cs);
2593
2594             return D3D_OK;
2595         }
2596
2597         default:
2598             return IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, dwRenderStateType, lpdwRenderState);
2599     }
2600 }
2601
2602 static HRESULT WINAPI
2603 Thunk_IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2604                                            D3DRENDERSTATETYPE dwRenderStateType,
2605                                            DWORD *lpdwRenderState)
2606 {
2607     IDirect3DDeviceImpl *This = device_from_device2(iface);
2608     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice3 interface.\n", This, dwRenderStateType, lpdwRenderState);
2609     return IDirect3DDevice3_GetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2610             dwRenderStateType, lpdwRenderState);
2611 }
2612
2613 /*****************************************************************************
2614  * IDirect3DDevice7::SetRenderState
2615  *
2616  * Sets a render state. The possible render states are defined in
2617  * include/d3dtypes.h
2618  *
2619  * Version 2, 3 and 7
2620  *
2621  * Params:
2622  *  RenderStateType: State to set
2623  *  Value: Value to assign to that state
2624  *
2625  * Returns:
2626  *  D3D_OK on success,
2627  *  for details see IWineD3DDevice::SetRenderState
2628  *
2629  *****************************************************************************/
2630 static HRESULT
2631 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2632                                      D3DRENDERSTATETYPE RenderStateType,
2633                                      DWORD Value)
2634 {
2635     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2636     HRESULT hr;
2637     TRACE("(%p)->(%08x,%d): Relay\n", This, RenderStateType, Value);
2638
2639     EnterCriticalSection(&ddraw_cs);
2640     /* Some render states need special care */
2641     switch(RenderStateType)
2642     {
2643         case D3DRENDERSTATE_TEXTUREMAG:
2644         {
2645             WINED3DTEXTUREFILTERTYPE tex_mag = WINED3DTEXF_POINT;
2646
2647             switch ((D3DTEXTUREFILTER) Value)
2648             {
2649                 case D3DFILTER_NEAREST:
2650                 case D3DFILTER_LINEARMIPNEAREST:
2651                     tex_mag = WINED3DTEXF_POINT;
2652                     break;
2653                 case D3DFILTER_LINEAR:
2654                 case D3DFILTER_LINEARMIPLINEAR:
2655                     tex_mag = WINED3DTEXF_LINEAR;
2656                     break;
2657                 default:
2658                     ERR("Unhandled texture mag %d !\n",Value);
2659             }
2660
2661             hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2662                                                 0, WINED3DSAMP_MAGFILTER,
2663                                                 tex_mag);
2664             break;
2665         }
2666
2667         case D3DRENDERSTATE_TEXTUREMIN:
2668         {
2669             WINED3DTEXTUREFILTERTYPE tex_min = WINED3DTEXF_POINT;
2670             WINED3DTEXTUREFILTERTYPE tex_mip = WINED3DTEXF_NONE;
2671
2672             switch ((D3DTEXTUREFILTER) Value)
2673             {
2674                 case D3DFILTER_NEAREST:
2675                     tex_min = WINED3DTEXF_POINT;
2676                     break;
2677                 case D3DFILTER_LINEAR:
2678                     tex_min = WINED3DTEXF_LINEAR;
2679                     break;
2680                 case D3DFILTER_MIPNEAREST:
2681                     tex_min = WINED3DTEXF_POINT;
2682                     tex_mip = WINED3DTEXF_POINT;
2683                     break;
2684                 case D3DFILTER_MIPLINEAR:
2685                     tex_min = WINED3DTEXF_POINT;
2686                     tex_mip = WINED3DTEXF_LINEAR;
2687                     break;
2688                 case D3DFILTER_LINEARMIPNEAREST:
2689                     tex_min = WINED3DTEXF_POINT;
2690                     tex_mip = WINED3DTEXF_LINEAR;
2691                     break;
2692                 case D3DFILTER_LINEARMIPLINEAR:
2693                     tex_min = WINED3DTEXF_LINEAR;
2694                     tex_mip = WINED3DTEXF_LINEAR;
2695                     break;
2696
2697                 default:
2698                     ERR("Unhandled texture min %d !\n",Value);
2699             }
2700
2701                    IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2702                                                   0, WINED3DSAMP_MIPFILTER,
2703                                                   tex_mip);
2704             hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2705                                                 0, WINED3DSAMP_MINFILTER,
2706                                                 tex_min);
2707             break;
2708         }
2709
2710         case D3DRENDERSTATE_TEXTUREADDRESS:
2711                    IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2712                                                   0, WINED3DSAMP_ADDRESSV,
2713                                                   Value);
2714             /* Drop through */
2715         case D3DRENDERSTATE_TEXTUREADDRESSU:
2716             hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2717                                                 0, WINED3DSAMP_ADDRESSU,
2718                                                 Value);
2719             break;
2720         case D3DRENDERSTATE_TEXTUREADDRESSV:
2721             hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2722                                                 0, WINED3DSAMP_ADDRESSV,
2723                                                 Value);
2724             break;
2725
2726         default:
2727
2728             /* FIXME: Unhandled: D3DRENDERSTATE_STIPPLEPATTERN00 - 31 */
2729
2730             hr = IWineD3DDevice_SetRenderState(This->wineD3DDevice,
2731                                                RenderStateType,
2732                                                Value);
2733             break;
2734     }
2735     LeaveCriticalSection(&ddraw_cs);
2736     return hr;
2737 }
2738
2739 static HRESULT WINAPI
2740 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2741                                      D3DRENDERSTATETYPE RenderStateType,
2742                                      DWORD Value)
2743 {
2744     return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2745 }
2746
2747 static HRESULT WINAPI
2748 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2749                                      D3DRENDERSTATETYPE RenderStateType,
2750                                      DWORD Value)
2751 {
2752     HRESULT hr;
2753     WORD old_fpucw;
2754
2755     old_fpucw = d3d_fpu_setup();
2756     hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2757     set_fpu_control_word(old_fpucw);
2758
2759     return hr;
2760 }
2761
2762 static HRESULT WINAPI
2763 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2764                                      D3DRENDERSTATETYPE RenderStateType,
2765                                      DWORD Value)
2766 {
2767     /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2768     for this state can be directly mapped to texture stage colorop and alphaop, but
2769     D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2770     from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2771     alphaarg when needed.
2772
2773     Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2774
2775     Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2776     TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2777     are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2778     requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2779     with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2780     in device - TRUE if the app is using TEXTUREMAPBLEND.
2781
2782     Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2783     GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2784     unless some broken game will be found that cares. */
2785
2786     HRESULT hr;
2787     IDirect3DDeviceImpl *This = device_from_device3(iface);
2788     TRACE("(%p)->(%08x,%d)\n", This, RenderStateType, Value);
2789
2790     EnterCriticalSection(&ddraw_cs);
2791
2792     switch(RenderStateType)
2793     {
2794         case D3DRENDERSTATE_TEXTUREHANDLE:
2795         {
2796             if(Value == 0)
2797             {
2798                 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
2799                                                0,
2800                                                NULL);
2801                 break;
2802             }
2803
2804             if(Value > This->numHandles)
2805             {
2806                 FIXME("Specified handle %d out of range\n", Value);
2807                 hr = DDERR_INVALIDPARAMS;
2808                 break;
2809             }
2810             if(This->Handles[Value - 1].type != DDrawHandle_Texture)
2811             {
2812                 FIXME("Handle %d isn't a texture handle\n", Value);
2813                 hr = DDERR_INVALIDPARAMS;
2814                 break;
2815             }
2816             else
2817             {
2818                 IDirectDrawSurfaceImpl *surf = This->Handles[Value - 1].ptr;
2819                 IDirect3DTexture2 *tex = surf ? (IDirect3DTexture2 *)&surf->IDirect3DTexture2_vtbl : NULL;
2820                 hr = IDirect3DDevice3_SetTexture(iface, 0, tex);
2821                 break;
2822             }
2823         }
2824
2825         case D3DRENDERSTATE_TEXTUREMAPBLEND:
2826         {
2827             This->legacyTextureBlending = TRUE;
2828
2829             switch ( (D3DTEXTUREBLEND) Value)
2830             {
2831                 case D3DTBLEND_MODULATE:
2832                 {
2833                     BOOL tex_alpha = FALSE;
2834                     IWineD3DBaseTexture *tex = NULL;
2835                     WINED3DSURFACE_DESC desc;
2836                     DDPIXELFORMAT ddfmt;
2837
2838                     hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2839                                                 0,
2840                                                 &tex);
2841
2842                     if(hr == WINED3D_OK && tex)
2843                     {
2844                         memset(&desc, 0, sizeof(desc));
2845                         hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2846                         if (SUCCEEDED(hr))
2847                         {
2848                             ddfmt.dwSize = sizeof(ddfmt);
2849                             PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2850                             if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2851                         }
2852
2853                         IWineD3DBaseTexture_Release(tex);
2854                     }
2855
2856                     if (tex_alpha)
2857                         IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2858                     else
2859                         IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2860                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2861                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2862                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2863                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2864                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2865
2866                     break;
2867                 }
2868
2869                 case D3DTBLEND_ADD:
2870                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2871                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2872                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2873                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2874                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2875                     break;
2876
2877                 case D3DTBLEND_MODULATEALPHA:
2878                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2879                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2880                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2881                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2882                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2883                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2884                     break;
2885
2886                 case D3DTBLEND_COPY:
2887                 case D3DTBLEND_DECAL:
2888                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2889                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2890                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2891                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2892                     break;
2893
2894                 case D3DTBLEND_DECALALPHA:
2895                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2896                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2897                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2898                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2899                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2900                     break;
2901
2902                 default:
2903                     ERR("Unhandled texture environment %d !\n",Value);
2904             }
2905
2906             hr = D3D_OK;
2907             break;
2908         }
2909
2910         default:
2911             hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, RenderStateType, Value);
2912             break;
2913     }
2914
2915     LeaveCriticalSection(&ddraw_cs);
2916
2917     return hr;
2918 }
2919
2920 static HRESULT WINAPI
2921 Thunk_IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2922                                            D3DRENDERSTATETYPE RenderStateType,
2923                                            DWORD Value)
2924 {
2925     IDirect3DDeviceImpl *This = device_from_device2(iface);
2926     TRACE_(ddraw_thunk)("(%p)->(%08x,%d) thunking to IDirect3DDevice3 interface.\n", This, RenderStateType, Value);
2927     return IDirect3DDevice3_SetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, RenderStateType, Value);
2928 }
2929
2930 /*****************************************************************************
2931  * Direct3DDevice3::SetLightState
2932  *
2933  * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2934  * light states are forwarded to Direct3DDevice7 render states
2935  *
2936  * Version 2 and 3
2937  *
2938  * Params:
2939  *  LightStateType: The light state to change
2940  *  Value: The value to assign to that light state
2941  *
2942  * Returns:
2943  *  D3D_OK on success
2944  *  DDERR_INVALIDPARAMS if the parameters were incorrect
2945  *  Also check IDirect3DDevice7::SetRenderState
2946  *
2947  *****************************************************************************/
2948 static HRESULT WINAPI
2949 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
2950                                     D3DLIGHTSTATETYPE LightStateType,
2951                                     DWORD Value)
2952 {
2953     IDirect3DDeviceImpl *This = device_from_device3(iface);
2954     HRESULT hr;
2955
2956     TRACE("(%p)->(%08x,%08x)\n", This, LightStateType, Value);
2957
2958     if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2959     {
2960         TRACE("Unexpected Light State Type\n");
2961         return DDERR_INVALIDPARAMS;
2962     }
2963
2964     EnterCriticalSection(&ddraw_cs);
2965     if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
2966     {
2967         IDirect3DMaterialImpl *mat;
2968
2969         if(Value == 0) mat = NULL;
2970         else if(Value > This->numHandles)
2971         {
2972             ERR("Material handle out of range(%d)\n", Value);
2973             LeaveCriticalSection(&ddraw_cs);
2974             return DDERR_INVALIDPARAMS;
2975         }
2976         else if(This->Handles[Value - 1].type != DDrawHandle_Material)
2977         {
2978             ERR("Invalid handle %d\n", Value);
2979             LeaveCriticalSection(&ddraw_cs);
2980             return DDERR_INVALIDPARAMS;
2981         }
2982         else
2983         {
2984             mat = This->Handles[Value - 1].ptr;
2985         }
2986
2987         if (mat != NULL)
2988         {
2989             TRACE(" activating material %p.\n", mat);
2990             mat->activate(mat);
2991         }
2992         else
2993         {
2994             FIXME(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
2995         }
2996         This->material = Value;
2997     }
2998     else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
2999     {
3000         switch (Value)
3001         {
3002             case D3DCOLOR_MONO:
3003                 ERR("DDCOLOR_MONO should not happen!\n");
3004                 break;
3005             case D3DCOLOR_RGB:
3006                 /* We are already in this mode */
3007                 TRACE("Setting color model to RGB (no-op).\n");
3008                 break;
3009             default:
3010                 ERR("Unknown color model!\n");
3011                 LeaveCriticalSection(&ddraw_cs);
3012                 return DDERR_INVALIDPARAMS;
3013         }
3014     }
3015     else
3016     {
3017         D3DRENDERSTATETYPE rs;
3018         switch (LightStateType)
3019         {
3020             case D3DLIGHTSTATE_AMBIENT:       /* 2 */
3021                 rs = D3DRENDERSTATE_AMBIENT;
3022                 break;          
3023             case D3DLIGHTSTATE_FOGMODE:       /* 4 */
3024                 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3025                 break;
3026             case D3DLIGHTSTATE_FOGSTART:      /* 5 */
3027                 rs = D3DRENDERSTATE_FOGSTART;
3028                 break;
3029             case D3DLIGHTSTATE_FOGEND:        /* 6 */
3030                 rs = D3DRENDERSTATE_FOGEND;
3031                 break;
3032             case D3DLIGHTSTATE_FOGDENSITY:    /* 7 */
3033                 rs = D3DRENDERSTATE_FOGDENSITY;
3034                 break;
3035             case D3DLIGHTSTATE_COLORVERTEX:   /* 8 */
3036                 rs = D3DRENDERSTATE_COLORVERTEX;
3037                 break;
3038             default:
3039                 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3040                 LeaveCriticalSection(&ddraw_cs);
3041                 return DDERR_INVALIDPARAMS;
3042         }
3043
3044         hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, rs, Value);
3045         LeaveCriticalSection(&ddraw_cs);
3046         return hr;
3047     }
3048
3049     LeaveCriticalSection(&ddraw_cs);
3050     return D3D_OK;
3051 }
3052
3053 static HRESULT WINAPI
3054 Thunk_IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3055                                           D3DLIGHTSTATETYPE LightStateType,
3056                                           DWORD Value)
3057 {
3058     IDirect3DDeviceImpl *This = device_from_device2(iface);
3059     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x) thunking to IDirect3DDevice3 interface.\n", This, LightStateType, Value);
3060     return IDirect3DDevice3_SetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3061 }
3062
3063 /*****************************************************************************
3064  * IDirect3DDevice3::GetLightState
3065  *
3066  * Returns the current setting of a light state. The state is read from
3067  * the Direct3DDevice7 render state.
3068  *
3069  * Version 2 and 3
3070  *
3071  * Params:
3072  *  LightStateType: The light state to return
3073  *  Value: The address to store the light state setting at
3074  *
3075  * Returns:
3076  *  D3D_OK on success
3077  *  DDDERR_INVALIDPARAMS if the parameters were incorrect
3078  *  Also see IDirect3DDevice7::GetRenderState
3079  *
3080  *****************************************************************************/
3081 static HRESULT WINAPI
3082 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3083                                     D3DLIGHTSTATETYPE LightStateType,
3084                                     DWORD *Value)
3085 {
3086     IDirect3DDeviceImpl *This = device_from_device3(iface);
3087     HRESULT hr;
3088
3089     TRACE("(%p)->(%08x,%p)\n", This, LightStateType, Value);
3090
3091     if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3092     {
3093         TRACE("Unexpected Light State Type\n");
3094         return DDERR_INVALIDPARAMS;
3095     }
3096
3097     if(!Value)
3098         return DDERR_INVALIDPARAMS;
3099
3100     EnterCriticalSection(&ddraw_cs);
3101     if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3102     {
3103         *Value = This->material;
3104     }
3105     else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3106     {
3107         *Value = D3DCOLOR_RGB;
3108     }
3109     else
3110     {
3111         D3DRENDERSTATETYPE rs;
3112         switch (LightStateType)
3113         {
3114             case D3DLIGHTSTATE_AMBIENT:       /* 2 */
3115                 rs = D3DRENDERSTATE_AMBIENT;
3116                 break;          
3117             case D3DLIGHTSTATE_FOGMODE:       /* 4 */
3118                 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3119                 break;
3120             case D3DLIGHTSTATE_FOGSTART:      /* 5 */
3121                 rs = D3DRENDERSTATE_FOGSTART;
3122                 break;
3123             case D3DLIGHTSTATE_FOGEND:        /* 6 */
3124                 rs = D3DRENDERSTATE_FOGEND;
3125                 break;
3126             case D3DLIGHTSTATE_FOGDENSITY:    /* 7 */
3127                 rs = D3DRENDERSTATE_FOGDENSITY;
3128                 break;
3129             case D3DLIGHTSTATE_COLORVERTEX:   /* 8 */
3130                 rs = D3DRENDERSTATE_COLORVERTEX;
3131                 break;
3132             default:
3133                 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3134                 LeaveCriticalSection(&ddraw_cs);
3135                 return DDERR_INVALIDPARAMS;
3136         }
3137
3138         hr = IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, rs, Value);
3139         LeaveCriticalSection(&ddraw_cs);
3140         return hr;
3141     }
3142
3143     LeaveCriticalSection(&ddraw_cs);
3144     return D3D_OK;
3145 }
3146
3147 static HRESULT WINAPI
3148 Thunk_IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3149                                           D3DLIGHTSTATETYPE LightStateType,
3150                                           DWORD *Value)
3151 {
3152     IDirect3DDeviceImpl *This = device_from_device2(iface);
3153     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice3 interface.\n", This, LightStateType, Value);
3154     return IDirect3DDevice3_GetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3155 }
3156
3157 /*****************************************************************************
3158  * IDirect3DDevice7::SetTransform
3159  *
3160  * Assigns a D3DMATRIX to a transform type. The transform types are defined
3161  * in include/d3dtypes.h.
3162  * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3163  * (=255) for wined3d, because the 1 transform state was removed in d3d8
3164  * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3165  *
3166  * Version 2, 3 and 7
3167  *
3168  * Params:
3169  *  TransformStateType: transform state to set
3170  *  Matrix: Matrix to assign to the state
3171  *
3172  * Returns:
3173  *  D3D_OK on success
3174  *  DDERR_INVALIDPARAMS if Matrix == NULL
3175  *  For details see IWineD3DDevice::SetTransform
3176  *
3177  *****************************************************************************/
3178 static HRESULT
3179 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3180                                    D3DTRANSFORMSTATETYPE TransformStateType,
3181                                    D3DMATRIX *Matrix)
3182 {
3183     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3184     D3DTRANSFORMSTATETYPE type;
3185     HRESULT hr;
3186     TRACE("(%p)->(%08x,%p): Relay\n", This, TransformStateType, Matrix);
3187
3188     switch(TransformStateType)
3189     {
3190         case D3DTRANSFORMSTATE_WORLD :  type = WINED3DTS_WORLDMATRIX(0); break;
3191         case D3DTRANSFORMSTATE_WORLD1:  type = WINED3DTS_WORLDMATRIX(1); break;
3192         case D3DTRANSFORMSTATE_WORLD2:  type = WINED3DTS_WORLDMATRIX(2); break;
3193         case D3DTRANSFORMSTATE_WORLD3:  type = WINED3DTS_WORLDMATRIX(3); break;
3194         default:                        type = TransformStateType;
3195     }
3196
3197     if(!Matrix)
3198        return DDERR_INVALIDPARAMS;
3199
3200     /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3201     EnterCriticalSection(&ddraw_cs);
3202     hr = IWineD3DDevice_SetTransform(This->wineD3DDevice,
3203                                      type,
3204                                      (WINED3DMATRIX*) Matrix);
3205     LeaveCriticalSection(&ddraw_cs);
3206     return hr;
3207 }
3208
3209 static HRESULT WINAPI
3210 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3211                                    D3DTRANSFORMSTATETYPE TransformStateType,
3212                                    D3DMATRIX *Matrix)
3213 {
3214     return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3215 }
3216
3217 static HRESULT WINAPI
3218 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3219                                    D3DTRANSFORMSTATETYPE TransformStateType,
3220                                    D3DMATRIX *Matrix)
3221 {
3222     HRESULT hr;
3223     WORD old_fpucw;
3224
3225     old_fpucw = d3d_fpu_setup();
3226     hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3227     set_fpu_control_word(old_fpucw);
3228
3229     return hr;
3230 }
3231
3232 static HRESULT WINAPI
3233 Thunk_IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3234                                          D3DTRANSFORMSTATETYPE TransformStateType,
3235                                          D3DMATRIX *D3DMatrix)
3236 {
3237     IDirect3DDeviceImpl *This = device_from_device3(iface);
3238     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3239     return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3240 }
3241
3242 static HRESULT WINAPI
3243 Thunk_IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3244                                          D3DTRANSFORMSTATETYPE TransformStateType,
3245                                          D3DMATRIX *D3DMatrix)
3246 {
3247     IDirect3DDeviceImpl *This = device_from_device2(iface);
3248     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3249     return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3250 }
3251
3252 /*****************************************************************************
3253  * IDirect3DDevice7::GetTransform
3254  *
3255  * Returns the matrix assigned to a transform state
3256  * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3257  * SetTransform
3258  *
3259  * Params:
3260  *  TransformStateType: State to read the matrix from
3261  *  Matrix: Address to store the matrix at
3262  *
3263  * Returns:
3264  *  D3D_OK on success
3265  *  DDERR_INVALIDPARAMS if Matrix == NULL
3266  *  For details, see IWineD3DDevice::GetTransform
3267  *
3268  *****************************************************************************/
3269 static HRESULT
3270 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3271                                    D3DTRANSFORMSTATETYPE TransformStateType,
3272                                    D3DMATRIX *Matrix)
3273 {
3274     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3275     D3DTRANSFORMSTATETYPE type;
3276     HRESULT hr;
3277     TRACE("(%p)->(%08x,%p): Relay\n", This, TransformStateType, Matrix);
3278
3279     switch(TransformStateType)
3280     {
3281         case D3DTRANSFORMSTATE_WORLD :  type = WINED3DTS_WORLDMATRIX(0); break;
3282         case D3DTRANSFORMSTATE_WORLD1:  type = WINED3DTS_WORLDMATRIX(1); break;
3283         case D3DTRANSFORMSTATE_WORLD2:  type = WINED3DTS_WORLDMATRIX(2); break;
3284         case D3DTRANSFORMSTATE_WORLD3:  type = WINED3DTS_WORLDMATRIX(3); break;
3285         default:                        type = TransformStateType;
3286     }
3287
3288     if(!Matrix)
3289         return DDERR_INVALIDPARAMS;
3290
3291     /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3292     EnterCriticalSection(&ddraw_cs);
3293     hr = IWineD3DDevice_GetTransform(This->wineD3DDevice, type, (WINED3DMATRIX*) Matrix);
3294     LeaveCriticalSection(&ddraw_cs);
3295     return hr;
3296 }
3297
3298 static HRESULT WINAPI
3299 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3300                                    D3DTRANSFORMSTATETYPE TransformStateType,
3301                                    D3DMATRIX *Matrix)
3302 {
3303     return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3304 }
3305
3306 static HRESULT WINAPI
3307 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3308                                    D3DTRANSFORMSTATETYPE TransformStateType,
3309                                    D3DMATRIX *Matrix)
3310 {
3311     HRESULT hr;
3312     WORD old_fpucw;
3313
3314     old_fpucw = d3d_fpu_setup();
3315     hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3316     set_fpu_control_word(old_fpucw);
3317
3318     return hr;
3319 }
3320
3321 static HRESULT WINAPI
3322 Thunk_IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3323                                          D3DTRANSFORMSTATETYPE TransformStateType,
3324                                          D3DMATRIX *D3DMatrix)
3325 {
3326     IDirect3DDeviceImpl *This = device_from_device3(iface);
3327     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3328     return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3329 }
3330
3331 static HRESULT WINAPI
3332 Thunk_IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3333                                          D3DTRANSFORMSTATETYPE TransformStateType,
3334                                          D3DMATRIX *D3DMatrix)
3335 {
3336     IDirect3DDeviceImpl *This = device_from_device2(iface);
3337     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3338     return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3339 }
3340
3341 /*****************************************************************************
3342  * IDirect3DDevice7::MultiplyTransform
3343  *
3344  * Multiplies the already-set transform matrix of a transform state
3345  * with another matrix. For the world matrix, see SetTransform
3346  *
3347  * Version 2, 3 and 7
3348  *
3349  * Params:
3350  *  TransformStateType: Transform state to multiply
3351  *  D3DMatrix Matrix to multiply with.
3352  *
3353  * Returns
3354  *  D3D_OK on success
3355  *  DDERR_INVALIDPARAMS if D3DMatrix is NULL
3356  *  For details, see IWineD3DDevice::MultiplyTransform
3357  *
3358  *****************************************************************************/
3359 static HRESULT
3360 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3361                                         D3DTRANSFORMSTATETYPE TransformStateType,
3362                                         D3DMATRIX *D3DMatrix)
3363 {
3364     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3365     HRESULT hr;
3366     D3DTRANSFORMSTATETYPE type;
3367     TRACE("(%p)->(%08x,%p): Relay\n", This, TransformStateType, D3DMatrix);
3368
3369     switch(TransformStateType)
3370     {
3371         case D3DTRANSFORMSTATE_WORLD :  type = WINED3DTS_WORLDMATRIX(0); break;
3372         case D3DTRANSFORMSTATE_WORLD1:  type = WINED3DTS_WORLDMATRIX(1); break;
3373         case D3DTRANSFORMSTATE_WORLD2:  type = WINED3DTS_WORLDMATRIX(2); break;
3374         case D3DTRANSFORMSTATE_WORLD3:  type = WINED3DTS_WORLDMATRIX(3); break;
3375         default:                        type = TransformStateType;
3376     }
3377
3378     /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3379     EnterCriticalSection(&ddraw_cs);
3380     hr = IWineD3DDevice_MultiplyTransform(This->wineD3DDevice,
3381                                           type,
3382                                           (WINED3DMATRIX*) D3DMatrix);
3383     LeaveCriticalSection(&ddraw_cs);
3384     return hr;
3385 }
3386
3387 static HRESULT WINAPI
3388 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3389                                         D3DTRANSFORMSTATETYPE TransformStateType,
3390                                         D3DMATRIX *D3DMatrix)
3391 {
3392     return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3393 }
3394
3395 static HRESULT WINAPI
3396 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3397                                         D3DTRANSFORMSTATETYPE TransformStateType,
3398                                         D3DMATRIX *D3DMatrix)
3399 {
3400     HRESULT hr;
3401     WORD old_fpucw;
3402
3403     old_fpucw = d3d_fpu_setup();
3404     hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3405     set_fpu_control_word(old_fpucw);
3406
3407     return hr;
3408 }
3409
3410 static HRESULT WINAPI
3411 Thunk_IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3412                                               D3DTRANSFORMSTATETYPE TransformStateType,
3413                                               D3DMATRIX *D3DMatrix)
3414 {
3415     IDirect3DDeviceImpl *This = device_from_device3(iface);
3416     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3417     return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3418 }
3419
3420 static HRESULT WINAPI
3421 Thunk_IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3422                                               D3DTRANSFORMSTATETYPE TransformStateType,
3423                                               D3DMATRIX *D3DMatrix)
3424 {
3425     IDirect3DDeviceImpl *This = device_from_device2(iface);
3426     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3427     return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3428 }
3429
3430 /*****************************************************************************
3431  * IDirect3DDevice7::DrawPrimitive
3432  *
3433  * Draws primitives based on vertices in an application-provided pointer
3434  *
3435  * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3436  * an FVF format for D3D7
3437  *
3438  * Params:
3439  *  PrimitiveType: The type of the primitives to draw
3440  *  Vertex type: Flexible vertex format vertex description
3441  *  Vertices: Pointer to the vertex array
3442  *  VertexCount: The number of vertices to draw
3443  *  Flags: As usual a few flags
3444  *
3445  * Returns:
3446  *  D3D_OK on success
3447  *  DDERR_INVALIDPARAMS if Vertices is NULL
3448  *  For details, see IWineD3DDevice::DrawPrimitiveUP
3449  *
3450  *****************************************************************************/
3451 static HRESULT
3452 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3453                                     D3DPRIMITIVETYPE PrimitiveType,
3454                                     DWORD VertexType,
3455                                     void *Vertices,
3456                                     DWORD VertexCount,
3457                                     DWORD Flags)
3458 {
3459     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3460     UINT stride;
3461     HRESULT hr;
3462     TRACE("(%p)->(%08x,%08x,%p,%08x,%08x): Relay!\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3463
3464     if(!Vertices)
3465         return DDERR_INVALIDPARAMS;
3466
3467     /* Get the stride */
3468     stride = get_flexible_vertex_size(VertexType);
3469
3470     /* Set the FVF */
3471     EnterCriticalSection(&ddraw_cs);
3472     hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
3473                                              IDirectDrawImpl_FindDecl(This->ddraw, VertexType));
3474     if(hr != D3D_OK)
3475     {
3476         LeaveCriticalSection(&ddraw_cs);
3477         return hr;
3478     }
3479
3480     /* This method translates to the user pointer draw of WineD3D */
3481     IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3482     hr = IWineD3DDevice_DrawPrimitiveUP(This->wineD3DDevice, VertexCount, Vertices, stride);
3483     LeaveCriticalSection(&ddraw_cs);
3484     return hr;
3485 }
3486
3487 static HRESULT WINAPI
3488 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3489                                     D3DPRIMITIVETYPE PrimitiveType,
3490                                     DWORD VertexType,
3491                                     void *Vertices,
3492                                     DWORD VertexCount,
3493                                     DWORD Flags)
3494 {
3495     return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3496 }
3497
3498 static HRESULT WINAPI
3499 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3500                                     D3DPRIMITIVETYPE PrimitiveType,
3501                                     DWORD VertexType,
3502                                     void *Vertices,
3503                                     DWORD VertexCount,
3504                                     DWORD Flags)
3505 {
3506     HRESULT hr;
3507     WORD old_fpucw;
3508
3509     old_fpucw = d3d_fpu_setup();
3510     hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3511     set_fpu_control_word(old_fpucw);
3512
3513     return hr;
3514 }
3515
3516 static HRESULT WINAPI
3517 Thunk_IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3518                                           D3DPRIMITIVETYPE PrimitiveType,
3519                                           DWORD VertexType,
3520                                           void *Vertices,
3521                                           DWORD VertexCount,
3522                                           DWORD Flags)
3523 {
3524     IDirect3DDeviceImpl *This = device_from_device3(iface);
3525     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3526     return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This,
3527             PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3528 }
3529
3530 static HRESULT WINAPI
3531 Thunk_IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3532                                           D3DPRIMITIVETYPE PrimitiveType,
3533                                           D3DVERTEXTYPE VertexType,
3534                                           void *Vertices,
3535                                           DWORD VertexCount,
3536                                           DWORD Flags)
3537 {
3538     IDirect3DDeviceImpl *This = device_from_device2(iface);
3539     DWORD FVF;
3540     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3541
3542     switch(VertexType)
3543     {
3544         case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3545         case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3546         case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3547         default:
3548             ERR("Unexpected vertex type %d\n", VertexType);
3549             return DDERR_INVALIDPARAMS;  /* Should never happen */
3550     }
3551
3552     return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This, PrimitiveType, FVF, Vertices, VertexCount, Flags);
3553 }
3554
3555 /*****************************************************************************
3556  * IDirect3DDevice7::DrawIndexedPrimitive
3557  *
3558  * Draws vertices from an application-provided pointer, based on the index
3559  * numbers in a WORD array.
3560  *
3561  * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3562  * an FVF format for D3D7
3563  *
3564  * Params:
3565  *  PrimitiveType: The primitive type to draw
3566  *  VertexType: The FVF vertex description
3567  *  Vertices: Pointer to the vertex array
3568  *  VertexCount: ?
3569  *  Indices: Pointer to the index array
3570  *  IndexCount: Number of indices = Number of vertices to draw
3571  *  Flags: As usual, some flags
3572  *
3573  * Returns:
3574  *  D3D_OK on success
3575  *  DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3576  *  For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3577  *
3578  *****************************************************************************/
3579 static HRESULT
3580 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3581                                            D3DPRIMITIVETYPE PrimitiveType,
3582                                            DWORD VertexType,
3583                                            void *Vertices,
3584                                            DWORD VertexCount,
3585                                            WORD *Indices,
3586                                            DWORD IndexCount,
3587                                            DWORD Flags)
3588 {
3589     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3590     HRESULT hr;
3591     TRACE("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x): Relay!\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3592
3593     /* Set the D3DDevice's FVF */
3594     EnterCriticalSection(&ddraw_cs);
3595     hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
3596                                              IDirectDrawImpl_FindDecl(This->ddraw, VertexType));
3597     if(FAILED(hr))
3598     {
3599         ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3600         LeaveCriticalSection(&ddraw_cs);
3601         return hr;
3602     }
3603
3604     IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3605     hr = IWineD3DDevice_DrawIndexedPrimitiveUP(This->wineD3DDevice, IndexCount, Indices,
3606             WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3607     LeaveCriticalSection(&ddraw_cs);
3608     return hr;
3609 }
3610
3611 static HRESULT WINAPI
3612 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3613                                            D3DPRIMITIVETYPE PrimitiveType,
3614                                            DWORD VertexType,
3615                                            void *Vertices,
3616                                            DWORD VertexCount,
3617                                            WORD *Indices,
3618                                            DWORD IndexCount,
3619                                            DWORD Flags)
3620 {
3621     return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3622 }
3623
3624 static HRESULT WINAPI
3625 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3626                                            D3DPRIMITIVETYPE PrimitiveType,
3627                                            DWORD VertexType,
3628                                            void *Vertices,
3629                                            DWORD VertexCount,
3630                                            WORD *Indices,
3631                                            DWORD IndexCount,
3632                                            DWORD Flags)
3633 {
3634     HRESULT hr;
3635     WORD old_fpucw;
3636
3637     old_fpucw = d3d_fpu_setup();
3638     hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3639     set_fpu_control_word(old_fpucw);
3640
3641     return hr;
3642 }
3643
3644 static HRESULT WINAPI
3645 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3646                                                  D3DPRIMITIVETYPE PrimitiveType,
3647                                                  DWORD VertexType,
3648                                                  void *Vertices,
3649                                                  DWORD VertexCount,
3650                                                  WORD *Indices,
3651                                                  DWORD IndexCount,
3652                                                  DWORD Flags)
3653 {
3654     IDirect3DDeviceImpl *This = device_from_device3(iface);
3655     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3656     return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)This,
3657             PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3658 }
3659
3660 static HRESULT WINAPI
3661 Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3662                                                  D3DPRIMITIVETYPE PrimitiveType,
3663                                                  D3DVERTEXTYPE VertexType,
3664                                                  void *Vertices,
3665                                                  DWORD VertexCount,
3666                                                  WORD *Indices,
3667                                                  DWORD IndexCount,
3668                                                  DWORD Flags)
3669 {
3670     DWORD FVF;
3671     IDirect3DDeviceImpl *This = device_from_device2(iface);
3672     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3673
3674     switch(VertexType)
3675     {
3676         case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3677         case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3678         case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3679         default:
3680             ERR("Unexpected vertex type %d\n", VertexType);
3681             return DDERR_INVALIDPARAMS;  /* Should never happen */
3682     }
3683
3684     return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)This,
3685             PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3686 }
3687
3688 /*****************************************************************************
3689  * IDirect3DDevice7::SetClipStatus
3690  *
3691  * Sets the clip status. This defines things as clipping conditions and
3692  * the extents of the clipping region.
3693  *
3694  * Version 2, 3 and 7
3695  *
3696  * Params:
3697  *  ClipStatus:
3698  *
3699  * Returns:
3700  *  D3D_OK because it's a stub
3701  *  (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3702  *
3703  *****************************************************************************/
3704 static HRESULT WINAPI
3705 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3706                                     D3DCLIPSTATUS *ClipStatus)
3707 {
3708     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3709     FIXME("(%p)->(%p): Stub!\n", This, ClipStatus);
3710
3711     /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3712      * Perhaps this needs a new data type and an additional IWineD3DDevice method
3713      */
3714     /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3715     return D3D_OK;
3716 }
3717
3718 static HRESULT WINAPI
3719 Thunk_IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3720                                           D3DCLIPSTATUS *ClipStatus)
3721 {
3722     IDirect3DDeviceImpl *This = device_from_device3(iface);
3723     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3724     return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)This, ClipStatus);
3725 }
3726
3727 static HRESULT WINAPI
3728 Thunk_IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3729                                           D3DCLIPSTATUS *ClipStatus)
3730 {
3731     IDirect3DDeviceImpl *This = device_from_device2(iface);
3732     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3733     return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)This, ClipStatus);
3734 }
3735
3736 /*****************************************************************************
3737  * IDirect3DDevice7::GetClipStatus
3738  *
3739  * Returns the clip status
3740  *
3741  * Params:
3742  *  ClipStatus: Address to write the clip status to
3743  *
3744  * Returns:
3745  *  D3D_OK because it's a stub
3746  *
3747  *****************************************************************************/
3748 static HRESULT WINAPI
3749 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3750                                     D3DCLIPSTATUS *ClipStatus)
3751 {
3752     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3753     FIXME("(%p)->(%p): Stub!\n", This, ClipStatus);
3754
3755     /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3756     /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3757     return D3D_OK;
3758 }
3759
3760 static HRESULT WINAPI
3761 Thunk_IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3762                                           D3DCLIPSTATUS *ClipStatus)
3763 {
3764     IDirect3DDeviceImpl *This = device_from_device3(iface);
3765     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3766     return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)This, ClipStatus);
3767 }
3768
3769 static HRESULT WINAPI
3770 Thunk_IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3771                                           D3DCLIPSTATUS *ClipStatus)
3772 {
3773     IDirect3DDeviceImpl *This = device_from_device2(iface);
3774     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3775     return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)This, ClipStatus);
3776 }
3777
3778 /*****************************************************************************
3779  * IDirect3DDevice::DrawPrimitiveStrided
3780  *
3781  * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3782  *
3783  * Version 3 and 7
3784  *
3785  * Params:
3786  *  PrimitiveType: The primitive type to draw
3787  *  VertexType: The FVF description of the vertices to draw (for the stride??)
3788  *  D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3789  *                         the vertex data locations
3790  *  VertexCount: The number of vertices to draw
3791  *  Flags: Some flags
3792  *
3793  * Returns:
3794  *  D3D_OK, because it's a stub
3795  *  (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3796  *  (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3797  *
3798  *****************************************************************************/
3799 static HRESULT
3800 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3801                                            D3DPRIMITIVETYPE PrimitiveType,
3802                                            DWORD VertexType,
3803                                            D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3804                                            DWORD VertexCount,
3805                                            DWORD Flags)
3806 {
3807     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3808     WineDirect3DVertexStridedData WineD3DStrided;
3809     DWORD i;
3810     HRESULT hr;
3811
3812     TRACE("(%p)->(%08x,%08x,%p,%08x,%08x): stub!\n", This, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3813
3814     memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3815     /* Get the strided data right. the wined3d structure is a bit bigger
3816      * Watch out: The contents of the strided data are determined by the fvf,
3817      * not by the members set in D3DDrawPrimStrideData. So it's valid
3818      * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3819      * not set in the fvf.
3820      */
3821     if(VertexType & D3DFVF_POSITION_MASK)
3822     {
3823         WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3824         WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3825         WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3826         if (VertexType & D3DFVF_XYZRHW)
3827         {
3828             WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3829             WineD3DStrided.position_transformed = TRUE;
3830         } else
3831             WineD3DStrided.position_transformed = FALSE;
3832     }
3833
3834     if(VertexType & D3DFVF_NORMAL)
3835     {
3836         WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3837         WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3838         WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3839     }
3840
3841     if(VertexType & D3DFVF_DIFFUSE)
3842     {
3843         WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3844         WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3845         WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3846     }
3847
3848     if(VertexType & D3DFVF_SPECULAR)
3849     {
3850         WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3851         WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3852         WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3853     }
3854
3855     for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3856     {
3857         switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3858         {
3859             case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3860             case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3861             case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3862             case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3863             default: ERR("Unexpected texture coordinate size %d\n",
3864                          GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3865         }
3866         WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3867         WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3868     }
3869
3870     /* WineD3D doesn't need the FVF here */
3871     EnterCriticalSection(&ddraw_cs);
3872     IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3873     hr = IWineD3DDevice_DrawPrimitiveStrided(This->wineD3DDevice, VertexCount, &WineD3DStrided);
3874     LeaveCriticalSection(&ddraw_cs);
3875     return hr;
3876 }
3877
3878 static HRESULT WINAPI
3879 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3880                                            D3DPRIMITIVETYPE PrimitiveType,
3881                                            DWORD VertexType,
3882                                            D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3883                                            DWORD VertexCount,
3884                                            DWORD Flags)
3885 {
3886     return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3887 }
3888
3889 static HRESULT WINAPI
3890 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3891                                            D3DPRIMITIVETYPE PrimitiveType,
3892                                            DWORD VertexType,
3893                                            D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3894                                            DWORD VertexCount,
3895                                            DWORD Flags)
3896 {
3897     HRESULT hr;
3898     WORD old_fpucw;
3899
3900     old_fpucw = d3d_fpu_setup();
3901     hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3902     set_fpu_control_word(old_fpucw);
3903
3904     return hr;
3905 }
3906
3907 static HRESULT WINAPI
3908 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3909                                                  D3DPRIMITIVETYPE PrimitiveType,
3910                                                  DWORD VertexType,
3911                                                  D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3912                                                  DWORD VertexCount,
3913                                                  DWORD Flags)
3914 {
3915     IDirect3DDeviceImpl *This = device_from_device3(iface);
3916     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3917     return IDirect3DDevice7_DrawPrimitiveStrided((IDirect3DDevice7 *)This,
3918             PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3919 }
3920
3921 /*****************************************************************************
3922  * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3923  *
3924  * Draws primitives specified by strided data locations based on indices
3925  *
3926  * Version 3 and 7
3927  *
3928  * Params:
3929  *  PrimitiveType:
3930  *
3931  * Returns:
3932  *  D3D_OK, because it's a stub
3933  *  (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3934  *  (DDERR_INVALIDPARAMS if Indices is NULL)
3935  *  (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3936  *
3937  *****************************************************************************/
3938 static HRESULT
3939 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3940                                                   D3DPRIMITIVETYPE PrimitiveType,
3941                                                   DWORD VertexType,
3942                                                   D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3943                                                   DWORD VertexCount,
3944                                                   WORD *Indices,
3945                                                   DWORD IndexCount,
3946                                                   DWORD Flags)
3947 {
3948     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3949     WineDirect3DVertexStridedData WineD3DStrided;
3950     DWORD i;
3951     HRESULT hr;
3952
3953     TRACE("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x)\n", This, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3954
3955     memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3956     /* Get the strided data right. the wined3d structure is a bit bigger
3957      * Watch out: The contents of the strided data are determined by the fvf,
3958      * not by the members set in D3DDrawPrimStrideData. So it's valid
3959      * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3960      * not set in the fvf.
3961      */
3962     if(VertexType & D3DFVF_POSITION_MASK)
3963     {
3964         WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3965         WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3966         WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3967         if (VertexType & D3DFVF_XYZRHW)
3968         {
3969             WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3970             WineD3DStrided.position_transformed = TRUE;
3971         } else
3972             WineD3DStrided.position_transformed = FALSE;
3973     }
3974
3975     if(VertexType & D3DFVF_NORMAL)
3976     {
3977         WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3978         WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3979         WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3980     }
3981
3982     if(VertexType & D3DFVF_DIFFUSE)
3983     {
3984         WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3985         WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3986         WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3987     }
3988
3989     if(VertexType & D3DFVF_SPECULAR)
3990     {
3991         WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3992         WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3993         WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3994     }
3995
3996     for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3997     {
3998         switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3999         {
4000             case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
4001             case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
4002             case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
4003             case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
4004             default: ERR("Unexpected texture coordinate size %d\n",
4005                          GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4006         }
4007         WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4008         WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4009     }
4010
4011     /* WineD3D doesn't need the FVF here */
4012     EnterCriticalSection(&ddraw_cs);
4013     IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4014     hr = IWineD3DDevice_DrawIndexedPrimitiveStrided(This->wineD3DDevice,
4015             IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
4016     LeaveCriticalSection(&ddraw_cs);
4017     return hr;
4018 }
4019
4020 static HRESULT WINAPI
4021 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4022                                                   D3DPRIMITIVETYPE PrimitiveType,
4023                                                   DWORD VertexType,
4024                                                   D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4025                                                   DWORD VertexCount,
4026                                                   WORD *Indices,
4027                                                   DWORD IndexCount,
4028                                                   DWORD Flags)
4029 {
4030     return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4031 }
4032
4033 static HRESULT WINAPI
4034 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4035                                                   D3DPRIMITIVETYPE PrimitiveType,
4036                                                   DWORD VertexType,
4037                                                   D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4038                                                   DWORD VertexCount,
4039                                                   WORD *Indices,
4040                                                   DWORD IndexCount,
4041                                                   DWORD Flags)
4042 {
4043     HRESULT hr;
4044     WORD old_fpucw;
4045
4046     old_fpucw = d3d_fpu_setup();
4047     hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4048     set_fpu_control_word(old_fpucw);
4049
4050     return hr;
4051 }
4052
4053 static HRESULT WINAPI
4054 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4055                                                         D3DPRIMITIVETYPE PrimitiveType,
4056                                                         DWORD VertexType,
4057                                                         D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4058                                                         DWORD VertexCount,
4059                                                         WORD *Indices,
4060                                                         DWORD IndexCount,
4061                                                         DWORD Flags)
4062 {
4063     IDirect3DDeviceImpl *This = device_from_device3(iface);
4064     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4065     return IDirect3DDevice7_DrawIndexedPrimitiveStrided((IDirect3DDevice7 *)This, PrimitiveType,
4066             VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4067 }
4068
4069 /*****************************************************************************
4070  * IDirect3DDevice7::DrawPrimitiveVB
4071  *
4072  * Draws primitives from a vertex buffer to the screen.
4073  *
4074  * Version 3 and 7
4075  *
4076  * Params:
4077  *  PrimitiveType: Type of primitive to be rendered.
4078  *  D3DVertexBuf: Source Vertex Buffer
4079  *  StartVertex: Index of the first vertex from the buffer to be rendered
4080  *  NumVertices: Number of vertices to be rendered
4081  *  Flags: Can be D3DDP_WAIT to wait until rendering has finished
4082  *
4083  * Return values
4084  *  D3D_OK on success
4085  *  DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4086  *
4087  *****************************************************************************/
4088 static HRESULT
4089 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4090                                       D3DPRIMITIVETYPE PrimitiveType,
4091                                       IDirect3DVertexBuffer7 *D3DVertexBuf,
4092                                       DWORD StartVertex,
4093                                       DWORD NumVertices,
4094                                       DWORD Flags)
4095 {
4096     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4097     IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4098     HRESULT hr;
4099     DWORD stride;
4100
4101     TRACE("(%p)->(%08x,%p,%08x,%08x,%08x)\n", This, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4102
4103     /* Sanity checks */
4104     if(!vb)
4105     {
4106         ERR("(%p) No Vertex buffer specified\n", This);
4107         return DDERR_INVALIDPARAMS;
4108     }
4109     stride = get_flexible_vertex_size(vb->fvf);
4110
4111     EnterCriticalSection(&ddraw_cs);
4112     hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4113                                              vb->wineD3DVertexDeclaration);
4114     if(FAILED(hr))
4115     {
4116         ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4117         LeaveCriticalSection(&ddraw_cs);
4118         return hr;
4119     }
4120
4121     /* Set the vertex stream source */
4122     hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4123                                         0 /* StreamNumber */,
4124                                         vb->wineD3DVertexBuffer,
4125                                         0 /* StartVertex - we pass this to DrawPrimitive */,
4126                                         stride);
4127     if(hr != D3D_OK)
4128     {
4129         ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4130         LeaveCriticalSection(&ddraw_cs);
4131         return hr;
4132     }
4133
4134     /* Now draw the primitives */
4135     IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4136     hr = IWineD3DDevice_DrawPrimitive(This->wineD3DDevice, StartVertex, NumVertices);
4137     LeaveCriticalSection(&ddraw_cs);
4138     return hr;
4139 }
4140
4141 static HRESULT WINAPI
4142 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4143                                       D3DPRIMITIVETYPE PrimitiveType,
4144                                       IDirect3DVertexBuffer7 *D3DVertexBuf,
4145                                       DWORD StartVertex,
4146                                       DWORD NumVertices,
4147                                       DWORD Flags)
4148 {
4149     return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4150 }
4151
4152 static HRESULT WINAPI
4153 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4154                                       D3DPRIMITIVETYPE PrimitiveType,
4155                                       IDirect3DVertexBuffer7 *D3DVertexBuf,
4156                                       DWORD StartVertex,
4157                                       DWORD NumVertices,
4158                                       DWORD Flags)
4159 {
4160     HRESULT hr;
4161     WORD old_fpucw;
4162
4163     old_fpucw = d3d_fpu_setup();
4164     hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4165     set_fpu_control_word(old_fpucw);
4166
4167     return hr;
4168 }
4169
4170 static HRESULT WINAPI
4171 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4172                                             D3DPRIMITIVETYPE PrimitiveType,
4173                                             IDirect3DVertexBuffer *D3DVertexBuf,
4174                                             DWORD StartVertex,
4175                                             DWORD NumVertices,
4176                                             DWORD Flags)
4177 {
4178     IDirect3DDeviceImpl *This = device_from_device3(iface);
4179     IDirect3DVertexBufferImpl *vb = D3DVertexBuf ? vb_from_vb1(D3DVertexBuf) : NULL;
4180     TRACE_(ddraw_thunk)("(%p)->(%08x,%p,%08x,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This,  PrimitiveType, vb, StartVertex, NumVertices, Flags);
4181     return IDirect3DDevice7_DrawPrimitiveVB((IDirect3DDevice7 *)This, PrimitiveType,
4182             (IDirect3DVertexBuffer7 *)vb, StartVertex, NumVertices, Flags);
4183 }
4184
4185
4186 /*****************************************************************************
4187  * IDirect3DDevice7::DrawIndexedPrimitiveVB
4188  *
4189  * Draws primitives from a vertex buffer to the screen
4190  *
4191  * Params:
4192  *  PrimitiveType: Type of primitive to be rendered.
4193  *  D3DVertexBuf: Source Vertex Buffer
4194  *  StartVertex: Index of the first vertex from the buffer to be rendered
4195  *  NumVertices: Number of vertices to be rendered
4196  *  Indices: Array of DWORDs used to index into the Vertices
4197  *  IndexCount: Number of indices in Indices
4198  *  Flags: Can be D3DDP_WAIT to wait until rendering has finished
4199  *
4200  * Return values
4201  *
4202  *****************************************************************************/
4203 static HRESULT
4204 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4205                                              D3DPRIMITIVETYPE PrimitiveType,
4206                                              IDirect3DVertexBuffer7 *D3DVertexBuf,
4207                                              DWORD StartVertex,
4208                                              DWORD NumVertices,
4209                                              WORD *Indices,
4210                                              DWORD IndexCount,
4211                                              DWORD Flags)
4212 {
4213     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4214     IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4215     DWORD stride = get_flexible_vertex_size(vb->fvf);
4216     WORD *LockedIndices;
4217     HRESULT hr;
4218
4219     TRACE("(%p)->(%08x,%p,%d,%d,%p,%d,%08x)\n", This, PrimitiveType, vb, StartVertex, NumVertices, Indices, IndexCount, Flags);
4220
4221     /* Steps:
4222      * 1) Upload the Indices to the index buffer
4223      * 2) Set the index source
4224      * 3) Set the Vertex Buffer as the Stream source
4225      * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4226      */
4227
4228     EnterCriticalSection(&ddraw_cs);
4229
4230     hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4231                                              vb->wineD3DVertexDeclaration);
4232     if(FAILED(hr))
4233     {
4234         ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4235         LeaveCriticalSection(&ddraw_cs);
4236         return hr;
4237     }
4238
4239     /* copy the index stream into the index buffer.
4240      * A new IWineD3DDevice method could be created
4241      * which takes an user pointer containing the indices
4242      * or a SetData-Method for the index buffer, which
4243      * overrides the index buffer data with our pointer.
4244      */
4245     hr = IWineD3DBuffer_Map(This->indexbuffer,
4246                             0 /* OffSetToLock */,
4247                             IndexCount * sizeof(WORD),
4248                             (BYTE **) &LockedIndices,
4249                             0 /* Flags */);
4250     assert(IndexCount < 0x100000);
4251     if(hr != D3D_OK)
4252     {
4253         ERR("(%p) IWineD3DBuffer::Map failed with hr = %08x\n", This, hr);
4254         LeaveCriticalSection(&ddraw_cs);
4255         return hr;
4256     }
4257     memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4258     hr = IWineD3DBuffer_Unmap(This->indexbuffer);
4259     if(hr != D3D_OK)
4260     {
4261         ERR("(%p) IWineD3DBuffer::Unmap failed with hr = %08x\n", This, hr);
4262         LeaveCriticalSection(&ddraw_cs);
4263         return hr;
4264     }
4265
4266     /* Set the index stream */
4267     IWineD3DDevice_SetBaseVertexIndex(This->wineD3DDevice, StartVertex);
4268     hr = IWineD3DDevice_SetIndexBuffer(This->wineD3DDevice, This->indexbuffer,
4269                                    WINED3DFMT_R16_UINT);
4270
4271     /* Set the vertex stream source */
4272     hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4273                                         0 /* StreamNumber */,
4274                                         vb->wineD3DVertexBuffer,
4275                                         0 /* offset, we pass this to DrawIndexedPrimitive */,
4276                                         stride);
4277     if(hr != D3D_OK)
4278     {
4279         ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4280         LeaveCriticalSection(&ddraw_cs);
4281         return hr;
4282     }
4283
4284
4285     IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4286     hr = IWineD3DDevice_DrawIndexedPrimitive(This->wineD3DDevice, 0 /* StartIndex */, IndexCount);
4287
4288     LeaveCriticalSection(&ddraw_cs);
4289     return hr;
4290 }
4291
4292 static HRESULT WINAPI
4293 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4294                                              D3DPRIMITIVETYPE PrimitiveType,
4295                                              IDirect3DVertexBuffer7 *D3DVertexBuf,
4296                                              DWORD StartVertex,
4297                                              DWORD NumVertices,
4298                                              WORD *Indices,
4299                                              DWORD IndexCount,
4300                                              DWORD Flags)
4301 {
4302     return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4303 }
4304
4305 static HRESULT WINAPI
4306 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4307                                              D3DPRIMITIVETYPE PrimitiveType,
4308                                              IDirect3DVertexBuffer7 *D3DVertexBuf,
4309                                              DWORD StartVertex,
4310                                              DWORD NumVertices,
4311                                              WORD *Indices,
4312                                              DWORD IndexCount,
4313                                              DWORD Flags)
4314 {
4315     HRESULT hr;
4316     WORD old_fpucw;
4317
4318     old_fpucw = d3d_fpu_setup();
4319     hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4320     set_fpu_control_word(old_fpucw);
4321
4322     return hr;
4323 }
4324
4325 static HRESULT WINAPI
4326 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4327                                                    D3DPRIMITIVETYPE PrimitiveType,
4328                                                    IDirect3DVertexBuffer *D3DVertexBuf,
4329                                                    WORD *Indices,
4330                                                    DWORD IndexCount,
4331                                                    DWORD Flags)
4332 {
4333     IDirect3DDeviceImpl *This = device_from_device3(iface);
4334     IDirect3DVertexBufferImpl *VB = vb_from_vb1(D3DVertexBuf);
4335     TRACE_(ddraw_thunk)("(%p)->(%08x,%p,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VB, Indices, IndexCount, Flags);
4336
4337     return IDirect3DDevice7_DrawIndexedPrimitiveVB((IDirect3DDevice7 *)This, PrimitiveType,
4338             (IDirect3DVertexBuffer7 *)VB, 0, IndexCount, Indices, IndexCount, Flags);
4339 }
4340
4341 /*****************************************************************************
4342  * IDirect3DDevice7::ComputeSphereVisibility
4343  *
4344  * Calculates the visibility of spheres in the current viewport. The spheres
4345  * are passed in the Centers and Radii arrays, the results are passed back
4346  * in the ReturnValues array. Return values are either completely visible,
4347  * partially visible or completely invisible.
4348  * The return value consist of a combination of D3DCLIP_* flags, or it's
4349  * 0 if the sphere is completely visible(according to the SDK, not checked)
4350  *
4351  * Version 3 and 7
4352  *
4353  * Params:
4354  *  Centers: Array containing the sphere centers
4355  *  Radii: Array containing the sphere radii
4356  *  NumSpheres: The number of centers and radii in the arrays
4357  *  Flags: Some flags
4358  *  ReturnValues: Array to write the results to
4359  *
4360  * Returns:
4361  *  D3D_OK
4362  *  (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4363  *  (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4364  *  is singular)
4365  *
4366  *****************************************************************************/
4367
4368 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4369 {
4370     float distance, norm;
4371
4372     norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4373     distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4374
4375     if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4376     if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT  | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4377     return 0;
4378 }
4379
4380 static HRESULT WINAPI
4381 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4382                                               D3DVECTOR *Centers,
4383                                               D3DVALUE *Radii,
4384                                               DWORD NumSpheres,
4385                                               DWORD Flags,
4386                                               DWORD *ReturnValues)
4387 {
4388     D3DMATRIX m, temp;
4389     D3DVALUE origin_plane[6];
4390     D3DVECTOR vec[6];
4391     HRESULT hr;
4392     UINT i, j;
4393
4394     TRACE("(%p)->(%p,%p,%08x,%08x,%p)\n", iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4395
4396     hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4397     if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4398     hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4399     if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4400     multiply_matrix_D3D_way(&m, &m, &temp);
4401
4402     hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4403     if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4404     multiply_matrix_D3D_way(&m, &m, &temp);
4405
4406 /* Left plane */
4407     vec[0].u1.x = m._14 + m._11;
4408     vec[0].u2.y = m._24 + m._21;
4409     vec[0].u3.z = m._34 + m._31;
4410     origin_plane[0] = m._44 + m._41;
4411
4412 /* Right plane */
4413     vec[1].u1.x = m._14 - m._11;
4414     vec[1].u2.y = m._24 - m._21;
4415     vec[1].u3.z = m._34 - m._31;
4416     origin_plane[1] = m._44 - m._41;
4417
4418 /* Top plane */
4419     vec[2].u1.x = m._14 - m._12;
4420     vec[2].u2.y = m._24 - m._22;
4421     vec[2].u3.z = m._34 - m._32;
4422     origin_plane[2] = m._44 - m._42;
4423
4424 /* Bottom plane */
4425     vec[3].u1.x = m._14 + m._12;
4426     vec[3].u2.y = m._24 + m._22;
4427     vec[3].u3.z = m._34 + m._32;
4428     origin_plane[3] = m._44 + m._42;
4429
4430 /* Front plane */
4431     vec[4].u1.x = m._13;
4432     vec[4].u2.y = m._23;
4433     vec[4].u3.z = m._33;
4434     origin_plane[4] = m._43;
4435
4436 /* Back plane*/
4437     vec[5].u1.x = m._14 - m._13;
4438     vec[5].u2.y = m._24 - m._23;
4439     vec[5].u3.z = m._34 - m._33;
4440     origin_plane[5] = m._44 - m._43;
4441
4442     for(i=0; i<NumSpheres; i++)
4443     {
4444         ReturnValues[i] = 0;
4445         for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4446     }
4447
4448     return D3D_OK;
4449 }
4450
4451 static HRESULT WINAPI
4452 Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4453                                                     D3DVECTOR *Centers,
4454                                                     D3DVALUE *Radii,
4455                                                     DWORD NumSpheres,
4456                                                     DWORD Flags,
4457                                                     DWORD *ReturnValues)
4458 {
4459     IDirect3DDeviceImpl *This = device_from_device3(iface);
4460     TRACE_(ddraw_thunk)("(%p)->(%p,%p,%08x,%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, Centers, Radii, NumSpheres, Flags, ReturnValues);
4461     return IDirect3DDevice7_ComputeSphereVisibility((IDirect3DDevice7 *)This,
4462             Centers, Radii, NumSpheres, Flags, ReturnValues);
4463 }
4464
4465 /*****************************************************************************
4466  * IDirect3DDevice7::GetTexture
4467  *
4468  * Returns the texture interface handle assigned to a texture stage.
4469  * The returned texture is AddRefed. This is taken from old ddraw,
4470  * not checked in Windows.
4471  *
4472  * Version 3 and 7
4473  *
4474  * Params:
4475  *  Stage: Texture stage to read the texture from
4476  *  Texture: Address to store the interface pointer at
4477  *
4478  * Returns:
4479  *  D3D_OK on success
4480  *  DDERR_INVALIDPARAMS if Texture is NULL
4481  *  For details, see IWineD3DDevice::GetTexture
4482  *
4483  *****************************************************************************/
4484 static HRESULT
4485 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4486                                  DWORD Stage,
4487                                  IDirectDrawSurface7 **Texture)
4488 {
4489     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4490     IWineD3DBaseTexture *Surf;
4491     HRESULT hr;
4492     TRACE("(%p)->(%d,%p): Relay\n", This, Stage, Texture);
4493
4494     if(!Texture)
4495     {
4496         TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4497         return DDERR_INVALIDPARAMS;
4498     }
4499
4500     EnterCriticalSection(&ddraw_cs);
4501     hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, Stage, &Surf);
4502     if( (hr != D3D_OK) || (!Surf) )
4503     {
4504         *Texture = NULL;
4505         LeaveCriticalSection(&ddraw_cs);
4506         return hr;
4507     }
4508
4509     /* GetParent AddRef()s, which is perfectly OK.
4510      * We have passed the IDirectDrawSurface7 interface to WineD3D, so that's OK too.
4511      */
4512     hr = IWineD3DBaseTexture_GetParent(Surf,
4513                                        (IUnknown **) Texture);
4514     LeaveCriticalSection(&ddraw_cs);
4515     return hr;
4516 }
4517
4518 static HRESULT WINAPI
4519 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4520                                  DWORD Stage,
4521                                  IDirectDrawSurface7 **Texture)
4522 {
4523     return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4524 }
4525
4526 static HRESULT WINAPI
4527 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4528                                  DWORD Stage,
4529                                  IDirectDrawSurface7 **Texture)
4530 {
4531     HRESULT hr;
4532     WORD old_fpucw;
4533
4534     old_fpucw = d3d_fpu_setup();
4535     hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4536     set_fpu_control_word(old_fpucw);
4537
4538     return hr;
4539 }
4540
4541 static HRESULT WINAPI
4542 Thunk_IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface,
4543                                        DWORD Stage,
4544                                        IDirect3DTexture2 **Texture2)
4545 {
4546     IDirect3DDeviceImpl *This = device_from_device3(iface);
4547     HRESULT ret;
4548     IDirectDrawSurface7 *ret_val;
4549
4550     TRACE_(ddraw_thunk)("(%p)->(%d,%p) thunking to IDirect3DDevice7 interface.\n", This, Stage, Texture2);
4551     ret = IDirect3DDevice7_GetTexture((IDirect3DDevice7 *)This, Stage, &ret_val);
4552
4553     *Texture2 = ret_val ? (IDirect3DTexture2 *)&((IDirectDrawSurfaceImpl *)ret_val)->IDirect3DTexture2_vtbl : NULL;
4554
4555     TRACE_(ddraw_thunk)(" returning interface %p.\n", *Texture2);
4556
4557     return ret;
4558 }
4559
4560 /*****************************************************************************
4561  * IDirect3DDevice7::SetTexture
4562  *
4563  * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4564  *
4565  * Version 3 and 7
4566  *
4567  * Params:
4568  *  Stage: The stage to assign the texture to
4569  *  Texture: Interface pointer to the texture surface
4570  *
4571  * Returns
4572  * D3D_OK on success
4573  * For details, see IWineD3DDevice::SetTexture
4574  *
4575  *****************************************************************************/
4576 static HRESULT
4577 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4578                                  DWORD Stage,
4579                                  IDirectDrawSurface7 *Texture)
4580 {
4581     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4582     IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
4583     HRESULT hr;
4584     TRACE("(%p)->(%08x,%p): Relay!\n", This, Stage, surf);
4585
4586     /* Texture may be NULL here */
4587     EnterCriticalSection(&ddraw_cs);
4588     hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
4589                                    Stage,
4590                                    surf ? surf->wineD3DTexture : NULL);
4591     LeaveCriticalSection(&ddraw_cs);
4592     return hr;
4593 }
4594
4595 static HRESULT WINAPI
4596 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4597                                  DWORD Stage,
4598                                  IDirectDrawSurface7 *Texture)
4599 {
4600     return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4601 }
4602
4603 static HRESULT WINAPI
4604 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4605                                  DWORD Stage,
4606                                  IDirectDrawSurface7 *Texture)
4607 {
4608     HRESULT hr;
4609     WORD old_fpucw;
4610
4611     old_fpucw = d3d_fpu_setup();
4612     hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4613     set_fpu_control_word(old_fpucw);
4614
4615     return hr;
4616 }
4617
4618 static HRESULT WINAPI
4619 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4620                                  DWORD Stage,
4621                                  IDirect3DTexture2 *Texture2)
4622 {
4623     IDirect3DDeviceImpl *This = device_from_device3(iface);
4624     IDirectDrawSurfaceImpl *tex = Texture2 ? surface_from_texture2(Texture2) : NULL;
4625     DWORD texmapblend;
4626     HRESULT hr;
4627     TRACE("(%p)->(%d,%p)\n", This, Stage, tex);
4628
4629     EnterCriticalSection(&ddraw_cs);
4630
4631     if (This->legacyTextureBlending)
4632         IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4633
4634     hr = IDirect3DDevice7_SetTexture((IDirect3DDevice7 *)This, Stage, (IDirectDrawSurface7 *)tex);
4635
4636     if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4637     {
4638         /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4639            See IDirect3DDeviceImpl_3_SetRenderState for details. */
4640         BOOL tex_alpha = FALSE;
4641         IWineD3DBaseTexture *tex = NULL;
4642         WINED3DSURFACE_DESC desc;
4643         DDPIXELFORMAT ddfmt;
4644         HRESULT result;
4645
4646         result = IWineD3DDevice_GetTexture(This->wineD3DDevice,
4647                                     0,
4648                                     &tex);
4649
4650         if(result == WINED3D_OK && tex)
4651         {
4652             memset(&desc, 0, sizeof(desc));
4653             result = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
4654             if (SUCCEEDED(result))
4655             {
4656                 ddfmt.dwSize = sizeof(ddfmt);
4657                 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4658                 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4659             }
4660
4661             IWineD3DBaseTexture_Release(tex);
4662         }
4663
4664         /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4665         if (tex_alpha)
4666             IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4667         else
4668             IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4669     }
4670
4671     LeaveCriticalSection(&ddraw_cs);
4672
4673     return hr;
4674 }
4675
4676 static const struct tss_lookup
4677 {
4678     BOOL sampler_state;
4679     DWORD state;
4680 }
4681 tss_lookup[] =
4682 {
4683     {FALSE, WINED3DTSS_FORCE_DWORD},            /*  0, unused */
4684     {FALSE, WINED3DTSS_COLOROP},                /*  1, D3DTSS_COLOROP */
4685     {FALSE, WINED3DTSS_COLORARG1},              /*  2, D3DTSS_COLORARG1 */
4686     {FALSE, WINED3DTSS_COLORARG2},              /*  3, D3DTSS_COLORARG2 */
4687     {FALSE, WINED3DTSS_ALPHAOP},                /*  4, D3DTSS_ALPHAOP */
4688     {FALSE, WINED3DTSS_ALPHAARG1},              /*  5, D3DTSS_ALPHAARG1 */
4689     {FALSE, WINED3DTSS_ALPHAARG2},              /*  6, D3DTSS_ALPHAARG2 */
4690     {FALSE, WINED3DTSS_BUMPENVMAT00},           /*  7, D3DTSS_BUMPENVMAT00 */
4691     {FALSE, WINED3DTSS_BUMPENVMAT01},           /*  8, D3DTSS_BUMPENVMAT01 */
4692     {FALSE, WINED3DTSS_BUMPENVMAT10},           /*  9, D3DTSS_BUMPENVMAT10 */
4693     {FALSE, WINED3DTSS_BUMPENVMAT11},           /* 10, D3DTSS_BUMPENVMAT11 */
4694     {FALSE, WINED3DTSS_TEXCOORDINDEX},          /* 11, D3DTSS_TEXCOORDINDEX */
4695     {TRUE,  WINED3DSAMP_ADDRESSU},              /* 12, D3DTSS_ADDRESS */
4696     {TRUE,  WINED3DSAMP_ADDRESSU},              /* 13, D3DTSS_ADDRESSU */
4697     {TRUE,  WINED3DSAMP_ADDRESSV},              /* 14, D3DTSS_ADDRESSV */
4698     {TRUE,  WINED3DSAMP_BORDERCOLOR},           /* 15, D3DTSS_BORDERCOLOR */
4699     {TRUE,  WINED3DSAMP_MAGFILTER},             /* 16, D3DTSS_MAGFILTER */
4700     {TRUE,  WINED3DSAMP_MINFILTER},             /* 17, D3DTSS_MINFILTER */
4701     {TRUE,  WINED3DSAMP_MIPFILTER},             /* 18, D3DTSS_MIPFILTER */
4702     {TRUE,  WINED3DSAMP_MIPMAPLODBIAS},         /* 19, D3DTSS_MIPMAPLODBIAS */
4703     {TRUE,  WINED3DSAMP_MAXMIPLEVEL},           /* 20, D3DTSS_MAXMIPLEVEL */
4704     {TRUE,  WINED3DSAMP_MAXANISOTROPY},         /* 21, D3DTSS_MAXANISOTROPY */
4705     {FALSE, WINED3DTSS_BUMPENVLSCALE},          /* 22, D3DTSS_BUMPENVLSCALE */
4706     {FALSE, WINED3DTSS_BUMPENVLOFFSET},         /* 23, D3DTSS_BUMPENVLOFFSET */
4707     {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS},  /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4708 };
4709
4710 /*****************************************************************************
4711  * IDirect3DDevice7::GetTextureStageState
4712  *
4713  * Retrieves a state from a texture stage.
4714  *
4715  * Version 3 and 7
4716  *
4717  * Params:
4718  *  Stage: The stage to retrieve the state from
4719  *  TexStageStateType: The state type to retrieve
4720  *  State: Address to store the state's value at
4721  *
4722  * Returns:
4723  *  D3D_OK on success
4724  *  DDERR_INVALIDPARAMS if State is NULL
4725  *  For details, see IWineD3DDevice::GetTextureStageState
4726  *
4727  *****************************************************************************/
4728 static HRESULT
4729 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4730                                            DWORD Stage,
4731                                            D3DTEXTURESTAGESTATETYPE TexStageStateType,
4732                                            DWORD *State)
4733 {
4734     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4735     HRESULT hr;
4736     const struct tss_lookup *l = &tss_lookup[TexStageStateType];
4737     TRACE("(%p)->(%08x,%08x,%p): Relay!\n", This, Stage, TexStageStateType, State);
4738
4739     if(!State)
4740         return DDERR_INVALIDPARAMS;
4741
4742     if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4743     {
4744         WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4745         *State = 0;
4746         return DD_OK;
4747     }
4748
4749     EnterCriticalSection(&ddraw_cs);
4750
4751     if (l->sampler_state)
4752     {
4753         hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice, Stage, l->state, State);
4754
4755         switch(TexStageStateType)
4756         {
4757             /* Mipfilter is a sampler state with different values */
4758             case D3DTSS_MIPFILTER:
4759             {
4760                 switch(*State)
4761                 {
4762                     case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4763                     case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4764                     case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4765                     default:
4766                         ERR("Unexpected mipfilter value %#x\n", *State);
4767                         *State = D3DTFP_NONE;
4768                         break;
4769                 }
4770                 break;
4771             }
4772
4773             /* Magfilter has slightly different values */
4774             case D3DTSS_MAGFILTER:
4775             {
4776                 switch(*State)
4777                 {
4778                     case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4779                     case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4780                     case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4781                     case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4782                     case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4783                     default:
4784                         ERR("Unexpected wined3d mag filter value %#x\n", *State);
4785                         *State = D3DTFG_POINT;
4786                         break;
4787                 }
4788                 break;
4789             }
4790
4791             default:
4792                 break;
4793         }
4794     }
4795     else
4796     {
4797         hr = IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
4798     }
4799
4800     LeaveCriticalSection(&ddraw_cs);
4801     return hr;
4802 }
4803
4804 static HRESULT WINAPI
4805 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4806                                            DWORD Stage,
4807                                            D3DTEXTURESTAGESTATETYPE TexStageStateType,
4808                                            DWORD *State)
4809 {
4810     return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4811 }
4812
4813 static HRESULT WINAPI
4814 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4815                                            DWORD Stage,
4816                                            D3DTEXTURESTAGESTATETYPE TexStageStateType,
4817                                            DWORD *State)
4818 {
4819     HRESULT hr;
4820     WORD old_fpucw;
4821
4822     old_fpucw = d3d_fpu_setup();
4823     hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4824     set_fpu_control_word(old_fpucw);
4825
4826     return hr;
4827 }
4828
4829 static HRESULT WINAPI
4830 Thunk_IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4831                                                  DWORD Stage,
4832                                                  D3DTEXTURESTAGESTATETYPE TexStageStateType,
4833                                                  DWORD *State)
4834 {
4835     IDirect3DDeviceImpl *This = device_from_device3(iface);
4836     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, Stage, TexStageStateType, State);
4837     return IDirect3DDevice7_GetTextureStageState((IDirect3DDevice7 *)This, Stage, TexStageStateType, State);
4838 }
4839
4840 /*****************************************************************************
4841  * IDirect3DDevice7::SetTextureStageState
4842  *
4843  * Sets a texture stage state. Some stage types need to be handled specially,
4844  * because they do not exist in WineD3D and were moved to another place
4845  *
4846  * Version 3 and 7
4847  *
4848  * Params:
4849  *  Stage: The stage to modify
4850  *  TexStageStateType: The state to change
4851  *  State: The new value for the state
4852  *
4853  * Returns:
4854  *  D3D_OK on success
4855  *  For details, see IWineD3DDevice::SetTextureStageState
4856  *
4857  *****************************************************************************/
4858 static HRESULT
4859 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4860                                            DWORD Stage,
4861                                            D3DTEXTURESTAGESTATETYPE TexStageStateType,
4862                                            DWORD State)
4863 {
4864     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4865     const struct tss_lookup *l = &tss_lookup[TexStageStateType];
4866     HRESULT hr;
4867     TRACE("(%p)->(%08x,%08x,%08x): Relay!\n", This, Stage, TexStageStateType, State);
4868
4869     if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4870     {
4871         WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4872         return DD_OK;
4873     }
4874
4875     EnterCriticalSection(&ddraw_cs);
4876
4877     if (l->sampler_state)
4878     {
4879         switch(TexStageStateType)
4880         {
4881             /* Mipfilter is a sampler state with different values */
4882             case D3DTSS_MIPFILTER:
4883             {
4884                 switch(State)
4885                 {
4886                     case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
4887                     case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
4888                     case 0: /* Unchecked */
4889                     case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
4890                     default:
4891                         ERR("Unexpected mipfilter value %d\n", State);
4892                         State = WINED3DTEXF_NONE;
4893                         break;
4894                 }
4895                 break;
4896             }
4897
4898             /* Magfilter has slightly different values */
4899             case D3DTSS_MAGFILTER:
4900             {
4901                 switch(State)
4902                 {
4903                     case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
4904                     case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
4905                     case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
4906                     case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
4907                     case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
4908                     default:
4909                         ERR("Unexpected d3d7 mag filter type %d\n", State);
4910                         State = WINED3DTEXF_POINT;
4911                         break;
4912                 }
4913                 break;
4914             }
4915
4916             case D3DTSS_ADDRESS:
4917                 IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, WINED3DSAMP_ADDRESSV, State);
4918                 break;
4919
4920             default:
4921                 break;
4922         }
4923
4924         hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, l->state, State);
4925     }
4926     else
4927     {
4928         hr = IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
4929     }
4930
4931     LeaveCriticalSection(&ddraw_cs);
4932     return hr;
4933 }
4934
4935 static HRESULT WINAPI
4936 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4937                                            DWORD Stage,
4938                                            D3DTEXTURESTAGESTATETYPE TexStageStateType,
4939                                            DWORD State)
4940 {
4941     return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4942 }
4943
4944 static HRESULT WINAPI
4945 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4946                                            DWORD Stage,
4947                                            D3DTEXTURESTAGESTATETYPE TexStageStateType,
4948                                            DWORD State)
4949 {
4950     HRESULT hr;
4951     WORD old_fpucw;
4952
4953     old_fpucw = d3d_fpu_setup();
4954     hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4955     set_fpu_control_word(old_fpucw);
4956
4957     return hr;
4958 }
4959
4960 static HRESULT WINAPI
4961 Thunk_IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
4962                                                  DWORD Stage,
4963                                                  D3DTEXTURESTAGESTATETYPE TexStageStateType,
4964                                                  DWORD State)
4965 {
4966     IDirect3DDeviceImpl *This = device_from_device3(iface);
4967     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, Stage, TexStageStateType, State);
4968     return IDirect3DDevice7_SetTextureStageState((IDirect3DDevice7 *)This, Stage, TexStageStateType, State);
4969 }
4970
4971 /*****************************************************************************
4972  * IDirect3DDevice7::ValidateDevice
4973  *
4974  * SDK: "Reports the device's ability to render the currently set
4975  * texture-blending operations in a single pass". Whatever that means
4976  * exactly...
4977  *
4978  * Version 3 and 7
4979  *
4980  * Params:
4981  *  NumPasses: Address to write the number of necessary passes for the
4982  *             desired effect to.
4983  *
4984  * Returns:
4985  *  D3D_OK on success
4986  *  See IWineD3DDevice::ValidateDevice for more details
4987  *
4988  *****************************************************************************/
4989 static HRESULT
4990 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
4991                                      DWORD *NumPasses)
4992 {
4993     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4994     HRESULT hr;
4995     TRACE("(%p)->(%p): Relay\n", This, NumPasses);
4996
4997     EnterCriticalSection(&ddraw_cs);
4998     hr = IWineD3DDevice_ValidateDevice(This->wineD3DDevice, NumPasses);
4999     LeaveCriticalSection(&ddraw_cs);
5000     return hr;
5001 }
5002
5003 static HRESULT WINAPI
5004 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
5005                                      DWORD *NumPasses)
5006 {
5007     return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5008 }
5009
5010 static HRESULT WINAPI
5011 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
5012                                      DWORD *NumPasses)
5013 {
5014     HRESULT hr;
5015     WORD old_fpucw;
5016
5017     old_fpucw = d3d_fpu_setup();
5018     hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5019     set_fpu_control_word(old_fpucw);
5020
5021     return hr;
5022 }
5023
5024 static HRESULT WINAPI
5025 Thunk_IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface,
5026                                            DWORD *Passes)
5027 {
5028     IDirect3DDeviceImpl *This = device_from_device3(iface);
5029     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Passes);
5030     return IDirect3DDevice7_ValidateDevice((IDirect3DDevice7 *)This, Passes);
5031 }
5032
5033 /*****************************************************************************
5034  * IDirect3DDevice7::Clear
5035  *
5036  * Fills the render target, the z buffer and the stencil buffer with a
5037  * clear color / value
5038  *
5039  * Version 7 only
5040  *
5041  * Params:
5042  *  Count: Number of rectangles in Rects must be 0 if Rects is NULL
5043  *  Rects: Rectangles to clear. If NULL, the whole surface is cleared
5044  *  Flags: Some flags, as usual
5045  *  Color: Clear color for the render target
5046  *  Z: Clear value for the Z buffer
5047  *  Stencil: Clear value to store in each stencil buffer entry
5048  *
5049  * Returns:
5050  *  D3D_OK on success
5051  *  For details, see IWineD3DDevice::Clear
5052  *
5053  *****************************************************************************/
5054 static HRESULT
5055 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
5056                             DWORD Count,
5057                             D3DRECT *Rects,
5058                             DWORD Flags,
5059                             D3DCOLOR Color,
5060                             D3DVALUE Z,
5061                             DWORD Stencil)
5062 {
5063     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5064     HRESULT hr;
5065     TRACE("(%p)->(%08x,%p,%08x,%08x,%f,%08x): Relay\n", This, Count, Rects, Flags, Color, Z, Stencil);
5066
5067     /* Note; D3DRECT is compatible with WINED3DRECT */
5068     EnterCriticalSection(&ddraw_cs);
5069     hr = IWineD3DDevice_Clear(This->wineD3DDevice, Count, (WINED3DRECT*) Rects, Flags, Color, Z, Stencil);
5070     LeaveCriticalSection(&ddraw_cs);
5071     return hr;
5072 }
5073
5074 static HRESULT WINAPI
5075 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5076                             DWORD Count,
5077                             D3DRECT *Rects,
5078                             DWORD Flags,
5079                             D3DCOLOR Color,
5080                             D3DVALUE Z,
5081                             DWORD Stencil)
5082 {
5083     return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5084 }
5085
5086 static HRESULT WINAPI
5087 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5088                             DWORD Count,
5089                             D3DRECT *Rects,
5090                             DWORD Flags,
5091                             D3DCOLOR Color,
5092                             D3DVALUE Z,
5093                             DWORD Stencil)
5094 {
5095     HRESULT hr;
5096     WORD old_fpucw;
5097
5098     old_fpucw = d3d_fpu_setup();
5099     hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5100     set_fpu_control_word(old_fpucw);
5101
5102     return hr;
5103 }
5104
5105 /*****************************************************************************
5106  * IDirect3DDevice7::SetViewport
5107  *
5108  * Sets the current viewport.
5109  *
5110  * Version 7 only, but IDirect3DViewport uses this call for older
5111  * versions
5112  *
5113  * Params:
5114  *  Data: The new viewport to set
5115  *
5116  * Returns:
5117  *  D3D_OK on success
5118  *  DDERR_INVALIDPARAMS if Data is NULL
5119  *  For more details, see IWineDDDevice::SetViewport
5120  *
5121  *****************************************************************************/
5122 static HRESULT
5123 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5124                                   D3DVIEWPORT7 *Data)
5125 {
5126     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5127     HRESULT hr;
5128     TRACE("(%p)->(%p) Relay!\n", This, Data);
5129
5130     if(!Data)
5131         return DDERR_INVALIDPARAMS;
5132
5133     /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5134     EnterCriticalSection(&ddraw_cs);
5135     hr = IWineD3DDevice_SetViewport(This->wineD3DDevice,
5136                                     (WINED3DVIEWPORT*) Data);
5137     LeaveCriticalSection(&ddraw_cs);
5138     return hr;
5139 }
5140
5141 static HRESULT WINAPI
5142 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5143                                   D3DVIEWPORT7 *Data)
5144 {
5145     return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5146 }
5147
5148 static HRESULT WINAPI
5149 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5150                                   D3DVIEWPORT7 *Data)
5151 {
5152     HRESULT hr;
5153     WORD old_fpucw;
5154
5155     old_fpucw = d3d_fpu_setup();
5156     hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5157     set_fpu_control_word(old_fpucw);
5158
5159     return hr;
5160 }
5161
5162 /*****************************************************************************
5163  * IDirect3DDevice::GetViewport
5164  *
5165  * Returns the current viewport
5166  *
5167  * Version 7
5168  *
5169  * Params:
5170  *  Data: D3D7Viewport structure to write the viewport information to
5171  *
5172  * Returns:
5173  *  D3D_OK on success
5174  *  DDERR_INVALIDPARAMS if Data is NULL
5175  *  For more details, see IWineD3DDevice::GetViewport
5176  *
5177  *****************************************************************************/
5178 static HRESULT
5179 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5180                                   D3DVIEWPORT7 *Data)
5181 {
5182     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5183     HRESULT hr;
5184     TRACE("(%p)->(%p) Relay!\n", This, Data);
5185
5186     if(!Data)
5187         return DDERR_INVALIDPARAMS;
5188
5189     /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5190     EnterCriticalSection(&ddraw_cs);
5191     hr = IWineD3DDevice_GetViewport(This->wineD3DDevice,
5192                                     (WINED3DVIEWPORT*) Data);
5193
5194     LeaveCriticalSection(&ddraw_cs);
5195     return hr_ddraw_from_wined3d(hr);
5196 }
5197
5198 static HRESULT WINAPI
5199 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5200                                   D3DVIEWPORT7 *Data)
5201 {
5202     return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5203 }
5204
5205 static HRESULT WINAPI
5206 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5207                                   D3DVIEWPORT7 *Data)
5208 {
5209     HRESULT hr;
5210     WORD old_fpucw;
5211
5212     old_fpucw = d3d_fpu_setup();
5213     hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5214     set_fpu_control_word(old_fpucw);
5215
5216     return hr;
5217 }
5218
5219 /*****************************************************************************
5220  * IDirect3DDevice7::SetMaterial
5221  *
5222  * Sets the Material
5223  *
5224  * Version 7
5225  *
5226  * Params:
5227  *  Mat: The material to set
5228  *
5229  * Returns:
5230  *  D3D_OK on success
5231  *  DDERR_INVALIDPARAMS if Mat is NULL.
5232  *  For more details, see IWineD3DDevice::SetMaterial
5233  *
5234  *****************************************************************************/
5235 static HRESULT
5236 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5237                                   D3DMATERIAL7 *Mat)
5238 {
5239     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5240     HRESULT hr;
5241     TRACE("(%p)->(%p): Relay!\n", This, Mat);
5242
5243     if (!Mat) return DDERR_INVALIDPARAMS;
5244     /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5245     EnterCriticalSection(&ddraw_cs);
5246     hr = IWineD3DDevice_SetMaterial(This->wineD3DDevice,
5247                                     (WINED3DMATERIAL*) Mat);
5248     LeaveCriticalSection(&ddraw_cs);
5249     return hr_ddraw_from_wined3d(hr);
5250 }
5251
5252 static HRESULT WINAPI
5253 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5254                                   D3DMATERIAL7 *Mat)
5255 {
5256     return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5257 }
5258
5259 static HRESULT WINAPI
5260 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5261                                   D3DMATERIAL7 *Mat)
5262 {
5263     HRESULT hr;
5264     WORD old_fpucw;
5265
5266     old_fpucw = d3d_fpu_setup();
5267     hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5268     set_fpu_control_word(old_fpucw);
5269
5270     return hr;
5271 }
5272
5273 /*****************************************************************************
5274  * IDirect3DDevice7::GetMaterial
5275  *
5276  * Returns the current material
5277  *
5278  * Version 7
5279  *
5280  * Params:
5281  *  Mat: D3DMATERIAL7 structure to write the material parameters to
5282  *
5283  * Returns:
5284  *  D3D_OK on success
5285  *  DDERR_INVALIDPARAMS if Mat is NULL
5286  *  For more details, see IWineD3DDevice::GetMaterial
5287  *
5288  *****************************************************************************/
5289 static HRESULT
5290 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5291                                   D3DMATERIAL7 *Mat)
5292 {
5293     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5294     HRESULT hr;
5295     TRACE("(%p)->(%p): Relay!\n", This, Mat);
5296
5297     EnterCriticalSection(&ddraw_cs);
5298     /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5299     hr = IWineD3DDevice_GetMaterial(This->wineD3DDevice,
5300                                     (WINED3DMATERIAL*) Mat);
5301     LeaveCriticalSection(&ddraw_cs);
5302     return hr_ddraw_from_wined3d(hr);
5303 }
5304
5305 static HRESULT WINAPI
5306 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5307                                   D3DMATERIAL7 *Mat)
5308 {
5309     return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5310 }
5311
5312 static HRESULT WINAPI
5313 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5314                                   D3DMATERIAL7 *Mat)
5315 {
5316     HRESULT hr;
5317     WORD old_fpucw;
5318
5319     old_fpucw = d3d_fpu_setup();
5320     hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5321     set_fpu_control_word(old_fpucw);
5322
5323     return hr;
5324 }
5325
5326 /*****************************************************************************
5327  * IDirect3DDevice7::SetLight
5328  *
5329  * Assigns a light to a light index, but doesn't activate it yet.
5330  *
5331  * Version 7, IDirect3DLight uses this method for older versions
5332  *
5333  * Params:
5334  *  LightIndex: The index of the new light
5335  *  Light: A D3DLIGHT7 structure describing the light
5336  *
5337  * Returns:
5338  *  D3D_OK on success
5339  *  For more details, see IWineD3DDevice::SetLight
5340  *
5341  *****************************************************************************/
5342 static HRESULT
5343 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5344                                DWORD LightIndex,
5345                                D3DLIGHT7 *Light)
5346 {
5347     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5348     HRESULT hr;
5349     TRACE("(%p)->(%08x,%p): Relay!\n", This, LightIndex, Light);
5350
5351     EnterCriticalSection(&ddraw_cs);
5352     /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5353     hr = IWineD3DDevice_SetLight(This->wineD3DDevice,
5354                                  LightIndex,
5355                                  (WINED3DLIGHT*) Light);
5356     LeaveCriticalSection(&ddraw_cs);
5357     return hr_ddraw_from_wined3d(hr);
5358 }
5359
5360 static HRESULT WINAPI
5361 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5362                                DWORD LightIndex,
5363                                D3DLIGHT7 *Light)
5364 {
5365     return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5366 }
5367
5368 static HRESULT WINAPI
5369 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5370                                DWORD LightIndex,
5371                                D3DLIGHT7 *Light)
5372 {
5373     HRESULT hr;
5374     WORD old_fpucw;
5375
5376     old_fpucw = d3d_fpu_setup();
5377     hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5378     set_fpu_control_word(old_fpucw);
5379
5380     return hr;
5381 }
5382
5383 /*****************************************************************************
5384  * IDirect3DDevice7::GetLight
5385  *
5386  * Returns the light assigned to a light index
5387  *
5388  * Params:
5389  *  Light: Structure to write the light information to
5390  *
5391  * Returns:
5392  *  D3D_OK on success
5393  *  DDERR_INVALIDPARAMS if Light is NULL
5394  *  For details, see IWineD3DDevice::GetLight
5395  *
5396  *****************************************************************************/
5397 static HRESULT
5398 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5399                                DWORD LightIndex,
5400                                D3DLIGHT7 *Light)
5401 {
5402     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5403     HRESULT rc;
5404     TRACE("(%p)->(%08x,%p): Relay!\n", This, LightIndex, Light);
5405
5406     EnterCriticalSection(&ddraw_cs);
5407     /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5408     rc =  IWineD3DDevice_GetLight(This->wineD3DDevice,
5409                                   LightIndex,
5410                                   (WINED3DLIGHT*) Light);
5411
5412     /* Translate the result. WineD3D returns other values than D3D7 */
5413     LeaveCriticalSection(&ddraw_cs);
5414     return hr_ddraw_from_wined3d(rc);
5415 }
5416
5417 static HRESULT WINAPI
5418 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5419                                DWORD LightIndex,
5420                                D3DLIGHT7 *Light)
5421 {
5422     return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5423 }
5424
5425 static HRESULT WINAPI
5426 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5427                                DWORD LightIndex,
5428                                D3DLIGHT7 *Light)
5429 {
5430     HRESULT hr;
5431     WORD old_fpucw;
5432
5433     old_fpucw = d3d_fpu_setup();
5434     hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5435     set_fpu_control_word(old_fpucw);
5436
5437     return hr;
5438 }
5439
5440 /*****************************************************************************
5441  * IDirect3DDevice7::BeginStateBlock
5442  *
5443  * Begins recording to a stateblock
5444  *
5445  * Version 7
5446  *
5447  * Returns:
5448  *  D3D_OK on success
5449  *  For details see IWineD3DDevice::BeginStateBlock
5450  *
5451  *****************************************************************************/
5452 static HRESULT
5453 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5454 {
5455     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5456     HRESULT hr;
5457     TRACE("(%p)->(): Relay!\n", This);
5458
5459     EnterCriticalSection(&ddraw_cs);
5460     hr = IWineD3DDevice_BeginStateBlock(This->wineD3DDevice);
5461     LeaveCriticalSection(&ddraw_cs);
5462     return hr_ddraw_from_wined3d(hr);
5463 }
5464
5465 static HRESULT WINAPI
5466 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5467 {
5468     return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5469 }
5470
5471 static HRESULT WINAPI
5472 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5473 {
5474     HRESULT hr;
5475     WORD old_fpucw;
5476
5477     old_fpucw = d3d_fpu_setup();
5478     hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5479     set_fpu_control_word(old_fpucw);
5480
5481     return hr;
5482 }
5483
5484 /*****************************************************************************
5485  * IDirect3DDevice7::EndStateBlock
5486  *
5487  * Stops recording to a state block and returns the created stateblock
5488  * handle.
5489  *
5490  * Version 7
5491  *
5492  * Params:
5493  *  BlockHandle: Address to store the stateblock's handle to
5494  *
5495  * Returns:
5496  *  D3D_OK on success
5497  *  DDERR_INVALIDPARAMS if BlockHandle is NULL
5498  *  See IWineD3DDevice::EndStateBlock for more details
5499  *
5500  *****************************************************************************/
5501 static HRESULT
5502 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5503                                     DWORD *BlockHandle)
5504 {
5505     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5506     HRESULT hr;
5507     TRACE("(%p)->(%p): Relay!\n", This, BlockHandle);
5508
5509     if(!BlockHandle)
5510     {
5511         WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5512         return DDERR_INVALIDPARAMS;
5513     }
5514
5515     EnterCriticalSection(&ddraw_cs);
5516     *BlockHandle = IDirect3DDeviceImpl_CreateHandle(This);
5517     if(!*BlockHandle)
5518     {
5519         ERR("Cannot get a handle number for the stateblock\n");
5520         LeaveCriticalSection(&ddraw_cs);
5521         return DDERR_OUTOFMEMORY;
5522     }
5523     This->Handles[*BlockHandle - 1].type = DDrawHandle_StateBlock;
5524     hr = IWineD3DDevice_EndStateBlock(This->wineD3DDevice,
5525                                       (IWineD3DStateBlock **) &This->Handles[*BlockHandle - 1].ptr);
5526     LeaveCriticalSection(&ddraw_cs);
5527     return hr_ddraw_from_wined3d(hr);
5528 }
5529
5530 static HRESULT WINAPI
5531 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5532                                     DWORD *BlockHandle)
5533 {
5534     return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5535 }
5536
5537 static HRESULT WINAPI
5538 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5539                                     DWORD *BlockHandle)
5540 {
5541     HRESULT hr;
5542     WORD old_fpucw;
5543
5544     old_fpucw = d3d_fpu_setup();
5545     hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5546     set_fpu_control_word(old_fpucw);
5547
5548     return hr;
5549 }
5550
5551 /*****************************************************************************
5552  * IDirect3DDevice7::PreLoad
5553  *
5554  * Allows the app to signal that a texture will be used soon, to allow
5555  * the Direct3DDevice to load it to the video card in the meantime.
5556  *
5557  * Version 7
5558  *
5559  * Params:
5560  *  Texture: The texture to preload
5561  *
5562  * Returns:
5563  *  D3D_OK on success
5564  *  DDERR_INVALIDPARAMS if Texture is NULL
5565  *  See IWineD3DSurface::PreLoad for details
5566  *
5567  *****************************************************************************/
5568 static HRESULT
5569 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5570                               IDirectDrawSurface7 *Texture)
5571 {
5572     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5573     IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
5574
5575     TRACE("(%p)->(%p): Relay!\n", This, surf);
5576
5577     if(!Texture)
5578         return DDERR_INVALIDPARAMS;
5579
5580     EnterCriticalSection(&ddraw_cs);
5581     IWineD3DSurface_PreLoad(surf->WineD3DSurface);
5582     LeaveCriticalSection(&ddraw_cs);
5583     return D3D_OK;
5584 }
5585
5586 static HRESULT WINAPI
5587 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5588                               IDirectDrawSurface7 *Texture)
5589 {
5590     return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5591 }
5592
5593 static HRESULT WINAPI
5594 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5595                               IDirectDrawSurface7 *Texture)
5596 {
5597     HRESULT hr;
5598     WORD old_fpucw;
5599
5600     old_fpucw = d3d_fpu_setup();
5601     hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5602     set_fpu_control_word(old_fpucw);
5603
5604     return hr;
5605 }
5606
5607 /*****************************************************************************
5608  * IDirect3DDevice7::ApplyStateBlock
5609  *
5610  * Activates the state stored in a state block handle.
5611  *
5612  * Params:
5613  *  BlockHandle: The stateblock handle to activate
5614  *
5615  * Returns:
5616  *  D3D_OK on success
5617  *  D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5618  *
5619  *****************************************************************************/
5620 static HRESULT
5621 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5622                                       DWORD BlockHandle)
5623 {
5624     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5625     HRESULT hr;
5626     TRACE("(%p)->(%08x): Relay!\n", This, BlockHandle);
5627
5628     EnterCriticalSection(&ddraw_cs);
5629     if(!BlockHandle || BlockHandle > This->numHandles)
5630     {
5631         WARN("Out of range handle %d, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5632         LeaveCriticalSection(&ddraw_cs);
5633         return D3DERR_INVALIDSTATEBLOCK;
5634     }
5635     if(This->Handles[BlockHandle - 1].type != DDrawHandle_StateBlock)
5636     {
5637         WARN("Handle %d is not a stateblock, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5638         LeaveCriticalSection(&ddraw_cs);
5639         return D3DERR_INVALIDSTATEBLOCK;
5640     }
5641
5642     hr = IWineD3DStateBlock_Apply((IWineD3DStateBlock *) This->Handles[BlockHandle - 1].ptr);
5643     LeaveCriticalSection(&ddraw_cs);
5644     return hr_ddraw_from_wined3d(hr);
5645 }
5646
5647 static HRESULT WINAPI
5648 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5649                                       DWORD BlockHandle)
5650 {
5651     return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5652 }
5653
5654 static HRESULT WINAPI
5655 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5656                                       DWORD BlockHandle)
5657 {
5658     HRESULT hr;
5659     WORD old_fpucw;
5660
5661     old_fpucw = d3d_fpu_setup();
5662     hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5663     set_fpu_control_word(old_fpucw);
5664
5665     return hr;
5666 }
5667
5668 /*****************************************************************************
5669  * IDirect3DDevice7::CaptureStateBlock
5670  *
5671  * Updates a stateblock's values to the values currently set for the device
5672  *
5673  * Version 7
5674  *
5675  * Params:
5676  *  BlockHandle: Stateblock to update
5677  *
5678  * Returns:
5679  *  D3D_OK on success
5680  *  D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5681  *  See IWineD3DDevice::CaptureStateBlock for more details
5682  *
5683  *****************************************************************************/
5684 static HRESULT
5685 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5686                                         DWORD BlockHandle)
5687 {
5688     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5689     HRESULT hr;
5690     TRACE("(%p)->(%08x): Relay!\n", This, BlockHandle);
5691
5692     EnterCriticalSection(&ddraw_cs);
5693     if(BlockHandle == 0 || BlockHandle > This->numHandles)
5694     {
5695         WARN("Out of range handle %d, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5696         LeaveCriticalSection(&ddraw_cs);
5697         return D3DERR_INVALIDSTATEBLOCK;
5698     }
5699     if(This->Handles[BlockHandle - 1].type != DDrawHandle_StateBlock)
5700     {
5701         WARN("Handle %d is not a stateblock, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5702         LeaveCriticalSection(&ddraw_cs);
5703         return D3DERR_INVALIDSTATEBLOCK;
5704     }
5705
5706     hr = IWineD3DStateBlock_Capture((IWineD3DStateBlock *) This->Handles[BlockHandle - 1].ptr);
5707     LeaveCriticalSection(&ddraw_cs);
5708     return hr_ddraw_from_wined3d(hr);
5709 }
5710
5711 static HRESULT WINAPI
5712 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5713                                         DWORD BlockHandle)
5714 {
5715     return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5716 }
5717
5718 static HRESULT WINAPI
5719 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5720                                         DWORD BlockHandle)
5721 {
5722     HRESULT hr;
5723     WORD old_fpucw;
5724
5725     old_fpucw = d3d_fpu_setup();
5726     hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5727     set_fpu_control_word(old_fpucw);
5728
5729     return hr;
5730 }
5731
5732 /*****************************************************************************
5733  * IDirect3DDevice7::DeleteStateBlock
5734  *
5735  * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5736  *
5737  * Version 7
5738  *
5739  * Params:
5740  *  BlockHandle: Stateblock handle to delete
5741  *
5742  * Returns:
5743  *  D3D_OK on success
5744  *  D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5745  *
5746  *****************************************************************************/
5747 static HRESULT
5748 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5749                                        DWORD BlockHandle)
5750 {
5751     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5752     ULONG ref;
5753     TRACE("(%p)->(%08x): Relay!\n", This, BlockHandle);
5754
5755     EnterCriticalSection(&ddraw_cs);
5756     if(BlockHandle == 0 || BlockHandle > This->numHandles)
5757     {
5758         WARN("Out of range handle %d, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5759         LeaveCriticalSection(&ddraw_cs);
5760         return D3DERR_INVALIDSTATEBLOCK;
5761     }
5762     if(This->Handles[BlockHandle - 1].type != DDrawHandle_StateBlock)
5763     {
5764         WARN("Handle %d is not a stateblock, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5765         LeaveCriticalSection(&ddraw_cs);
5766         return D3DERR_INVALIDSTATEBLOCK;
5767     }
5768
5769     ref = IWineD3DStateBlock_Release((IWineD3DStateBlock *) This->Handles[BlockHandle - 1].ptr);
5770     if(ref)
5771     {
5772         ERR("Something is still holding the stateblock %p(Handle %d). Ref = %d\n", This->Handles[BlockHandle - 1].ptr, BlockHandle, ref);
5773     }
5774     This->Handles[BlockHandle - 1].ptr = NULL;
5775     This->Handles[BlockHandle - 1].type = DDrawHandle_Unknown;
5776
5777     LeaveCriticalSection(&ddraw_cs);
5778     return D3D_OK;
5779 }
5780
5781 static HRESULT WINAPI
5782 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5783                                        DWORD BlockHandle)
5784 {
5785     return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5786 }
5787
5788 static HRESULT WINAPI
5789 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5790                                        DWORD BlockHandle)
5791 {
5792     HRESULT hr;
5793     WORD old_fpucw;
5794
5795     old_fpucw = d3d_fpu_setup();
5796     hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5797     set_fpu_control_word(old_fpucw);
5798
5799     return hr;
5800 }
5801
5802 /*****************************************************************************
5803  * IDirect3DDevice7::CreateStateBlock
5804  *
5805  * Creates a new state block handle.
5806  *
5807  * Version 7
5808  *
5809  * Params:
5810  *  Type: The state block type
5811  *  BlockHandle: Address to write the created handle to
5812  *
5813  * Returns:
5814  *   D3D_OK on success
5815  *   DDERR_INVALIDPARAMS if BlockHandle is NULL
5816  *
5817  *****************************************************************************/
5818 static HRESULT
5819 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5820                                        D3DSTATEBLOCKTYPE Type,
5821                                        DWORD *BlockHandle)
5822 {
5823     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5824     HRESULT hr;
5825     TRACE("(%p)->(%08x,%p)!\n", This, Type, BlockHandle);
5826
5827     if(!BlockHandle)
5828     {
5829         WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5830         return DDERR_INVALIDPARAMS;
5831     }
5832     if(Type != D3DSBT_ALL         && Type != D3DSBT_PIXELSTATE &&
5833        Type != D3DSBT_VERTEXSTATE                              ) {
5834         WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5835         return DDERR_INVALIDPARAMS;
5836     }
5837
5838     EnterCriticalSection(&ddraw_cs);
5839     *BlockHandle = IDirect3DDeviceImpl_CreateHandle(This);
5840     if(!*BlockHandle)
5841     {
5842         ERR("Cannot get a handle number for the stateblock\n");
5843         LeaveCriticalSection(&ddraw_cs);
5844         return DDERR_OUTOFMEMORY;
5845     }
5846     This->Handles[*BlockHandle - 1].type = DDrawHandle_StateBlock;
5847
5848     /* The D3DSTATEBLOCKTYPE enum is fine here */
5849     hr = IWineD3DDevice_CreateStateBlock(This->wineD3DDevice,
5850                                          Type,
5851                                          (IWineD3DStateBlock **) &This->Handles[*BlockHandle - 1].ptr,
5852                                          NULL /* Parent, hope that works */);
5853     LeaveCriticalSection(&ddraw_cs);
5854     return hr_ddraw_from_wined3d(hr);
5855 }
5856
5857 static HRESULT WINAPI
5858 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5859                                        D3DSTATEBLOCKTYPE Type,
5860                                        DWORD *BlockHandle)
5861 {
5862     return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5863 }
5864
5865 static HRESULT WINAPI
5866 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5867                                        D3DSTATEBLOCKTYPE Type,
5868                                        DWORD *BlockHandle)
5869 {
5870     HRESULT hr;
5871     WORD old_fpucw;
5872
5873     old_fpucw = d3d_fpu_setup();
5874     hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5875     set_fpu_control_word(old_fpucw);
5876
5877     return hr;
5878 }
5879
5880 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5881 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
5882                                 IDirectDrawSurfaceImpl *src)
5883 {
5884     IDirectDrawSurfaceImpl *src_level, *dest_level;
5885     IDirectDrawSurface7 *temp;
5886     DDSURFACEDESC2 ddsd;
5887     BOOL levelFound; /* at least one suitable sublevel in dest found */
5888
5889     /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5890      * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5891      * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5892      */
5893     levelFound = FALSE;
5894
5895     src_level = src;
5896     dest_level = dest;
5897
5898     for (;src_level && dest_level;)
5899     {
5900         if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5901             src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5902         {
5903             levelFound = TRUE;
5904
5905             ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5906             ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5907             IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
5908
5909             if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5910
5911             dest_level = (IDirectDrawSurfaceImpl *)temp;
5912         }
5913
5914         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5915         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5916         IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
5917
5918         if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5919
5920         src_level = (IDirectDrawSurfaceImpl *)temp;
5921     }
5922
5923     if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5924     if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5925
5926     return !dest_level && levelFound;
5927 }
5928
5929 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5930 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
5931                               IDirectDrawSurfaceImpl *dest,
5932                               IDirectDrawSurfaceImpl *src,
5933                               const POINT *DestPoint,
5934                               const RECT *SrcRect)
5935 {
5936     IDirectDrawSurfaceImpl *src_level, *dest_level;
5937     IDirectDrawSurface7 *temp;
5938     DDSURFACEDESC2 ddsd;
5939     POINT point;
5940     RECT rect;
5941     HRESULT hr;
5942     IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5943     DWORD ckeyflag;
5944     DDCOLORKEY ddckey;
5945     BOOL palette_missing = FALSE;
5946
5947     /* Copy palette, if possible. */
5948     IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)src, &pal_src);
5949     IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)dest, &pal);
5950
5951     if (pal_src != NULL && pal != NULL)
5952     {
5953         PALETTEENTRY palent[256];
5954
5955         IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5956         IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5957     }
5958
5959     if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
5960             DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
5961     {
5962         palette_missing = TRUE;
5963     }
5964
5965     if (pal) IDirectDrawPalette_Release(pal);
5966     if (pal_src) IDirectDrawPalette_Release(pal_src);
5967
5968     /* Copy colorkeys, if present. */
5969     for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5970     {
5971         hr = IDirectDrawSurface7_GetColorKey((IDirectDrawSurface7 *)src, ckeyflag, &ddckey);
5972
5973         if (SUCCEEDED(hr))
5974         {
5975             IDirectDrawSurface7_SetColorKey((IDirectDrawSurface7 *)dest, ckeyflag, &ddckey);
5976         }
5977     }
5978
5979     src_level = src;
5980     dest_level = dest;
5981
5982     point = *DestPoint;
5983     rect = *SrcRect;
5984
5985     for (;src_level && dest_level;)
5986     {
5987         if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5988             src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5989         {
5990             /* Try UpdateSurface that may perform a more direct opengl loading. But skip this if destination is paletted texture and has no palette.
5991              * Some games like Sacrifice set palette after Load, and it is a waste of effort to try to load texture without palette and generates
5992              * warnings in wined3d. */
5993             if (!palette_missing)
5994                 hr = IWineD3DDevice_UpdateSurface(device->wineD3DDevice, src_level->WineD3DSurface, &rect, dest_level->WineD3DSurface,
5995                                 &point);
5996
5997             if (palette_missing || FAILED(hr))
5998             {
5999                 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
6000                 IWineD3DSurface_BltFast(dest_level->WineD3DSurface,
6001                                         point.x, point.y,
6002                                         src_level->WineD3DSurface, &rect, 0);
6003             }
6004
6005             ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6006             ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6007             IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
6008
6009             if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6010
6011             dest_level = (IDirectDrawSurfaceImpl *)temp;
6012         }
6013
6014         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6015         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6016         IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
6017
6018         if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6019
6020         src_level = (IDirectDrawSurfaceImpl *)temp;
6021
6022         point.x /= 2;
6023         point.y /= 2;
6024
6025         rect.top /= 2;
6026         rect.left /= 2;
6027         rect.right = (rect.right + 1) / 2;
6028         rect.bottom = (rect.bottom + 1) / 2;
6029     }
6030
6031     if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6032     if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6033 }
6034
6035 /*****************************************************************************
6036  * IDirect3DDevice7::Load
6037  *
6038  * Loads a rectangular area from the source into the destination texture.
6039  * It can also copy the source to the faces of a cubic environment map
6040  *
6041  * Version 7
6042  *
6043  * Params:
6044  *  DestTex: Destination texture
6045  *  DestPoint: Point in the destination where the source image should be
6046  *             written to
6047  *  SrcTex: Source texture
6048  *  SrcRect: Source rectangle
6049  *  Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6050  *          DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6051  *          DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6052  *
6053  * Returns:
6054  *  D3D_OK on success
6055  *  DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6056  *
6057  *
6058  *****************************************************************************/
6059
6060 static HRESULT
6061 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6062                            IDirectDrawSurface7 *DestTex,
6063                            POINT *DestPoint,
6064                            IDirectDrawSurface7 *SrcTex,
6065                            RECT *SrcRect,
6066                            DWORD Flags)
6067 {
6068     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6069     IDirectDrawSurfaceImpl *dest = (IDirectDrawSurfaceImpl *)DestTex;
6070     IDirectDrawSurfaceImpl *src = (IDirectDrawSurfaceImpl *)SrcTex;
6071     POINT destpoint;
6072     RECT srcrect;
6073     TRACE("(%p)->(%p,%p,%p,%p,%08x)\n", This, dest, DestPoint, src, SrcRect, Flags);
6074
6075     if( (!src) || (!dest) )
6076         return DDERR_INVALIDPARAMS;
6077
6078     EnterCriticalSection(&ddraw_cs);
6079
6080     if (SrcRect) srcrect = *SrcRect;
6081     else
6082     {
6083         srcrect.left = srcrect.top = 0;
6084         srcrect.right = src->surface_desc.dwWidth;
6085         srcrect.bottom = src->surface_desc.dwHeight;
6086     }
6087
6088     if (DestPoint) destpoint = *DestPoint;
6089     else
6090     {
6091         destpoint.x = destpoint.y = 0;
6092     }
6093     /* Check bad dimensions. DestPoint is validated against src, not dest, because
6094      * destination can be a subset of mip levels, in which case actual coordinates used
6095      * for it may be divided. If any dimension of dest is larger than source, it can't be
6096      * mip level subset, so an error can be returned early.
6097      */
6098     if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6099         srcrect.right > src->surface_desc.dwWidth ||
6100         srcrect.bottom > src->surface_desc.dwHeight ||
6101         destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6102         destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6103         dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6104         dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6105     {
6106         LeaveCriticalSection(&ddraw_cs);
6107         return DDERR_INVALIDPARAMS;
6108     }
6109
6110     /* Must be top level surfaces. */
6111     if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6112         dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6113     {
6114         LeaveCriticalSection(&ddraw_cs);
6115         return DDERR_INVALIDPARAMS;
6116     }
6117
6118     if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6119     {
6120         DWORD src_face_flag, dest_face_flag;
6121         IDirectDrawSurfaceImpl *src_face, *dest_face;
6122         IDirectDrawSurface7 *temp;
6123         DDSURFACEDESC2 ddsd;
6124         int i;
6125
6126         if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6127         {
6128             LeaveCriticalSection(&ddraw_cs);
6129             return DDERR_INVALIDPARAMS;
6130         }
6131
6132         /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6133          * time it's actual surface loading. */
6134         for (i = 0; i < 2; i++)
6135         {
6136             dest_face = dest;
6137             src_face = src;
6138
6139             for (;dest_face && src_face;)
6140             {
6141                 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6142                 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6143
6144                 if (src_face_flag == dest_face_flag)
6145                 {
6146                     if (i == 0)
6147                     {
6148                         /* Destination mip levels must be subset of source mip levels. */
6149                         if (!is_mip_level_subset(dest_face, src_face))
6150                         {
6151                             LeaveCriticalSection(&ddraw_cs);
6152                             return DDERR_INVALIDPARAMS;
6153                         }
6154                     }
6155                     else if (Flags & dest_face_flag)
6156                     {
6157                         copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6158                     }
6159
6160                     if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6161                     {
6162                         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6163                         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6164                         IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src, &ddsd.ddsCaps, &temp);
6165
6166                         if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6167
6168                         src_face = (IDirectDrawSurfaceImpl *)temp;
6169                     }
6170                     else
6171                     {
6172                         if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6173
6174                         src_face = NULL;
6175                     }
6176                 }
6177
6178                 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6179                 {
6180                     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6181                     ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6182                     IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest, &ddsd.ddsCaps, &temp);
6183
6184                     if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6185
6186                     dest_face = (IDirectDrawSurfaceImpl *)temp;
6187                 }
6188                 else
6189                 {
6190                     if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6191
6192                     dest_face = NULL;
6193                 }
6194             }
6195
6196             if (i == 0)
6197             {
6198                 /* Native returns error if src faces are not subset of dest faces. */
6199                 if (src_face)
6200                 {
6201                     LeaveCriticalSection(&ddraw_cs);
6202                     return DDERR_INVALIDPARAMS;
6203                 }
6204             }
6205         }
6206
6207         LeaveCriticalSection(&ddraw_cs);
6208         return D3D_OK;
6209     }
6210     else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6211     {
6212         LeaveCriticalSection(&ddraw_cs);
6213         return DDERR_INVALIDPARAMS;
6214     }
6215
6216     /* Handle non cube map textures. */
6217
6218     /* Destination mip levels must be subset of source mip levels. */
6219     if (!is_mip_level_subset(dest, src))
6220     {
6221         LeaveCriticalSection(&ddraw_cs);
6222         return DDERR_INVALIDPARAMS;
6223     }
6224
6225     copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6226
6227     LeaveCriticalSection(&ddraw_cs);
6228     return D3D_OK;
6229 }
6230
6231 static HRESULT WINAPI
6232 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6233                            IDirectDrawSurface7 *DestTex,
6234                            POINT *DestPoint,
6235                            IDirectDrawSurface7 *SrcTex,
6236                            RECT *SrcRect,
6237                            DWORD Flags)
6238 {
6239     return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6240 }
6241
6242 static HRESULT WINAPI
6243 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6244                            IDirectDrawSurface7 *DestTex,
6245                            POINT *DestPoint,
6246                            IDirectDrawSurface7 *SrcTex,
6247                            RECT *SrcRect,
6248                            DWORD Flags)
6249 {
6250     HRESULT hr;
6251     WORD old_fpucw;
6252
6253     old_fpucw = d3d_fpu_setup();
6254     hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6255     set_fpu_control_word(old_fpucw);
6256
6257     return hr;
6258 }
6259
6260 /*****************************************************************************
6261  * IDirect3DDevice7::LightEnable
6262  *
6263  * Enables or disables a light
6264  *
6265  * Version 7, IDirect3DLight uses this method too.
6266  *
6267  * Params:
6268  *  LightIndex: The index of the light to enable / disable
6269  *  Enable: Enable or disable the light
6270  *
6271  * Returns:
6272  *  D3D_OK on success
6273  *  For more details, see IWineD3DDevice::SetLightEnable
6274  *
6275  *****************************************************************************/
6276 static HRESULT
6277 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6278                                   DWORD LightIndex,
6279                                   BOOL Enable)
6280 {
6281     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6282     HRESULT hr;
6283     TRACE("(%p)->(%08x,%d): Relay!\n", This, LightIndex, Enable);
6284
6285     EnterCriticalSection(&ddraw_cs);
6286     hr = IWineD3DDevice_SetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6287     LeaveCriticalSection(&ddraw_cs);
6288     return hr_ddraw_from_wined3d(hr);
6289 }
6290
6291 static HRESULT WINAPI
6292 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6293                                   DWORD LightIndex,
6294                                   BOOL Enable)
6295 {
6296     return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6297 }
6298
6299 static HRESULT WINAPI
6300 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6301                                   DWORD LightIndex,
6302                                   BOOL Enable)
6303 {
6304     HRESULT hr;
6305     WORD old_fpucw;
6306
6307     old_fpucw = d3d_fpu_setup();
6308     hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6309     set_fpu_control_word(old_fpucw);
6310
6311     return hr;
6312 }
6313
6314 /*****************************************************************************
6315  * IDirect3DDevice7::GetLightEnable
6316  *
6317  * Retrieves if the light with the given index is enabled or not
6318  *
6319  * Version 7
6320  *
6321  * Params:
6322  *  LightIndex: Index of desired light
6323  *  Enable: Pointer to a BOOL which contains the result
6324  *
6325  * Returns:
6326  *  D3D_OK on success
6327  *  DDERR_INVALIDPARAMS if Enable is NULL
6328  *  See IWineD3DDevice::GetLightEnable for more details
6329  *
6330  *****************************************************************************/
6331 static HRESULT
6332 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6333                                      DWORD LightIndex,
6334                                      BOOL* Enable)
6335 {
6336     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6337     HRESULT hr;
6338     TRACE("(%p)->(%08x,%p): Relay\n", This, LightIndex, Enable);
6339
6340     if(!Enable)
6341         return DDERR_INVALIDPARAMS;
6342
6343     EnterCriticalSection(&ddraw_cs);
6344     hr = IWineD3DDevice_GetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6345     LeaveCriticalSection(&ddraw_cs);
6346     return hr_ddraw_from_wined3d(hr);
6347 }
6348
6349 static HRESULT WINAPI
6350 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6351                                      DWORD LightIndex,
6352                                      BOOL* Enable)
6353 {
6354     return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6355 }
6356
6357 static HRESULT WINAPI
6358 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6359                                      DWORD LightIndex,
6360                                      BOOL* Enable)
6361 {
6362     HRESULT hr;
6363     WORD old_fpucw;
6364
6365     old_fpucw = d3d_fpu_setup();
6366     hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6367     set_fpu_control_word(old_fpucw);
6368
6369     return hr;
6370 }
6371
6372 /*****************************************************************************
6373  * IDirect3DDevice7::SetClipPlane
6374  *
6375  * Sets custom clipping plane
6376  *
6377  * Version 7
6378  *
6379  * Params:
6380  *  Index: The index of the clipping plane
6381  *  PlaneEquation: An equation defining the clipping plane
6382  *
6383  * Returns:
6384  *  D3D_OK on success
6385  *  DDERR_INVALIDPARAMS if PlaneEquation is NULL
6386  *  See IWineD3DDevice::SetClipPlane for more details
6387  *
6388  *****************************************************************************/
6389 static HRESULT
6390 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6391                                    DWORD Index,
6392                                    D3DVALUE* PlaneEquation)
6393 {
6394     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6395     HRESULT hr;
6396     TRACE("(%p)->(%08x,%p): Relay!\n", This, Index, PlaneEquation);
6397
6398     if(!PlaneEquation)
6399         return DDERR_INVALIDPARAMS;
6400
6401     EnterCriticalSection(&ddraw_cs);
6402     hr = IWineD3DDevice_SetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6403     LeaveCriticalSection(&ddraw_cs);
6404     return hr;
6405 }
6406
6407 static HRESULT WINAPI
6408 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6409                                    DWORD Index,
6410                                    D3DVALUE* PlaneEquation)
6411 {
6412     return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6413 }
6414
6415 static HRESULT WINAPI
6416 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6417                                    DWORD Index,
6418                                    D3DVALUE* PlaneEquation)
6419 {
6420     HRESULT hr;
6421     WORD old_fpucw;
6422
6423     old_fpucw = d3d_fpu_setup();
6424     hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6425     set_fpu_control_word(old_fpucw);
6426
6427     return hr;
6428 }
6429
6430 /*****************************************************************************
6431  * IDirect3DDevice7::GetClipPlane
6432  *
6433  * Returns the clipping plane with a specific index
6434  *
6435  * Params:
6436  *  Index: The index of the desired plane
6437  *  PlaneEquation: Address to store the plane equation to
6438  *
6439  * Returns:
6440  *  D3D_OK on success
6441  *  DDERR_INVALIDPARAMS if PlaneEquation is NULL
6442  *  See IWineD3DDevice::GetClipPlane for more details
6443  *
6444  *****************************************************************************/
6445 static HRESULT
6446 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6447                                    DWORD Index,
6448                                    D3DVALUE* PlaneEquation)
6449 {
6450     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6451     HRESULT hr;
6452     TRACE("(%p)->(%d,%p): Relay!\n", This, Index, PlaneEquation);
6453
6454     if(!PlaneEquation)
6455         return DDERR_INVALIDPARAMS;
6456
6457     EnterCriticalSection(&ddraw_cs);
6458     hr = IWineD3DDevice_GetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6459     LeaveCriticalSection(&ddraw_cs);
6460     return hr;
6461 }
6462
6463 static HRESULT WINAPI
6464 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6465                                    DWORD Index,
6466                                    D3DVALUE* PlaneEquation)
6467 {
6468     return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6469 }
6470
6471 static HRESULT WINAPI
6472 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6473                                    DWORD Index,
6474                                    D3DVALUE* PlaneEquation)
6475 {
6476     HRESULT hr;
6477     WORD old_fpucw;
6478
6479     old_fpucw = d3d_fpu_setup();
6480     hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6481     set_fpu_control_word(old_fpucw);
6482
6483     return hr;
6484 }
6485
6486 /*****************************************************************************
6487  * IDirect3DDevice7::GetInfo
6488  *
6489  * Retrieves some information about the device. The DirectX sdk says that
6490  * this version returns S_FALSE for all retail builds of DirectX, that's what
6491  * this implementation does.
6492  *
6493  * Params:
6494  *  DevInfoID: Information type requested
6495  *  DevInfoStruct: Pointer to a structure to store the info to
6496  *  Size: Size of the structure
6497  *
6498  * Returns:
6499  *  S_FALSE, because it's a non-debug driver
6500  *
6501  *****************************************************************************/
6502 static HRESULT WINAPI
6503 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6504                               DWORD DevInfoID,
6505                               void *DevInfoStruct,
6506                               DWORD Size)
6507 {
6508     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6509     TRACE("(%p)->(%08x,%p,%08x)\n", This, DevInfoID, DevInfoStruct, Size);
6510
6511     if (TRACE_ON(d3d7))
6512     {
6513         TRACE(" info requested : ");
6514         switch (DevInfoID)
6515         {
6516             case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6517             case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6518             case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6519             default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6520         }
6521     }
6522
6523     return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6524 }
6525
6526 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6527  * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6528  * are not duplicated.
6529
6530  * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6531  * has already been setup for optimal d3d operation.
6532
6533  * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6534  * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6535  * by Sacrifice (game). */
6536 const IDirect3DDevice7Vtbl IDirect3DDevice7_FPUSetup_Vtbl =
6537 {
6538     /*** IUnknown Methods ***/
6539     IDirect3DDeviceImpl_7_QueryInterface,
6540     IDirect3DDeviceImpl_7_AddRef,
6541     IDirect3DDeviceImpl_7_Release,
6542     /*** IDirect3DDevice7 ***/
6543     IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6544     IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6545     IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6546     IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6547     IDirect3DDeviceImpl_7_GetDirect3D,
6548     IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6549     IDirect3DDeviceImpl_7_GetRenderTarget,
6550     IDirect3DDeviceImpl_7_Clear_FPUSetup,
6551     IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6552     IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6553     IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6554     IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6555     IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6556     IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6557     IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6558     IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6559     IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6560     IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6561     IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6562     IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6563     IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6564     IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6565     IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6566     IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6567     IDirect3DDeviceImpl_7_SetClipStatus,
6568     IDirect3DDeviceImpl_7_GetClipStatus,
6569     IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6570     IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6571     IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6572     IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6573     IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6574     IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6575     IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6576     IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6577     IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6578     IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6579     IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6580     IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6581     IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6582     IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6583     IDirect3DDeviceImpl_7_Load_FPUSetup,
6584     IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6585     IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6586     IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6587     IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6588     IDirect3DDeviceImpl_7_GetInfo
6589 };
6590
6591 const IDirect3DDevice7Vtbl IDirect3DDevice7_FPUPreserve_Vtbl =
6592 {
6593     /*** IUnknown Methods ***/
6594     IDirect3DDeviceImpl_7_QueryInterface,
6595     IDirect3DDeviceImpl_7_AddRef,
6596     IDirect3DDeviceImpl_7_Release,
6597     /*** IDirect3DDevice7 ***/
6598     IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6599     IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6600     IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6601     IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6602     IDirect3DDeviceImpl_7_GetDirect3D,
6603     IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6604     IDirect3DDeviceImpl_7_GetRenderTarget,
6605     IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6606     IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6607     IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6608     IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6609     IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6610     IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6611     IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6612     IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6613     IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6614     IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6615     IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6616     IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6617     IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6618     IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6619     IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6620     IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6621     IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6622     IDirect3DDeviceImpl_7_SetClipStatus,
6623     IDirect3DDeviceImpl_7_GetClipStatus,
6624     IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6625     IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6626     IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6627     IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6628     IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6629     IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6630     IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6631     IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6632     IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6633     IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6634     IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6635     IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6636     IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6637     IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6638     IDirect3DDeviceImpl_7_Load_FPUPreserve,
6639     IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6640     IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6641     IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6642     IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6643     IDirect3DDeviceImpl_7_GetInfo
6644 };
6645
6646 const IDirect3DDevice3Vtbl IDirect3DDevice3_Vtbl =
6647 {
6648     /*** IUnknown Methods ***/
6649     Thunk_IDirect3DDeviceImpl_3_QueryInterface,
6650     Thunk_IDirect3DDeviceImpl_3_AddRef,
6651     Thunk_IDirect3DDeviceImpl_3_Release,
6652     /*** IDirect3DDevice3 ***/
6653     IDirect3DDeviceImpl_3_GetCaps,
6654     IDirect3DDeviceImpl_3_GetStats,
6655     IDirect3DDeviceImpl_3_AddViewport,
6656     IDirect3DDeviceImpl_3_DeleteViewport,
6657     IDirect3DDeviceImpl_3_NextViewport,
6658     Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
6659     Thunk_IDirect3DDeviceImpl_3_BeginScene,
6660     Thunk_IDirect3DDeviceImpl_3_EndScene,
6661     Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
6662     IDirect3DDeviceImpl_3_SetCurrentViewport,
6663     IDirect3DDeviceImpl_3_GetCurrentViewport,
6664     Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
6665     Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
6666     IDirect3DDeviceImpl_3_Begin,
6667     IDirect3DDeviceImpl_3_BeginIndexed,
6668     IDirect3DDeviceImpl_3_Vertex,
6669     IDirect3DDeviceImpl_3_Index,
6670     IDirect3DDeviceImpl_3_End,
6671     IDirect3DDeviceImpl_3_GetRenderState,
6672     IDirect3DDeviceImpl_3_SetRenderState,
6673     IDirect3DDeviceImpl_3_GetLightState,
6674     IDirect3DDeviceImpl_3_SetLightState,
6675     Thunk_IDirect3DDeviceImpl_3_SetTransform,
6676     Thunk_IDirect3DDeviceImpl_3_GetTransform,
6677     Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
6678     Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
6679     Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6680     Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
6681     Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
6682     Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6683     Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6684     Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6685     Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6686     Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6687     Thunk_IDirect3DDeviceImpl_3_GetTexture,
6688     IDirect3DDeviceImpl_3_SetTexture,
6689     Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
6690     Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
6691     Thunk_IDirect3DDeviceImpl_3_ValidateDevice
6692 };
6693
6694 const IDirect3DDevice2Vtbl IDirect3DDevice2_Vtbl =
6695 {
6696     /*** IUnknown Methods ***/
6697     Thunk_IDirect3DDeviceImpl_2_QueryInterface,
6698     Thunk_IDirect3DDeviceImpl_2_AddRef,
6699     Thunk_IDirect3DDeviceImpl_2_Release,
6700     /*** IDirect3DDevice2 ***/
6701     Thunk_IDirect3DDeviceImpl_2_GetCaps,
6702     IDirect3DDeviceImpl_2_SwapTextureHandles,
6703     Thunk_IDirect3DDeviceImpl_2_GetStats,
6704     Thunk_IDirect3DDeviceImpl_2_AddViewport,
6705     Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
6706     Thunk_IDirect3DDeviceImpl_2_NextViewport,
6707     IDirect3DDeviceImpl_2_EnumTextureFormats,
6708     Thunk_IDirect3DDeviceImpl_2_BeginScene,
6709     Thunk_IDirect3DDeviceImpl_2_EndScene,
6710     Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
6711     Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
6712     Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
6713     Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
6714     Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
6715     Thunk_IDirect3DDeviceImpl_2_Begin,
6716     Thunk_IDirect3DDeviceImpl_2_BeginIndexed,
6717     Thunk_IDirect3DDeviceImpl_2_Vertex,
6718     Thunk_IDirect3DDeviceImpl_2_Index,
6719     Thunk_IDirect3DDeviceImpl_2_End,
6720     Thunk_IDirect3DDeviceImpl_2_GetRenderState,
6721     Thunk_IDirect3DDeviceImpl_2_SetRenderState,
6722     Thunk_IDirect3DDeviceImpl_2_GetLightState,
6723     Thunk_IDirect3DDeviceImpl_2_SetLightState,
6724     Thunk_IDirect3DDeviceImpl_2_SetTransform,
6725     Thunk_IDirect3DDeviceImpl_2_GetTransform,
6726     Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
6727     Thunk_IDirect3DDeviceImpl_2_DrawPrimitive,
6728     Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6729     Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
6730     Thunk_IDirect3DDeviceImpl_2_GetClipStatus
6731 };
6732
6733 const IDirect3DDeviceVtbl IDirect3DDevice1_Vtbl =
6734 {
6735     /*** IUnknown Methods ***/
6736     Thunk_IDirect3DDeviceImpl_1_QueryInterface,
6737     Thunk_IDirect3DDeviceImpl_1_AddRef,
6738     Thunk_IDirect3DDeviceImpl_1_Release,
6739     /*** IDirect3DDevice1 ***/
6740     IDirect3DDeviceImpl_1_Initialize,
6741     Thunk_IDirect3DDeviceImpl_1_GetCaps,
6742     Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
6743     IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6744     Thunk_IDirect3DDeviceImpl_1_GetStats,
6745     IDirect3DDeviceImpl_1_Execute,
6746     Thunk_IDirect3DDeviceImpl_1_AddViewport,
6747     Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
6748     Thunk_IDirect3DDeviceImpl_1_NextViewport,
6749     IDirect3DDeviceImpl_1_Pick,
6750     IDirect3DDeviceImpl_1_GetPickRecords,
6751     Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
6752     IDirect3DDeviceImpl_1_CreateMatrix,
6753     IDirect3DDeviceImpl_1_SetMatrix,
6754     IDirect3DDeviceImpl_1_GetMatrix,
6755     IDirect3DDeviceImpl_1_DeleteMatrix,
6756     Thunk_IDirect3DDeviceImpl_1_BeginScene,
6757     Thunk_IDirect3DDeviceImpl_1_EndScene,
6758     Thunk_IDirect3DDeviceImpl_1_GetDirect3D
6759 };
6760
6761 /*****************************************************************************
6762  * IDirect3DDeviceImpl_CreateHandle
6763  *
6764  * Not called from the VTable
6765  *
6766  * Some older interface versions operate with handles, which are basically
6767  * DWORDs which identify an interface, for example
6768  * IDirect3DDevice::SetRenderState with DIRECT3DRENDERSTATE_TEXTUREHANDLE
6769  *
6770  * Those handle could be just casts to the interface pointers or vice versa,
6771  * but that is not 64 bit safe and would mean blindly derefering a DWORD
6772  * passed by the app. Instead there is a dynamic array in the device which
6773  * keeps a DWORD to pointer information and a type for the handle.
6774  *
6775  * Basically this array only grows, when a handle is freed its pointer is
6776  * just set to NULL. There will be much more reads from the array than
6777  * insertion operations, so a dynamic array is fine.
6778  *
6779  * Params:
6780  *  This: D3DDevice implementation for which this handle should be created
6781  *
6782  * Returns:
6783  *  A free handle on success
6784  *  0 on failure
6785  *
6786  *****************************************************************************/
6787 DWORD
6788 IDirect3DDeviceImpl_CreateHandle(IDirect3DDeviceImpl *This)
6789 {
6790     DWORD i;
6791     struct HandleEntry *oldHandles = This->Handles;
6792
6793     TRACE("(%p)\n", This);
6794
6795     for(i = 0; i < This->numHandles; i++)
6796     {
6797         if(This->Handles[i].ptr == NULL &&
6798            This->Handles[i].type == DDrawHandle_Unknown)
6799         {
6800             TRACE("Reusing freed handle %d\n", i + 1);
6801             return i + 1;
6802         }
6803     }
6804
6805     TRACE("Growing the handle array\n");
6806
6807     This->numHandles++;
6808     This->Handles = HeapAlloc(GetProcessHeap(), 0, sizeof(struct HandleEntry) * This->numHandles);
6809     if(!This->Handles)
6810     {
6811         ERR("Out of memory\n");
6812         This->Handles = oldHandles;
6813         This->numHandles--;
6814         return 0;
6815     }
6816     if(oldHandles)
6817     {
6818         memcpy(This->Handles, oldHandles, (This->numHandles - 1) * sizeof(struct HandleEntry));
6819         HeapFree(GetProcessHeap(), 0, oldHandles);
6820     }
6821
6822     TRACE("Returning %d\n", This->numHandles);
6823     return This->numHandles;
6824 }
6825
6826 /*****************************************************************************
6827  * IDirect3DDeviceImpl_UpdateDepthStencil
6828  *
6829  * Checks the current render target for attached depth stencils and sets the
6830  * WineD3D depth stencil accordingly.
6831  *
6832  * Returns:
6833  *  The depth stencil state to set if creating the device
6834  *
6835  *****************************************************************************/
6836 WINED3DZBUFFERTYPE
6837 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6838 {
6839     IDirectDrawSurface7 *depthStencil = NULL;
6840     IDirectDrawSurfaceImpl *dsi;
6841     static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6842
6843     IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)This->target, &depthcaps, &depthStencil);
6844     if(!depthStencil)
6845     {
6846         TRACE("Setting wined3d depth stencil to NULL\n");
6847         IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6848                                               NULL);
6849         return WINED3DZB_FALSE;
6850     }
6851
6852     dsi = (IDirectDrawSurfaceImpl *)depthStencil;
6853     TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->WineD3DSurface);
6854     IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6855                                           dsi->WineD3DSurface);
6856
6857     IDirectDrawSurface7_Release(depthStencil);
6858     return WINED3DZB_TRUE;
6859 }