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