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