jscript: Remove break after return (Smatch).
[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, WINED3D_RS_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, WINED3D_RS_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 state, D3DMATRIX *matrix)
3283 {
3284     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3285
3286     TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3287
3288     if (!matrix)
3289         return DDERR_INVALIDPARAMS;
3290
3291     if (state == D3DTRANSFORMSTATE_PROJECTION)
3292     {
3293         D3DMATRIX projection;
3294         HRESULT hr;
3295
3296         wined3d_mutex_lock();
3297         multiply_matrix(&projection, &This->legacy_clipspace, matrix);
3298         hr = wined3d_device_set_transform(This->wined3d_device,
3299                 WINED3DTS_PROJECTION, (struct wined3d_matrix *)&projection);
3300         if (SUCCEEDED(hr))
3301             This->legacy_projection = *matrix;
3302         wined3d_mutex_unlock();
3303
3304         return hr;
3305     }
3306
3307     return IDirect3DDevice7_SetTransform(&This->IDirect3DDevice7_iface, state, matrix);
3308 }
3309
3310 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3311         D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3312 {
3313     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3314
3315     TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3316
3317     return IDirect3DDevice7_SetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3318 }
3319
3320 /*****************************************************************************
3321  * IDirect3DDevice7::GetTransform
3322  *
3323  * Returns the matrix assigned to a transform state
3324  * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3325  * SetTransform
3326  *
3327  * Params:
3328  *  TransformStateType: State to read the matrix from
3329  *  Matrix: Address to store the matrix at
3330  *
3331  * Returns:
3332  *  D3D_OK on success
3333  *  DDERR_INVALIDPARAMS if Matrix == NULL
3334  *  For details, see IWineD3DDevice::GetTransform
3335  *
3336  *****************************************************************************/
3337 static HRESULT
3338 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3339                                    D3DTRANSFORMSTATETYPE TransformStateType,
3340                                    D3DMATRIX *Matrix)
3341 {
3342     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3343     D3DTRANSFORMSTATETYPE type;
3344     HRESULT hr;
3345
3346     TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3347
3348     switch(TransformStateType)
3349     {
3350         case D3DTRANSFORMSTATE_WORLD :  type = WINED3DTS_WORLDMATRIX(0); break;
3351         case D3DTRANSFORMSTATE_WORLD1:  type = WINED3DTS_WORLDMATRIX(1); break;
3352         case D3DTRANSFORMSTATE_WORLD2:  type = WINED3DTS_WORLDMATRIX(2); break;
3353         case D3DTRANSFORMSTATE_WORLD3:  type = WINED3DTS_WORLDMATRIX(3); break;
3354         default:                        type = TransformStateType;
3355     }
3356
3357     if(!Matrix)
3358         return DDERR_INVALIDPARAMS;
3359
3360     /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3361     wined3d_mutex_lock();
3362     hr = wined3d_device_get_transform(This->wined3d_device, type, (struct wined3d_matrix *)Matrix);
3363     wined3d_mutex_unlock();
3364
3365     return hr;
3366 }
3367
3368 static HRESULT WINAPI
3369 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3370                                    D3DTRANSFORMSTATETYPE TransformStateType,
3371                                    D3DMATRIX *Matrix)
3372 {
3373     return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3374 }
3375
3376 static HRESULT WINAPI
3377 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3378                                    D3DTRANSFORMSTATETYPE TransformStateType,
3379                                    D3DMATRIX *Matrix)
3380 {
3381     HRESULT hr;
3382     WORD old_fpucw;
3383
3384     old_fpucw = d3d_fpu_setup();
3385     hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3386     set_fpu_control_word(old_fpucw);
3387
3388     return hr;
3389 }
3390
3391 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3392         D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3393 {
3394     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3395
3396     TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3397
3398     if (!matrix)
3399         return DDERR_INVALIDPARAMS;
3400
3401     if (state == D3DTRANSFORMSTATE_PROJECTION)
3402     {
3403         wined3d_mutex_lock();
3404         *matrix = This->legacy_projection;
3405         wined3d_mutex_unlock();
3406         return DD_OK;
3407     }
3408
3409     return IDirect3DDevice7_GetTransform(&This->IDirect3DDevice7_iface, state, matrix);
3410 }
3411
3412 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3413         D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3414 {
3415     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3416
3417     TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3418
3419     return IDirect3DDevice7_GetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3420 }
3421
3422 /*****************************************************************************
3423  * IDirect3DDevice7::MultiplyTransform
3424  *
3425  * Multiplies the already-set transform matrix of a transform state
3426  * with another matrix. For the world matrix, see SetTransform
3427  *
3428  * Version 2, 3 and 7
3429  *
3430  * Params:
3431  *  TransformStateType: Transform state to multiply
3432  *  D3DMatrix Matrix to multiply with.
3433  *
3434  * Returns
3435  *  D3D_OK on success
3436  *  DDERR_INVALIDPARAMS if D3DMatrix is NULL
3437  *  For details, see IWineD3DDevice::MultiplyTransform
3438  *
3439  *****************************************************************************/
3440 static HRESULT
3441 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3442                                         D3DTRANSFORMSTATETYPE TransformStateType,
3443                                         D3DMATRIX *D3DMatrix)
3444 {
3445     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3446     HRESULT hr;
3447     D3DTRANSFORMSTATETYPE type;
3448
3449     TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3450
3451     switch(TransformStateType)
3452     {
3453         case D3DTRANSFORMSTATE_WORLD :  type = WINED3DTS_WORLDMATRIX(0); break;
3454         case D3DTRANSFORMSTATE_WORLD1:  type = WINED3DTS_WORLDMATRIX(1); break;
3455         case D3DTRANSFORMSTATE_WORLD2:  type = WINED3DTS_WORLDMATRIX(2); break;
3456         case D3DTRANSFORMSTATE_WORLD3:  type = WINED3DTS_WORLDMATRIX(3); break;
3457         default:                        type = TransformStateType;
3458     }
3459
3460     /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3461     wined3d_mutex_lock();
3462     hr = wined3d_device_multiply_transform(This->wined3d_device,
3463             type, (struct wined3d_matrix *)D3DMatrix);
3464     wined3d_mutex_unlock();
3465
3466     return hr;
3467 }
3468
3469 static HRESULT WINAPI
3470 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3471                                         D3DTRANSFORMSTATETYPE TransformStateType,
3472                                         D3DMATRIX *D3DMatrix)
3473 {
3474     return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3475 }
3476
3477 static HRESULT WINAPI
3478 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3479                                         D3DTRANSFORMSTATETYPE TransformStateType,
3480                                         D3DMATRIX *D3DMatrix)
3481 {
3482     HRESULT hr;
3483     WORD old_fpucw;
3484
3485     old_fpucw = d3d_fpu_setup();
3486     hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3487     set_fpu_control_word(old_fpucw);
3488
3489     return hr;
3490 }
3491
3492 static HRESULT WINAPI IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3493         D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3494 {
3495     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3496
3497     TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3498
3499     if (state == D3DTRANSFORMSTATE_PROJECTION)
3500     {
3501         D3DMATRIX projection, tmp;
3502         HRESULT hr;
3503
3504         wined3d_mutex_lock();
3505         multiply_matrix(&tmp, &This->legacy_projection, matrix);
3506         multiply_matrix(&projection, &This->legacy_clipspace, &tmp);
3507         hr = wined3d_device_set_transform(This->wined3d_device,
3508                 WINED3DTS_PROJECTION, (struct wined3d_matrix *)&projection);
3509         if (SUCCEEDED(hr))
3510             This->legacy_projection = tmp;
3511         wined3d_mutex_unlock();
3512
3513         return hr;
3514     }
3515
3516     return IDirect3DDevice7_MultiplyTransform(&This->IDirect3DDevice7_iface, state, matrix);
3517 }
3518
3519 static HRESULT WINAPI IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3520         D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3521 {
3522     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3523
3524     TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3525
3526     return IDirect3DDevice7_MultiplyTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3527 }
3528
3529 /*****************************************************************************
3530  * IDirect3DDevice7::DrawPrimitive
3531  *
3532  * Draws primitives based on vertices in an application-provided pointer
3533  *
3534  * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3535  * an FVF format for D3D7
3536  *
3537  * Params:
3538  *  PrimitiveType: The type of the primitives to draw
3539  *  Vertex type: Flexible vertex format vertex description
3540  *  Vertices: Pointer to the vertex array
3541  *  VertexCount: The number of vertices to draw
3542  *  Flags: As usual a few flags
3543  *
3544  * Returns:
3545  *  D3D_OK on success
3546  *  DDERR_INVALIDPARAMS if Vertices is NULL
3547  *  For details, see IWineD3DDevice::DrawPrimitiveUP
3548  *
3549  *****************************************************************************/
3550 static HRESULT
3551 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3552                                     D3DPRIMITIVETYPE PrimitiveType,
3553                                     DWORD VertexType,
3554                                     void *Vertices,
3555                                     DWORD VertexCount,
3556                                     DWORD Flags)
3557 {
3558     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3559     UINT stride;
3560     HRESULT hr;
3561
3562     TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3563             iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3564
3565     if(!Vertices)
3566         return DDERR_INVALIDPARAMS;
3567
3568     /* Get the stride */
3569     stride = get_flexible_vertex_size(VertexType);
3570
3571     /* Set the FVF */
3572     wined3d_mutex_lock();
3573     hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3574     if(hr != D3D_OK)
3575     {
3576         wined3d_mutex_unlock();
3577         return hr;
3578     }
3579
3580     /* This method translates to the user pointer draw of WineD3D */
3581     wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3582     hr = wined3d_device_draw_primitive_up(This->wined3d_device, VertexCount, Vertices, stride);
3583     wined3d_mutex_unlock();
3584
3585     return hr;
3586 }
3587
3588 static HRESULT WINAPI
3589 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3590                                     D3DPRIMITIVETYPE PrimitiveType,
3591                                     DWORD VertexType,
3592                                     void *Vertices,
3593                                     DWORD VertexCount,
3594                                     DWORD Flags)
3595 {
3596     return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3597 }
3598
3599 static HRESULT WINAPI
3600 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3601                                     D3DPRIMITIVETYPE PrimitiveType,
3602                                     DWORD VertexType,
3603                                     void *Vertices,
3604                                     DWORD VertexCount,
3605                                     DWORD Flags)
3606 {
3607     HRESULT hr;
3608     WORD old_fpucw;
3609
3610     old_fpucw = d3d_fpu_setup();
3611     hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3612     set_fpu_control_word(old_fpucw);
3613
3614     return hr;
3615 }
3616
3617 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3618         D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3619         DWORD Flags)
3620 {
3621     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3622     TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3623             iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3624
3625     return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface,
3626             PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3627 }
3628
3629 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3630         D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3631         DWORD VertexCount, DWORD Flags)
3632 {
3633     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3634     DWORD FVF;
3635
3636     TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3637             iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3638
3639     switch(VertexType)
3640     {
3641         case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3642         case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3643         case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3644         default:
3645             ERR("Unexpected vertex type %d\n", VertexType);
3646             return DDERR_INVALIDPARAMS;  /* Should never happen */
3647     }
3648
3649     return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface,
3650             PrimitiveType, FVF, Vertices, VertexCount, Flags);
3651 }
3652
3653 /*****************************************************************************
3654  * IDirect3DDevice7::DrawIndexedPrimitive
3655  *
3656  * Draws vertices from an application-provided pointer, based on the index
3657  * numbers in a WORD array.
3658  *
3659  * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3660  * an FVF format for D3D7
3661  *
3662  * Params:
3663  *  PrimitiveType: The primitive type to draw
3664  *  VertexType: The FVF vertex description
3665  *  Vertices: Pointer to the vertex array
3666  *  VertexCount: ?
3667  *  Indices: Pointer to the index array
3668  *  IndexCount: Number of indices = Number of vertices to draw
3669  *  Flags: As usual, some flags
3670  *
3671  * Returns:
3672  *  D3D_OK on success
3673  *  DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3674  *  For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3675  *
3676  *****************************************************************************/
3677 static HRESULT
3678 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(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     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3688     HRESULT hr;
3689
3690     TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3691             iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3692
3693     /* Set the D3DDevice's FVF */
3694     wined3d_mutex_lock();
3695     hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3696     if(FAILED(hr))
3697     {
3698         ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3699         wined3d_mutex_unlock();
3700         return hr;
3701     }
3702
3703     wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3704     hr = wined3d_device_draw_indexed_primitive_up(This->wined3d_device, IndexCount, Indices,
3705             WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3706     wined3d_mutex_unlock();
3707
3708     return hr;
3709 }
3710
3711 static HRESULT WINAPI
3712 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3713                                            D3DPRIMITIVETYPE PrimitiveType,
3714                                            DWORD VertexType,
3715                                            void *Vertices,
3716                                            DWORD VertexCount,
3717                                            WORD *Indices,
3718                                            DWORD IndexCount,
3719                                            DWORD Flags)
3720 {
3721     return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3722 }
3723
3724 static HRESULT WINAPI
3725 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3726                                            D3DPRIMITIVETYPE PrimitiveType,
3727                                            DWORD VertexType,
3728                                            void *Vertices,
3729                                            DWORD VertexCount,
3730                                            WORD *Indices,
3731                                            DWORD IndexCount,
3732                                            DWORD Flags)
3733 {
3734     HRESULT hr;
3735     WORD old_fpucw;
3736
3737     old_fpucw = d3d_fpu_setup();
3738     hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3739     set_fpu_control_word(old_fpucw);
3740
3741     return hr;
3742 }
3743
3744 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3745         D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3746         WORD *Indices, DWORD IndexCount, DWORD Flags)
3747 {
3748     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3749     TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3750             iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3751
3752     return IDirect3DDevice7_DrawIndexedPrimitive(&This->IDirect3DDevice7_iface,
3753             PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3754 }
3755
3756 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3757         D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3758         DWORD VertexCount, WORD *Indices, DWORD IndexCount, DWORD Flags)
3759 {
3760     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3761     DWORD FVF;
3762
3763     TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3764             iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3765
3766     switch(VertexType)
3767     {
3768         case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3769         case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3770         case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3771         default:
3772             ERR("Unexpected vertex type %d\n", VertexType);
3773             return DDERR_INVALIDPARAMS;  /* Should never happen */
3774     }
3775
3776     return IDirect3DDevice7_DrawIndexedPrimitive(&This->IDirect3DDevice7_iface,
3777             PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3778 }
3779
3780 /*****************************************************************************
3781  * IDirect3DDevice7::SetClipStatus
3782  *
3783  * Sets the clip status. This defines things as clipping conditions and
3784  * the extents of the clipping region.
3785  *
3786  * Version 2, 3 and 7
3787  *
3788  * Params:
3789  *  ClipStatus:
3790  *
3791  * Returns:
3792  *  D3D_OK because it's a stub
3793  *  (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3794  *
3795  *****************************************************************************/
3796 static HRESULT WINAPI
3797 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3798                                     D3DCLIPSTATUS *ClipStatus)
3799 {
3800     FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3801
3802     /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3803      * Perhaps this needs a new data type and an additional IWineD3DDevice method
3804      */
3805     /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3806     return D3D_OK;
3807 }
3808
3809 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3810         D3DCLIPSTATUS *ClipStatus)
3811 {
3812     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3813     TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3814
3815     return IDirect3DDevice7_SetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3816 }
3817
3818 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3819         D3DCLIPSTATUS *ClipStatus)
3820 {
3821     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3822     TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3823
3824     return IDirect3DDevice7_SetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3825 }
3826
3827 /*****************************************************************************
3828  * IDirect3DDevice7::GetClipStatus
3829  *
3830  * Returns the clip status
3831  *
3832  * Params:
3833  *  ClipStatus: Address to write the clip status to
3834  *
3835  * Returns:
3836  *  D3D_OK because it's a stub
3837  *
3838  *****************************************************************************/
3839 static HRESULT WINAPI
3840 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3841                                     D3DCLIPSTATUS *ClipStatus)
3842 {
3843     FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3844
3845     /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3846     /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3847     return D3D_OK;
3848 }
3849
3850 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3851         D3DCLIPSTATUS *ClipStatus)
3852 {
3853     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3854     TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3855
3856     return IDirect3DDevice7_GetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3857 }
3858
3859 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3860         D3DCLIPSTATUS *ClipStatus)
3861 {
3862     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3863     TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3864
3865     return IDirect3DDevice7_GetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3866 }
3867
3868 /*****************************************************************************
3869  * IDirect3DDevice::DrawPrimitiveStrided
3870  *
3871  * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3872  *
3873  * Version 3 and 7
3874  *
3875  * Params:
3876  *  PrimitiveType: The primitive type to draw
3877  *  VertexType: The FVF description of the vertices to draw (for the stride??)
3878  *  D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3879  *                         the vertex data locations
3880  *  VertexCount: The number of vertices to draw
3881  *  Flags: Some flags
3882  *
3883  * Returns:
3884  *  D3D_OK, because it's a stub
3885  *  (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3886  *  (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3887  *
3888  *****************************************************************************/
3889 static HRESULT
3890 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3891                                            D3DPRIMITIVETYPE PrimitiveType,
3892                                            DWORD VertexType,
3893                                            D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3894                                            DWORD VertexCount,
3895                                            DWORD Flags)
3896 {
3897     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3898     struct wined3d_strided_data wined3d_strided;
3899     DWORD i;
3900     HRESULT hr;
3901
3902     TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3903             iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3904
3905     memset(&wined3d_strided, 0, sizeof(wined3d_strided));
3906     /* Get the strided data right. the wined3d structure is a bit bigger
3907      * Watch out: The contents of the strided data are determined by the fvf,
3908      * not by the members set in D3DDrawPrimStrideData. So it's valid
3909      * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3910      * not set in the fvf.
3911      */
3912     if(VertexType & D3DFVF_POSITION_MASK)
3913     {
3914         wined3d_strided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3915         wined3d_strided.position.data = D3DDrawPrimStrideData->position.lpvData;
3916         wined3d_strided.position.stride = D3DDrawPrimStrideData->position.dwStride;
3917         if (VertexType & D3DFVF_XYZRHW)
3918         {
3919             wined3d_strided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3920             wined3d_strided.position_transformed = TRUE;
3921         }
3922         else
3923         {
3924             wined3d_strided.position_transformed = FALSE;
3925         }
3926     }
3927
3928     if (VertexType & D3DFVF_NORMAL)
3929     {
3930         wined3d_strided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3931         wined3d_strided.normal.data = D3DDrawPrimStrideData->normal.lpvData;
3932         wined3d_strided.normal.stride = D3DDrawPrimStrideData->normal.dwStride;
3933     }
3934
3935     if (VertexType & D3DFVF_DIFFUSE)
3936     {
3937         wined3d_strided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3938         wined3d_strided.diffuse.data = D3DDrawPrimStrideData->diffuse.lpvData;
3939         wined3d_strided.diffuse.stride = D3DDrawPrimStrideData->diffuse.dwStride;
3940     }
3941
3942     if (VertexType & D3DFVF_SPECULAR)
3943     {
3944         wined3d_strided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3945         wined3d_strided.specular.data = D3DDrawPrimStrideData->specular.lpvData;
3946         wined3d_strided.specular.stride = D3DDrawPrimStrideData->specular.dwStride;
3947     }
3948
3949     for (i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); ++i)
3950     {
3951         switch (GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3952         {
3953             case 1: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32_FLOAT; break;
3954             case 2: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3955             case 3: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3956             case 4: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3957             default: ERR("Unexpected texture coordinate size %d\n",
3958                          GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3959         }
3960         wined3d_strided.tex_coords[i].data = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3961         wined3d_strided.tex_coords[i].stride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3962     }
3963
3964     /* WineD3D doesn't need the FVF here */
3965     wined3d_mutex_lock();
3966     wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3967     hr = wined3d_device_draw_primitive_strided(This->wined3d_device, VertexCount, &wined3d_strided);
3968     wined3d_mutex_unlock();
3969
3970     return hr;
3971 }
3972
3973 static HRESULT WINAPI
3974 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3975                                            D3DPRIMITIVETYPE PrimitiveType,
3976                                            DWORD VertexType,
3977                                            D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3978                                            DWORD VertexCount,
3979                                            DWORD Flags)
3980 {
3981     return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3982 }
3983
3984 static HRESULT WINAPI
3985 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3986                                            D3DPRIMITIVETYPE PrimitiveType,
3987                                            DWORD VertexType,
3988                                            D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3989                                            DWORD VertexCount,
3990                                            DWORD Flags)
3991 {
3992     HRESULT hr;
3993     WORD old_fpucw;
3994
3995     old_fpucw = d3d_fpu_setup();
3996     hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3997     set_fpu_control_word(old_fpucw);
3998
3999     return hr;
4000 }
4001
4002 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
4003         D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4004         D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4005 {
4006     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4007
4008     TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
4009             iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4010
4011     return IDirect3DDevice7_DrawPrimitiveStrided(&This->IDirect3DDevice7_iface,
4012             PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4013 }
4014
4015 /*****************************************************************************
4016  * IDirect3DDevice7::DrawIndexedPrimitiveStrided
4017  *
4018  * Draws primitives specified by strided data locations based on indices
4019  *
4020  * Version 3 and 7
4021  *
4022  * Params:
4023  *  PrimitiveType:
4024  *
4025  * Returns:
4026  *  D3D_OK, because it's a stub
4027  *  (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
4028  *  (DDERR_INVALIDPARAMS if Indices is NULL)
4029  *  (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
4030  *
4031  *****************************************************************************/
4032 static HRESULT
4033 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
4034                                                   D3DPRIMITIVETYPE PrimitiveType,
4035                                                   DWORD VertexType,
4036                                                   D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4037                                                   DWORD VertexCount,
4038                                                   WORD *Indices,
4039                                                   DWORD IndexCount,
4040                                                   DWORD Flags)
4041 {
4042     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4043     struct wined3d_strided_data wined3d_strided;
4044     DWORD i;
4045     HRESULT hr;
4046
4047     TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4048             iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4049
4050     memset(&wined3d_strided, 0, sizeof(wined3d_strided));
4051     /* Get the strided data right. the wined3d structure is a bit bigger
4052      * Watch out: The contents of the strided data are determined by the fvf,
4053      * not by the members set in D3DDrawPrimStrideData. So it's valid
4054      * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
4055      * not set in the fvf. */
4056     if (VertexType & D3DFVF_POSITION_MASK)
4057     {
4058         wined3d_strided.position.format = WINED3DFMT_R32G32B32_FLOAT;
4059         wined3d_strided.position.data = D3DDrawPrimStrideData->position.lpvData;
4060         wined3d_strided.position.stride = D3DDrawPrimStrideData->position.dwStride;
4061         if (VertexType & D3DFVF_XYZRHW)
4062         {
4063             wined3d_strided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
4064             wined3d_strided.position_transformed = TRUE;
4065         }
4066         else
4067         {
4068             wined3d_strided.position_transformed = FALSE;
4069         }
4070     }
4071
4072     if (VertexType & D3DFVF_NORMAL)
4073     {
4074         wined3d_strided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
4075         wined3d_strided.normal.data = D3DDrawPrimStrideData->normal.lpvData;
4076         wined3d_strided.normal.stride = D3DDrawPrimStrideData->normal.dwStride;
4077     }
4078
4079     if (VertexType & D3DFVF_DIFFUSE)
4080     {
4081         wined3d_strided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
4082         wined3d_strided.diffuse.data = D3DDrawPrimStrideData->diffuse.lpvData;
4083         wined3d_strided.diffuse.stride = D3DDrawPrimStrideData->diffuse.dwStride;
4084     }
4085
4086     if (VertexType & D3DFVF_SPECULAR)
4087     {
4088         wined3d_strided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
4089         wined3d_strided.specular.data = D3DDrawPrimStrideData->specular.lpvData;
4090         wined3d_strided.specular.stride = D3DDrawPrimStrideData->specular.dwStride;
4091     }
4092
4093     for (i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); ++i)
4094     {
4095         switch (GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
4096         {
4097             case 1: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32_FLOAT; break;
4098             case 2: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32_FLOAT; break;
4099             case 3: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
4100             case 4: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
4101             default: ERR("Unexpected texture coordinate size %d\n",
4102                          GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4103         }
4104         wined3d_strided.tex_coords[i].data = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4105         wined3d_strided.tex_coords[i].stride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4106     }
4107
4108     /* WineD3D doesn't need the FVF here */
4109     wined3d_mutex_lock();
4110     wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4111     hr = wined3d_device_draw_indexed_primitive_strided(This->wined3d_device,
4112             IndexCount, &wined3d_strided, VertexCount, Indices, WINED3DFMT_R16_UINT);
4113     wined3d_mutex_unlock();
4114
4115     return hr;
4116 }
4117
4118 static HRESULT WINAPI
4119 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4120                                                   D3DPRIMITIVETYPE PrimitiveType,
4121                                                   DWORD VertexType,
4122                                                   D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4123                                                   DWORD VertexCount,
4124                                                   WORD *Indices,
4125                                                   DWORD IndexCount,
4126                                                   DWORD Flags)
4127 {
4128     return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4129 }
4130
4131 static HRESULT WINAPI
4132 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4133                                                   D3DPRIMITIVETYPE PrimitiveType,
4134                                                   DWORD VertexType,
4135                                                   D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4136                                                   DWORD VertexCount,
4137                                                   WORD *Indices,
4138                                                   DWORD IndexCount,
4139                                                   DWORD Flags)
4140 {
4141     HRESULT hr;
4142     WORD old_fpucw;
4143
4144     old_fpucw = d3d_fpu_setup();
4145     hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4146     set_fpu_control_word(old_fpucw);
4147
4148     return hr;
4149 }
4150
4151 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4152         D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4153         D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4154         DWORD IndexCount, DWORD Flags)
4155 {
4156     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4157
4158     TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4159             iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4160
4161     return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&This->IDirect3DDevice7_iface,
4162             PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4163 }
4164
4165 /*****************************************************************************
4166  * IDirect3DDevice7::DrawPrimitiveVB
4167  *
4168  * Draws primitives from a vertex buffer to the screen.
4169  *
4170  * Version 3 and 7
4171  *
4172  * Params:
4173  *  PrimitiveType: Type of primitive to be rendered.
4174  *  D3DVertexBuf: Source Vertex Buffer
4175  *  StartVertex: Index of the first vertex from the buffer to be rendered
4176  *  NumVertices: Number of vertices to be rendered
4177  *  Flags: Can be D3DDP_WAIT to wait until rendering has finished
4178  *
4179  * Return values
4180  *  D3D_OK on success
4181  *  DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4182  *
4183  *****************************************************************************/
4184 static HRESULT
4185 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4186                                       D3DPRIMITIVETYPE PrimitiveType,
4187                                       IDirect3DVertexBuffer7 *D3DVertexBuf,
4188                                       DWORD StartVertex,
4189                                       DWORD NumVertices,
4190                                       DWORD Flags)
4191 {
4192     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4193     IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4194     HRESULT hr;
4195     DWORD stride;
4196
4197     TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4198             iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4199
4200     /* Sanity checks */
4201     if(!vb)
4202     {
4203         ERR("(%p) No Vertex buffer specified\n", This);
4204         return DDERR_INVALIDPARAMS;
4205     }
4206     stride = get_flexible_vertex_size(vb->fvf);
4207
4208     wined3d_mutex_lock();
4209     hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4210     if (FAILED(hr))
4211     {
4212         ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4213         wined3d_mutex_unlock();
4214         return hr;
4215     }
4216
4217     /* Set the vertex stream source */
4218     hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4219     if(hr != D3D_OK)
4220     {
4221         ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4222         wined3d_mutex_unlock();
4223         return hr;
4224     }
4225
4226     /* Now draw the primitives */
4227     wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4228     hr = wined3d_device_draw_primitive(This->wined3d_device, StartVertex, NumVertices);
4229     wined3d_mutex_unlock();
4230
4231     return hr;
4232 }
4233
4234 static HRESULT WINAPI
4235 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4236                                       D3DPRIMITIVETYPE PrimitiveType,
4237                                       IDirect3DVertexBuffer7 *D3DVertexBuf,
4238                                       DWORD StartVertex,
4239                                       DWORD NumVertices,
4240                                       DWORD Flags)
4241 {
4242     return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4243 }
4244
4245 static HRESULT WINAPI
4246 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4247                                       D3DPRIMITIVETYPE PrimitiveType,
4248                                       IDirect3DVertexBuffer7 *D3DVertexBuf,
4249                                       DWORD StartVertex,
4250                                       DWORD NumVertices,
4251                                       DWORD Flags)
4252 {
4253     HRESULT hr;
4254     WORD old_fpucw;
4255
4256     old_fpucw = d3d_fpu_setup();
4257     hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4258     set_fpu_control_word(old_fpucw);
4259
4260     return hr;
4261 }
4262
4263 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4264         D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex,
4265         DWORD NumVertices, DWORD Flags)
4266 {
4267     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4268     IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4269
4270     TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4271             iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4272
4273     return IDirect3DDevice7_DrawPrimitiveVB(&This->IDirect3DDevice7_iface,
4274             PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4275 }
4276
4277
4278 /*****************************************************************************
4279  * IDirect3DDevice7::DrawIndexedPrimitiveVB
4280  *
4281  * Draws primitives from a vertex buffer to the screen
4282  *
4283  * Params:
4284  *  PrimitiveType: Type of primitive to be rendered.
4285  *  D3DVertexBuf: Source Vertex Buffer
4286  *  StartVertex: Index of the first vertex from the buffer to be rendered
4287  *  NumVertices: Number of vertices to be rendered
4288  *  Indices: Array of DWORDs used to index into the Vertices
4289  *  IndexCount: Number of indices in Indices
4290  *  Flags: Can be D3DDP_WAIT to wait until rendering has finished
4291  *
4292  * Return values
4293  *
4294  *****************************************************************************/
4295 static HRESULT
4296 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4297                                              D3DPRIMITIVETYPE PrimitiveType,
4298                                              IDirect3DVertexBuffer7 *D3DVertexBuf,
4299                                              DWORD StartVertex,
4300                                              DWORD NumVertices,
4301                                              WORD *Indices,
4302                                              DWORD IndexCount,
4303                                              DWORD Flags)
4304 {
4305     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4306     IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4307     DWORD stride = get_flexible_vertex_size(vb->fvf);
4308     struct wined3d_resource *wined3d_resource;
4309     struct wined3d_resource_desc desc;
4310     WORD *LockedIndices;
4311     HRESULT hr;
4312
4313     TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4314             iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4315
4316     /* Steps:
4317      * 1) Upload the Indices to the index buffer
4318      * 2) Set the index source
4319      * 3) Set the Vertex Buffer as the Stream source
4320      * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4321      */
4322
4323     wined3d_mutex_lock();
4324
4325     hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4326     if (FAILED(hr))
4327     {
4328         ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4329         wined3d_mutex_unlock();
4330         return hr;
4331     }
4332
4333     /* check that the buffer is large enough to hold the indices,
4334      * reallocate if necessary. */
4335     wined3d_resource = wined3d_buffer_get_resource(This->indexbuffer);
4336     wined3d_resource_get_desc(wined3d_resource, &desc);
4337     if (desc.size < IndexCount * sizeof(WORD))
4338     {
4339         UINT size = max(desc.size * 2, IndexCount * sizeof(WORD));
4340         struct wined3d_buffer *buffer;
4341
4342         TRACE("Growing index buffer to %u bytes\n", size);
4343
4344         hr = wined3d_buffer_create_ib(This->wined3d_device, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4345                 WINED3DPOOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
4346         if (FAILED(hr))
4347         {
4348             ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4349             wined3d_mutex_unlock();
4350             return hr;
4351         }
4352
4353         wined3d_buffer_decref(This->indexbuffer);
4354         This->indexbuffer = buffer;
4355     }
4356
4357     /* Copy the index stream into the index buffer. A new IWineD3DDevice
4358      * method could be created which takes an user pointer containing the
4359      * indices or a SetData-Method for the index buffer, which overrides the
4360      * index buffer data with our pointer. */
4361     hr = wined3d_buffer_map(This->indexbuffer, 0, IndexCount * sizeof(WORD),
4362             (BYTE **)&LockedIndices, 0);
4363     if (FAILED(hr))
4364     {
4365         ERR("Failed to map buffer, hr %#x.\n", hr);
4366         wined3d_mutex_unlock();
4367         return hr;
4368     }
4369     memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4370     wined3d_buffer_unmap(This->indexbuffer);
4371
4372     /* Set the index stream */
4373     wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4374     hr = wined3d_device_set_index_buffer(This->wined3d_device, This->indexbuffer, WINED3DFMT_R16_UINT);
4375
4376     /* Set the vertex stream source */
4377     hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4378     if (FAILED(hr))
4379     {
4380         ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4381         wined3d_mutex_unlock();
4382         return hr;
4383     }
4384
4385
4386     wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4387     hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, 0, IndexCount);
4388
4389     wined3d_mutex_unlock();
4390
4391     return hr;
4392 }
4393
4394 static HRESULT WINAPI
4395 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4396                                              D3DPRIMITIVETYPE PrimitiveType,
4397                                              IDirect3DVertexBuffer7 *D3DVertexBuf,
4398                                              DWORD StartVertex,
4399                                              DWORD NumVertices,
4400                                              WORD *Indices,
4401                                              DWORD IndexCount,
4402                                              DWORD Flags)
4403 {
4404     return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4405 }
4406
4407 static HRESULT WINAPI
4408 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4409                                              D3DPRIMITIVETYPE PrimitiveType,
4410                                              IDirect3DVertexBuffer7 *D3DVertexBuf,
4411                                              DWORD StartVertex,
4412                                              DWORD NumVertices,
4413                                              WORD *Indices,
4414                                              DWORD IndexCount,
4415                                              DWORD Flags)
4416 {
4417     HRESULT hr;
4418     WORD old_fpucw;
4419
4420     old_fpucw = d3d_fpu_setup();
4421     hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4422     set_fpu_control_word(old_fpucw);
4423
4424     return hr;
4425 }
4426
4427 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4428         D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4429         DWORD IndexCount, DWORD Flags)
4430 {
4431     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4432     IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4433
4434     TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4435             iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4436
4437     return IDirect3DDevice7_DrawIndexedPrimitiveVB(&This->IDirect3DDevice7_iface,
4438             PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount,
4439             Flags);
4440 }
4441
4442 /*****************************************************************************
4443  * IDirect3DDevice7::ComputeSphereVisibility
4444  *
4445  * Calculates the visibility of spheres in the current viewport. The spheres
4446  * are passed in the Centers and Radii arrays, the results are passed back
4447  * in the ReturnValues array. Return values are either completely visible,
4448  * partially visible or completely invisible.
4449  * The return value consist of a combination of D3DCLIP_* flags, or it's
4450  * 0 if the sphere is completely visible(according to the SDK, not checked)
4451  *
4452  * Version 3 and 7
4453  *
4454  * Params:
4455  *  Centers: Array containing the sphere centers
4456  *  Radii: Array containing the sphere radii
4457  *  NumSpheres: The number of centers and radii in the arrays
4458  *  Flags: Some flags
4459  *  ReturnValues: Array to write the results to
4460  *
4461  * Returns:
4462  *  D3D_OK
4463  *  (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4464  *  (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4465  *  is singular)
4466  *
4467  *****************************************************************************/
4468
4469 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4470 {
4471     float distance, norm;
4472
4473     norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4474     distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4475
4476     if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4477     if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT  | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4478     return 0;
4479 }
4480
4481 static HRESULT WINAPI
4482 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4483                                               D3DVECTOR *Centers,
4484                                               D3DVALUE *Radii,
4485                                               DWORD NumSpheres,
4486                                               DWORD Flags,
4487                                               DWORD *ReturnValues)
4488 {
4489     D3DMATRIX m, temp;
4490     D3DVALUE origin_plane[6];
4491     D3DVECTOR vec[6];
4492     HRESULT hr;
4493     UINT i, j;
4494
4495     TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4496             iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4497
4498     hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4499     if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4500     hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4501     if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4502     multiply_matrix(&m, &temp, &m);
4503
4504     hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4505     if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4506     multiply_matrix(&m, &temp, &m);
4507
4508 /* Left plane */
4509     vec[0].u1.x = m._14 + m._11;
4510     vec[0].u2.y = m._24 + m._21;
4511     vec[0].u3.z = m._34 + m._31;
4512     origin_plane[0] = m._44 + m._41;
4513
4514 /* Right plane */
4515     vec[1].u1.x = m._14 - m._11;
4516     vec[1].u2.y = m._24 - m._21;
4517     vec[1].u3.z = m._34 - m._31;
4518     origin_plane[1] = m._44 - m._41;
4519
4520 /* Top plane */
4521     vec[2].u1.x = m._14 - m._12;
4522     vec[2].u2.y = m._24 - m._22;
4523     vec[2].u3.z = m._34 - m._32;
4524     origin_plane[2] = m._44 - m._42;
4525
4526 /* Bottom plane */
4527     vec[3].u1.x = m._14 + m._12;
4528     vec[3].u2.y = m._24 + m._22;
4529     vec[3].u3.z = m._34 + m._32;
4530     origin_plane[3] = m._44 + m._42;
4531
4532 /* Front plane */
4533     vec[4].u1.x = m._13;
4534     vec[4].u2.y = m._23;
4535     vec[4].u3.z = m._33;
4536     origin_plane[4] = m._43;
4537
4538 /* Back plane*/
4539     vec[5].u1.x = m._14 - m._13;
4540     vec[5].u2.y = m._24 - m._23;
4541     vec[5].u3.z = m._34 - m._33;
4542     origin_plane[5] = m._44 - m._43;
4543
4544     for(i=0; i<NumSpheres; i++)
4545     {
4546         ReturnValues[i] = 0;
4547         for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4548     }
4549
4550     return D3D_OK;
4551 }
4552
4553 static HRESULT WINAPI IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4554         D3DVECTOR *Centers, D3DVALUE *Radii, DWORD NumSpheres, DWORD Flags, DWORD *ReturnValues)
4555 {
4556     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4557
4558     TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4559             iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4560
4561     return IDirect3DDevice7_ComputeSphereVisibility(&This->IDirect3DDevice7_iface,
4562             Centers, Radii, NumSpheres, Flags, ReturnValues);
4563 }
4564
4565 /*****************************************************************************
4566  * IDirect3DDevice7::GetTexture
4567  *
4568  * Returns the texture interface handle assigned to a texture stage.
4569  * The returned texture is AddRefed. This is taken from old ddraw,
4570  * not checked in Windows.
4571  *
4572  * Version 3 and 7
4573  *
4574  * Params:
4575  *  Stage: Texture stage to read the texture from
4576  *  Texture: Address to store the interface pointer at
4577  *
4578  * Returns:
4579  *  D3D_OK on success
4580  *  DDERR_INVALIDPARAMS if Texture is NULL
4581  *  For details, see IWineD3DDevice::GetTexture
4582  *
4583  *****************************************************************************/
4584 static HRESULT
4585 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4586                                  DWORD Stage,
4587                                  IDirectDrawSurface7 **Texture)
4588 {
4589     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4590     struct wined3d_texture *wined3d_texture;
4591     HRESULT hr;
4592
4593     TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4594
4595     if(!Texture)
4596     {
4597         TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4598         return DDERR_INVALIDPARAMS;
4599     }
4600
4601     wined3d_mutex_lock();
4602     hr = wined3d_device_get_texture(This->wined3d_device, Stage, &wined3d_texture);
4603     if (FAILED(hr) || !wined3d_texture)
4604     {
4605         *Texture = NULL;
4606         wined3d_mutex_unlock();
4607         return hr;
4608     }
4609
4610     *Texture = wined3d_texture_get_parent(wined3d_texture);
4611     IDirectDrawSurface7_AddRef(*Texture);
4612     wined3d_texture_decref(wined3d_texture);
4613     wined3d_mutex_unlock();
4614
4615     return hr;
4616 }
4617
4618 static HRESULT WINAPI
4619 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4620                                  DWORD Stage,
4621                                  IDirectDrawSurface7 **Texture)
4622 {
4623     return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4624 }
4625
4626 static HRESULT WINAPI
4627 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4628                                  DWORD Stage,
4629                                  IDirectDrawSurface7 **Texture)
4630 {
4631     HRESULT hr;
4632     WORD old_fpucw;
4633
4634     old_fpucw = d3d_fpu_setup();
4635     hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4636     set_fpu_control_word(old_fpucw);
4637
4638     return hr;
4639 }
4640
4641 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface, DWORD Stage,
4642         IDirect3DTexture2 **Texture2)
4643 {
4644     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4645     HRESULT ret;
4646     IDirectDrawSurface7 *ret_val;
4647     IDirectDrawSurfaceImpl *ret_val_impl;
4648
4649     TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4650
4651     ret = IDirect3DDevice7_GetTexture(&This->IDirect3DDevice7_iface, Stage, &ret_val);
4652
4653     ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4654     *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4655
4656     TRACE("Returning texture %p.\n", *Texture2);
4657
4658     return ret;
4659 }
4660
4661 /*****************************************************************************
4662  * IDirect3DDevice7::SetTexture
4663  *
4664  * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4665  *
4666  * Version 3 and 7
4667  *
4668  * Params:
4669  *  Stage: The stage to assign the texture to
4670  *  Texture: Interface pointer to the texture surface
4671  *
4672  * Returns
4673  * D3D_OK on success
4674  * For details, see IWineD3DDevice::SetTexture
4675  *
4676  *****************************************************************************/
4677 static HRESULT
4678 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4679                                  DWORD Stage,
4680                                  IDirectDrawSurface7 *Texture)
4681 {
4682     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4683     IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
4684     HRESULT hr;
4685
4686     TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4687
4688     /* Texture may be NULL here */
4689     wined3d_mutex_lock();
4690     hr = wined3d_device_set_texture(This->wined3d_device,
4691             Stage, surf ? surf->wined3d_texture : NULL);
4692     wined3d_mutex_unlock();
4693
4694     return hr;
4695 }
4696
4697 static HRESULT WINAPI
4698 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4699                                  DWORD Stage,
4700                                  IDirectDrawSurface7 *Texture)
4701 {
4702     return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4703 }
4704
4705 static HRESULT WINAPI
4706 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4707                                  DWORD Stage,
4708                                  IDirectDrawSurface7 *Texture)
4709 {
4710     HRESULT hr;
4711     WORD old_fpucw;
4712
4713     old_fpucw = d3d_fpu_setup();
4714     hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4715     set_fpu_control_word(old_fpucw);
4716
4717     return hr;
4718 }
4719
4720 static HRESULT WINAPI
4721 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4722                                  DWORD Stage,
4723                                  IDirect3DTexture2 *Texture2)
4724 {
4725     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4726     IDirectDrawSurfaceImpl *tex = unsafe_impl_from_IDirect3DTexture2(Texture2);
4727     DWORD texmapblend;
4728     HRESULT hr;
4729
4730     TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4731
4732     wined3d_mutex_lock();
4733
4734     if (This->legacyTextureBlending)
4735         IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4736
4737     hr = IDirect3DDevice7_SetTexture(&This->IDirect3DDevice7_iface, Stage, &tex->IDirectDrawSurface7_iface);
4738
4739     if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4740     {
4741         /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4742            See IDirect3DDeviceImpl_3_SetRenderState for details. */
4743         struct wined3d_texture *tex = NULL;
4744         BOOL tex_alpha = FALSE;
4745         DDPIXELFORMAT ddfmt;
4746         HRESULT result;
4747
4748         result = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
4749         if (result == WINED3D_OK && tex)
4750         {
4751             struct wined3d_resource *sub_resource;
4752
4753             if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4754             {
4755                 struct wined3d_resource_desc desc;
4756
4757                 wined3d_resource_get_desc(sub_resource, &desc);
4758                 ddfmt.dwSize = sizeof(ddfmt);
4759                 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4760                 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4761             }
4762
4763             wined3d_texture_decref(tex);
4764         }
4765
4766         /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4767         if (tex_alpha)
4768             wined3d_device_set_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4769         else
4770             wined3d_device_set_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4771     }
4772
4773     wined3d_mutex_unlock();
4774
4775     return hr;
4776 }
4777
4778 static const struct tss_lookup
4779 {
4780     BOOL sampler_state;
4781     DWORD state;
4782 }
4783 tss_lookup[] =
4784 {
4785     {FALSE, WINED3DTSS_FORCE_DWORD},            /*  0, unused */
4786     {FALSE, WINED3DTSS_COLOROP},                /*  1, D3DTSS_COLOROP */
4787     {FALSE, WINED3DTSS_COLORARG1},              /*  2, D3DTSS_COLORARG1 */
4788     {FALSE, WINED3DTSS_COLORARG2},              /*  3, D3DTSS_COLORARG2 */
4789     {FALSE, WINED3DTSS_ALPHAOP},                /*  4, D3DTSS_ALPHAOP */
4790     {FALSE, WINED3DTSS_ALPHAARG1},              /*  5, D3DTSS_ALPHAARG1 */
4791     {FALSE, WINED3DTSS_ALPHAARG2},              /*  6, D3DTSS_ALPHAARG2 */
4792     {FALSE, WINED3DTSS_BUMPENVMAT00},           /*  7, D3DTSS_BUMPENVMAT00 */
4793     {FALSE, WINED3DTSS_BUMPENVMAT01},           /*  8, D3DTSS_BUMPENVMAT01 */
4794     {FALSE, WINED3DTSS_BUMPENVMAT10},           /*  9, D3DTSS_BUMPENVMAT10 */
4795     {FALSE, WINED3DTSS_BUMPENVMAT11},           /* 10, D3DTSS_BUMPENVMAT11 */
4796     {FALSE, WINED3DTSS_TEXCOORDINDEX},          /* 11, D3DTSS_TEXCOORDINDEX */
4797     {TRUE,  WINED3DSAMP_ADDRESSU},              /* 12, D3DTSS_ADDRESS */
4798     {TRUE,  WINED3DSAMP_ADDRESSU},              /* 13, D3DTSS_ADDRESSU */
4799     {TRUE,  WINED3DSAMP_ADDRESSV},              /* 14, D3DTSS_ADDRESSV */
4800     {TRUE,  WINED3DSAMP_BORDERCOLOR},           /* 15, D3DTSS_BORDERCOLOR */
4801     {TRUE,  WINED3DSAMP_MAGFILTER},             /* 16, D3DTSS_MAGFILTER */
4802     {TRUE,  WINED3DSAMP_MINFILTER},             /* 17, D3DTSS_MINFILTER */
4803     {TRUE,  WINED3DSAMP_MIPFILTER},             /* 18, D3DTSS_MIPFILTER */
4804     {TRUE,  WINED3DSAMP_MIPMAPLODBIAS},         /* 19, D3DTSS_MIPMAPLODBIAS */
4805     {TRUE,  WINED3DSAMP_MAXMIPLEVEL},           /* 20, D3DTSS_MAXMIPLEVEL */
4806     {TRUE,  WINED3DSAMP_MAXANISOTROPY},         /* 21, D3DTSS_MAXANISOTROPY */
4807     {FALSE, WINED3DTSS_BUMPENVLSCALE},          /* 22, D3DTSS_BUMPENVLSCALE */
4808     {FALSE, WINED3DTSS_BUMPENVLOFFSET},         /* 23, D3DTSS_BUMPENVLOFFSET */
4809     {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS},  /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4810 };
4811
4812 /*****************************************************************************
4813  * IDirect3DDevice7::GetTextureStageState
4814  *
4815  * Retrieves a state from a texture stage.
4816  *
4817  * Version 3 and 7
4818  *
4819  * Params:
4820  *  Stage: The stage to retrieve the state from
4821  *  TexStageStateType: The state type to retrieve
4822  *  State: Address to store the state's value at
4823  *
4824  * Returns:
4825  *  D3D_OK on success
4826  *  DDERR_INVALIDPARAMS if State is NULL
4827  *  For details, see IWineD3DDevice::GetTextureStageState
4828  *
4829  *****************************************************************************/
4830 static HRESULT
4831 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4832                                            DWORD Stage,
4833                                            D3DTEXTURESTAGESTATETYPE TexStageStateType,
4834                                            DWORD *State)
4835 {
4836     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4837     HRESULT hr;
4838     const struct tss_lookup *l;
4839
4840     TRACE("iface %p, stage %u, state %#x, value %p.\n",
4841             iface, Stage, TexStageStateType, State);
4842
4843     if(!State)
4844         return DDERR_INVALIDPARAMS;
4845
4846     if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4847     {
4848         WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4849         return DD_OK;
4850     }
4851
4852     l = &tss_lookup[TexStageStateType];
4853
4854     wined3d_mutex_lock();
4855
4856     if (l->sampler_state)
4857     {
4858         hr = wined3d_device_get_sampler_state(This->wined3d_device, Stage, l->state, State);
4859
4860         switch(TexStageStateType)
4861         {
4862             /* Mipfilter is a sampler state with different values */
4863             case D3DTSS_MIPFILTER:
4864             {
4865                 switch(*State)
4866                 {
4867                     case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4868                     case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4869                     case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4870                     default:
4871                         ERR("Unexpected mipfilter value %#x\n", *State);
4872                         *State = D3DTFP_NONE;
4873                         break;
4874                 }
4875                 break;
4876             }
4877
4878             /* Magfilter has slightly different values */
4879             case D3DTSS_MAGFILTER:
4880             {
4881                 switch(*State)
4882                 {
4883                     case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4884                     case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4885                     case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4886                     case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4887                     case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4888                     default:
4889                         ERR("Unexpected wined3d mag filter value %#x\n", *State);
4890                         *State = D3DTFG_POINT;
4891                         break;
4892                 }
4893                 break;
4894             }
4895
4896             default:
4897                 break;
4898         }
4899     }
4900     else
4901     {
4902         hr = wined3d_device_get_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4903     }
4904
4905     wined3d_mutex_unlock();
4906
4907     return hr;
4908 }
4909
4910 static HRESULT WINAPI
4911 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4912                                            DWORD Stage,
4913                                            D3DTEXTURESTAGESTATETYPE TexStageStateType,
4914                                            DWORD *State)
4915 {
4916     return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4917 }
4918
4919 static HRESULT WINAPI
4920 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4921                                            DWORD Stage,
4922                                            D3DTEXTURESTAGESTATETYPE TexStageStateType,
4923                                            DWORD *State)
4924 {
4925     HRESULT hr;
4926     WORD old_fpucw;
4927
4928     old_fpucw = d3d_fpu_setup();
4929     hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4930     set_fpu_control_word(old_fpucw);
4931
4932     return hr;
4933 }
4934
4935 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4936         DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD *State)
4937 {
4938     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4939
4940     TRACE("iface %p, stage %u, state %#x, value %p.\n",
4941             iface, Stage, TexStageStateType, State);
4942
4943     return IDirect3DDevice7_GetTextureStageState(&This->IDirect3DDevice7_iface,
4944             Stage, TexStageStateType, State);
4945 }
4946
4947 /*****************************************************************************
4948  * IDirect3DDevice7::SetTextureStageState
4949  *
4950  * Sets a texture stage state. Some stage types need to be handled specially,
4951  * because they do not exist in WineD3D and were moved to another place
4952  *
4953  * Version 3 and 7
4954  *
4955  * Params:
4956  *  Stage: The stage to modify
4957  *  TexStageStateType: The state to change
4958  *  State: The new value for the state
4959  *
4960  * Returns:
4961  *  D3D_OK on success
4962  *  For details, see IWineD3DDevice::SetTextureStageState
4963  *
4964  *****************************************************************************/
4965 static HRESULT
4966 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4967                                            DWORD Stage,
4968                                            D3DTEXTURESTAGESTATETYPE TexStageStateType,
4969                                            DWORD State)
4970 {
4971     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4972     const struct tss_lookup *l;
4973     HRESULT hr;
4974
4975     TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4976             iface, Stage, TexStageStateType, State);
4977
4978     if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4979     {
4980         WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4981         return DD_OK;
4982     }
4983
4984     l = &tss_lookup[TexStageStateType];
4985
4986     wined3d_mutex_lock();
4987
4988     if (l->sampler_state)
4989     {
4990         switch(TexStageStateType)
4991         {
4992             /* Mipfilter is a sampler state with different values */
4993             case D3DTSS_MIPFILTER:
4994             {
4995                 switch(State)
4996                 {
4997                     case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
4998                     case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
4999                     case 0: /* Unchecked */
5000                     case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
5001                     default:
5002                         ERR("Unexpected mipfilter value %d\n", State);
5003                         State = WINED3DTEXF_NONE;
5004                         break;
5005                 }
5006                 break;
5007             }
5008
5009             /* Magfilter has slightly different values */
5010             case D3DTSS_MAGFILTER:
5011             {
5012                 switch(State)
5013                 {
5014                     case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
5015                     case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
5016                     case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
5017                     case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
5018                     case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
5019                     default:
5020                         ERR("Unexpected d3d7 mag filter type %d\n", State);
5021                         State = WINED3DTEXF_POINT;
5022                         break;
5023                 }
5024                 break;
5025             }
5026
5027             case D3DTSS_ADDRESS:
5028                 wined3d_device_set_sampler_state(This->wined3d_device, Stage, WINED3DSAMP_ADDRESSV, State);
5029                 break;
5030
5031             default:
5032                 break;
5033         }
5034
5035         hr = wined3d_device_set_sampler_state(This->wined3d_device, Stage, l->state, State);
5036     }
5037     else
5038     {
5039         hr = wined3d_device_set_texture_stage_state(This->wined3d_device, Stage, l->state, State);
5040     }
5041
5042     wined3d_mutex_unlock();
5043
5044     return hr;
5045 }
5046
5047 static HRESULT WINAPI
5048 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5049                                            DWORD Stage,
5050                                            D3DTEXTURESTAGESTATETYPE TexStageStateType,
5051                                            DWORD State)
5052 {
5053     return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5054 }
5055
5056 static HRESULT WINAPI
5057 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5058                                            DWORD Stage,
5059                                            D3DTEXTURESTAGESTATETYPE TexStageStateType,
5060                                            DWORD State)
5061 {
5062     HRESULT hr;
5063     WORD old_fpucw;
5064
5065     old_fpucw = d3d_fpu_setup();
5066     hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5067     set_fpu_control_word(old_fpucw);
5068
5069     return hr;
5070 }
5071
5072 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
5073         DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD State)
5074 {
5075     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
5076
5077     TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5078             iface, Stage, TexStageStateType, State);
5079
5080     return IDirect3DDevice7_SetTextureStageState(&This->IDirect3DDevice7_iface,
5081             Stage, TexStageStateType, State);
5082 }
5083
5084 /*****************************************************************************
5085  * IDirect3DDevice7::ValidateDevice
5086  *
5087  * SDK: "Reports the device's ability to render the currently set
5088  * texture-blending operations in a single pass". Whatever that means
5089  * exactly...
5090  *
5091  * Version 3 and 7
5092  *
5093  * Params:
5094  *  NumPasses: Address to write the number of necessary passes for the
5095  *             desired effect to.
5096  *
5097  * Returns:
5098  *  D3D_OK on success
5099  *  See IWineD3DDevice::ValidateDevice for more details
5100  *
5101  *****************************************************************************/
5102 static HRESULT
5103 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
5104                                      DWORD *NumPasses)
5105 {
5106     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5107     HRESULT hr;
5108
5109     TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
5110
5111     wined3d_mutex_lock();
5112     hr = wined3d_device_validate_device(This->wined3d_device, NumPasses);
5113     wined3d_mutex_unlock();
5114
5115     return hr;
5116 }
5117
5118 static HRESULT WINAPI
5119 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
5120                                      DWORD *NumPasses)
5121 {
5122     return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5123 }
5124
5125 static HRESULT WINAPI
5126 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
5127                                      DWORD *NumPasses)
5128 {
5129     HRESULT hr;
5130     WORD old_fpucw;
5131
5132     old_fpucw = d3d_fpu_setup();
5133     hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5134     set_fpu_control_word(old_fpucw);
5135
5136     return hr;
5137 }
5138
5139 static HRESULT WINAPI IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *Passes)
5140 {
5141     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
5142
5143     TRACE("iface %p, pass_count %p.\n", iface, Passes);
5144
5145     return IDirect3DDevice7_ValidateDevice(&This->IDirect3DDevice7_iface, Passes);
5146 }
5147
5148 /*****************************************************************************
5149  * IDirect3DDevice7::Clear
5150  *
5151  * Fills the render target, the z buffer and the stencil buffer with a
5152  * clear color / value
5153  *
5154  * Version 7 only
5155  *
5156  * Params:
5157  *  Count: Number of rectangles in Rects must be 0 if Rects is NULL
5158  *  Rects: Rectangles to clear. If NULL, the whole surface is cleared
5159  *  Flags: Some flags, as usual
5160  *  Color: Clear color for the render target
5161  *  Z: Clear value for the Z buffer
5162  *  Stencil: Clear value to store in each stencil buffer entry
5163  *
5164  * Returns:
5165  *  D3D_OK on success
5166  *  For details, see IWineD3DDevice::Clear
5167  *
5168  *****************************************************************************/
5169 static HRESULT IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface, DWORD count,
5170         D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5171 {
5172     const struct wined3d_color c =
5173     {
5174         ((color >> 16) & 0xff) / 255.0f,
5175         ((color >>  8) & 0xff) / 255.0f,
5176         (color & 0xff) / 255.0f,
5177         ((color >> 24) & 0xff) / 255.0f,
5178     };
5179     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5180     HRESULT hr;
5181
5182     TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5183             iface, count, rects, flags, color, z, stencil);
5184
5185     wined3d_mutex_lock();
5186     hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
5187     wined3d_mutex_unlock();
5188
5189     return hr;
5190 }
5191
5192 static HRESULT WINAPI
5193 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5194                             DWORD Count,
5195                             D3DRECT *Rects,
5196                             DWORD Flags,
5197                             D3DCOLOR Color,
5198                             D3DVALUE Z,
5199                             DWORD Stencil)
5200 {
5201     return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5202 }
5203
5204 static HRESULT WINAPI
5205 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5206                             DWORD Count,
5207                             D3DRECT *Rects,
5208                             DWORD Flags,
5209                             D3DCOLOR Color,
5210                             D3DVALUE Z,
5211                             DWORD Stencil)
5212 {
5213     HRESULT hr;
5214     WORD old_fpucw;
5215
5216     old_fpucw = d3d_fpu_setup();
5217     hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5218     set_fpu_control_word(old_fpucw);
5219
5220     return hr;
5221 }
5222
5223 /*****************************************************************************
5224  * IDirect3DDevice7::SetViewport
5225  *
5226  * Sets the current viewport.
5227  *
5228  * Version 7 only, but IDirect3DViewport uses this call for older
5229  * versions
5230  *
5231  * Params:
5232  *  Data: The new viewport to set
5233  *
5234  * Returns:
5235  *  D3D_OK on success
5236  *  DDERR_INVALIDPARAMS if Data is NULL
5237  *  For more details, see IWineDDDevice::SetViewport
5238  *
5239  *****************************************************************************/
5240 static HRESULT
5241 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5242                                   D3DVIEWPORT7 *Data)
5243 {
5244     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5245     HRESULT hr;
5246
5247     TRACE("iface %p, viewport %p.\n", iface, Data);
5248
5249     if(!Data)
5250         return DDERR_INVALIDPARAMS;
5251
5252     /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5253     wined3d_mutex_lock();
5254     hr = wined3d_device_set_viewport(This->wined3d_device, (struct wined3d_viewport *)Data);
5255     wined3d_mutex_unlock();
5256
5257     return hr;
5258 }
5259
5260 static HRESULT WINAPI
5261 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5262                                   D3DVIEWPORT7 *Data)
5263 {
5264     return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5265 }
5266
5267 static HRESULT WINAPI
5268 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5269                                   D3DVIEWPORT7 *Data)
5270 {
5271     HRESULT hr;
5272     WORD old_fpucw;
5273
5274     old_fpucw = d3d_fpu_setup();
5275     hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5276     set_fpu_control_word(old_fpucw);
5277
5278     return hr;
5279 }
5280
5281 /*****************************************************************************
5282  * IDirect3DDevice::GetViewport
5283  *
5284  * Returns the current viewport
5285  *
5286  * Version 7
5287  *
5288  * Params:
5289  *  Data: D3D7Viewport structure to write the viewport information to
5290  *
5291  * Returns:
5292  *  D3D_OK on success
5293  *  DDERR_INVALIDPARAMS if Data is NULL
5294  *  For more details, see IWineD3DDevice::GetViewport
5295  *
5296  *****************************************************************************/
5297 static HRESULT
5298 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5299                                   D3DVIEWPORT7 *Data)
5300 {
5301     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5302     HRESULT hr;
5303
5304     TRACE("iface %p, viewport %p.\n", iface, Data);
5305
5306     if(!Data)
5307         return DDERR_INVALIDPARAMS;
5308
5309     /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5310     wined3d_mutex_lock();
5311     hr = wined3d_device_get_viewport(This->wined3d_device, (struct wined3d_viewport *)Data);
5312     wined3d_mutex_unlock();
5313
5314     return hr_ddraw_from_wined3d(hr);
5315 }
5316
5317 static HRESULT WINAPI
5318 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5319                                   D3DVIEWPORT7 *Data)
5320 {
5321     return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5322 }
5323
5324 static HRESULT WINAPI
5325 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5326                                   D3DVIEWPORT7 *Data)
5327 {
5328     HRESULT hr;
5329     WORD old_fpucw;
5330
5331     old_fpucw = d3d_fpu_setup();
5332     hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5333     set_fpu_control_word(old_fpucw);
5334
5335     return hr;
5336 }
5337
5338 /*****************************************************************************
5339  * IDirect3DDevice7::SetMaterial
5340  *
5341  * Sets the Material
5342  *
5343  * Version 7
5344  *
5345  * Params:
5346  *  Mat: The material to set
5347  *
5348  * Returns:
5349  *  D3D_OK on success
5350  *  DDERR_INVALIDPARAMS if Mat is NULL.
5351  *  For more details, see IWineD3DDevice::SetMaterial
5352  *
5353  *****************************************************************************/
5354 static HRESULT
5355 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5356                                   D3DMATERIAL7 *Mat)
5357 {
5358     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5359     HRESULT hr;
5360
5361     TRACE("iface %p, material %p.\n", iface, Mat);
5362
5363     if (!Mat) return DDERR_INVALIDPARAMS;
5364
5365     wined3d_mutex_lock();
5366     /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5367     hr = wined3d_device_set_material(This->wined3d_device, (struct wined3d_material *)Mat);
5368     wined3d_mutex_unlock();
5369
5370     return hr_ddraw_from_wined3d(hr);
5371 }
5372
5373 static HRESULT WINAPI
5374 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5375                                   D3DMATERIAL7 *Mat)
5376 {
5377     return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5378 }
5379
5380 static HRESULT WINAPI
5381 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5382                                   D3DMATERIAL7 *Mat)
5383 {
5384     HRESULT hr;
5385     WORD old_fpucw;
5386
5387     old_fpucw = d3d_fpu_setup();
5388     hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5389     set_fpu_control_word(old_fpucw);
5390
5391     return hr;
5392 }
5393
5394 /*****************************************************************************
5395  * IDirect3DDevice7::GetMaterial
5396  *
5397  * Returns the current material
5398  *
5399  * Version 7
5400  *
5401  * Params:
5402  *  Mat: D3DMATERIAL7 structure to write the material parameters to
5403  *
5404  * Returns:
5405  *  D3D_OK on success
5406  *  DDERR_INVALIDPARAMS if Mat is NULL
5407  *  For more details, see IWineD3DDevice::GetMaterial
5408  *
5409  *****************************************************************************/
5410 static HRESULT
5411 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5412                                   D3DMATERIAL7 *Mat)
5413 {
5414     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5415     HRESULT hr;
5416
5417     TRACE("iface %p, material %p.\n", iface, Mat);
5418
5419     wined3d_mutex_lock();
5420     /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5421     hr = wined3d_device_get_material(This->wined3d_device, (struct wined3d_material *)Mat);
5422     wined3d_mutex_unlock();
5423
5424     return hr_ddraw_from_wined3d(hr);
5425 }
5426
5427 static HRESULT WINAPI
5428 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5429                                   D3DMATERIAL7 *Mat)
5430 {
5431     return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5432 }
5433
5434 static HRESULT WINAPI
5435 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5436                                   D3DMATERIAL7 *Mat)
5437 {
5438     HRESULT hr;
5439     WORD old_fpucw;
5440
5441     old_fpucw = d3d_fpu_setup();
5442     hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5443     set_fpu_control_word(old_fpucw);
5444
5445     return hr;
5446 }
5447
5448 /*****************************************************************************
5449  * IDirect3DDevice7::SetLight
5450  *
5451  * Assigns a light to a light index, but doesn't activate it yet.
5452  *
5453  * Version 7, IDirect3DLight uses this method for older versions
5454  *
5455  * Params:
5456  *  LightIndex: The index of the new light
5457  *  Light: A D3DLIGHT7 structure describing the light
5458  *
5459  * Returns:
5460  *  D3D_OK on success
5461  *  For more details, see IWineD3DDevice::SetLight
5462  *
5463  *****************************************************************************/
5464 static HRESULT
5465 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5466                                DWORD LightIndex,
5467                                D3DLIGHT7 *Light)
5468 {
5469     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5470     HRESULT hr;
5471
5472     TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5473
5474     wined3d_mutex_lock();
5475     /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5476     hr = wined3d_device_set_light(This->wined3d_device, LightIndex, (struct wined3d_light *)Light);
5477     wined3d_mutex_unlock();
5478
5479     return hr_ddraw_from_wined3d(hr);
5480 }
5481
5482 static HRESULT WINAPI
5483 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5484                                DWORD LightIndex,
5485                                D3DLIGHT7 *Light)
5486 {
5487     return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5488 }
5489
5490 static HRESULT WINAPI
5491 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5492                                DWORD LightIndex,
5493                                D3DLIGHT7 *Light)
5494 {
5495     HRESULT hr;
5496     WORD old_fpucw;
5497
5498     old_fpucw = d3d_fpu_setup();
5499     hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5500     set_fpu_control_word(old_fpucw);
5501
5502     return hr;
5503 }
5504
5505 /*****************************************************************************
5506  * IDirect3DDevice7::GetLight
5507  *
5508  * Returns the light assigned to a light index
5509  *
5510  * Params:
5511  *  Light: Structure to write the light information to
5512  *
5513  * Returns:
5514  *  D3D_OK on success
5515  *  DDERR_INVALIDPARAMS if Light is NULL
5516  *  For details, see IWineD3DDevice::GetLight
5517  *
5518  *****************************************************************************/
5519 static HRESULT
5520 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5521                                DWORD LightIndex,
5522                                D3DLIGHT7 *Light)
5523 {
5524     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5525     HRESULT rc;
5526
5527     TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5528
5529     wined3d_mutex_lock();
5530     /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5531     rc =  wined3d_device_get_light(This->wined3d_device, LightIndex, (struct wined3d_light *)Light);
5532     wined3d_mutex_unlock();
5533
5534     /* Translate the result. WineD3D returns other values than D3D7 */
5535     return hr_ddraw_from_wined3d(rc);
5536 }
5537
5538 static HRESULT WINAPI
5539 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5540                                DWORD LightIndex,
5541                                D3DLIGHT7 *Light)
5542 {
5543     return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5544 }
5545
5546 static HRESULT WINAPI
5547 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5548                                DWORD LightIndex,
5549                                D3DLIGHT7 *Light)
5550 {
5551     HRESULT hr;
5552     WORD old_fpucw;
5553
5554     old_fpucw = d3d_fpu_setup();
5555     hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5556     set_fpu_control_word(old_fpucw);
5557
5558     return hr;
5559 }
5560
5561 /*****************************************************************************
5562  * IDirect3DDevice7::BeginStateBlock
5563  *
5564  * Begins recording to a stateblock
5565  *
5566  * Version 7
5567  *
5568  * Returns:
5569  *  D3D_OK on success
5570  *  For details see IWineD3DDevice::BeginStateBlock
5571  *
5572  *****************************************************************************/
5573 static HRESULT
5574 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5575 {
5576     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5577     HRESULT hr;
5578
5579     TRACE("iface %p.\n", iface);
5580
5581     wined3d_mutex_lock();
5582     hr = wined3d_device_begin_stateblock(This->wined3d_device);
5583     wined3d_mutex_unlock();
5584
5585     return hr_ddraw_from_wined3d(hr);
5586 }
5587
5588 static HRESULT WINAPI
5589 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5590 {
5591     return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5592 }
5593
5594 static HRESULT WINAPI
5595 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5596 {
5597     HRESULT hr;
5598     WORD old_fpucw;
5599
5600     old_fpucw = d3d_fpu_setup();
5601     hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5602     set_fpu_control_word(old_fpucw);
5603
5604     return hr;
5605 }
5606
5607 /*****************************************************************************
5608  * IDirect3DDevice7::EndStateBlock
5609  *
5610  * Stops recording to a state block and returns the created stateblock
5611  * handle.
5612  *
5613  * Version 7
5614  *
5615  * Params:
5616  *  BlockHandle: Address to store the stateblock's handle to
5617  *
5618  * Returns:
5619  *  D3D_OK on success
5620  *  DDERR_INVALIDPARAMS if BlockHandle is NULL
5621  *  See IWineD3DDevice::EndStateBlock for more details
5622  *
5623  *****************************************************************************/
5624 static HRESULT
5625 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5626                                     DWORD *BlockHandle)
5627 {
5628     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5629     struct wined3d_stateblock *wined3d_sb;
5630     HRESULT hr;
5631     DWORD h;
5632
5633     TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5634
5635     if(!BlockHandle)
5636     {
5637         WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5638         return DDERR_INVALIDPARAMS;
5639     }
5640
5641     wined3d_mutex_lock();
5642
5643     hr = wined3d_device_end_stateblock(This->wined3d_device, &wined3d_sb);
5644     if (FAILED(hr))
5645     {
5646         WARN("Failed to end stateblock, hr %#x.\n", hr);
5647         wined3d_mutex_unlock();
5648         *BlockHandle = 0;
5649         return hr_ddraw_from_wined3d(hr);
5650     }
5651
5652     h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5653     if (h == DDRAW_INVALID_HANDLE)
5654     {
5655         ERR("Failed to allocate a stateblock handle.\n");
5656         wined3d_stateblock_decref(wined3d_sb);
5657         wined3d_mutex_unlock();
5658         *BlockHandle = 0;
5659         return DDERR_OUTOFMEMORY;
5660     }
5661
5662     wined3d_mutex_unlock();
5663     *BlockHandle = h + 1;
5664
5665     return hr_ddraw_from_wined3d(hr);
5666 }
5667
5668 static HRESULT WINAPI
5669 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5670                                     DWORD *BlockHandle)
5671 {
5672     return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5673 }
5674
5675 static HRESULT WINAPI
5676 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5677                                     DWORD *BlockHandle)
5678 {
5679     HRESULT hr;
5680     WORD old_fpucw;
5681
5682     old_fpucw = d3d_fpu_setup();
5683     hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5684     set_fpu_control_word(old_fpucw);
5685
5686     return hr;
5687 }
5688
5689 /*****************************************************************************
5690  * IDirect3DDevice7::PreLoad
5691  *
5692  * Allows the app to signal that a texture will be used soon, to allow
5693  * the Direct3DDevice to load it to the video card in the meantime.
5694  *
5695  * Version 7
5696  *
5697  * Params:
5698  *  Texture: The texture to preload
5699  *
5700  * Returns:
5701  *  D3D_OK on success
5702  *  DDERR_INVALIDPARAMS if Texture is NULL
5703  *  See IWineD3DSurface::PreLoad for details
5704  *
5705  *****************************************************************************/
5706 static HRESULT
5707 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5708                               IDirectDrawSurface7 *Texture)
5709 {
5710     IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
5711
5712     TRACE("iface %p, texture %p.\n", iface, Texture);
5713
5714     if(!Texture)
5715         return DDERR_INVALIDPARAMS;
5716
5717     wined3d_mutex_lock();
5718     wined3d_surface_preload(surf->wined3d_surface);
5719     wined3d_mutex_unlock();
5720
5721     return D3D_OK;
5722 }
5723
5724 static HRESULT WINAPI
5725 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5726                               IDirectDrawSurface7 *Texture)
5727 {
5728     return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5729 }
5730
5731 static HRESULT WINAPI
5732 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5733                               IDirectDrawSurface7 *Texture)
5734 {
5735     HRESULT hr;
5736     WORD old_fpucw;
5737
5738     old_fpucw = d3d_fpu_setup();
5739     hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5740     set_fpu_control_word(old_fpucw);
5741
5742     return hr;
5743 }
5744
5745 /*****************************************************************************
5746  * IDirect3DDevice7::ApplyStateBlock
5747  *
5748  * Activates the state stored in a state block handle.
5749  *
5750  * Params:
5751  *  BlockHandle: The stateblock handle to activate
5752  *
5753  * Returns:
5754  *  D3D_OK on success
5755  *  D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5756  *
5757  *****************************************************************************/
5758 static HRESULT
5759 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5760                                       DWORD BlockHandle)
5761 {
5762     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5763     struct wined3d_stateblock *wined3d_sb;
5764     HRESULT hr;
5765
5766     TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5767
5768     wined3d_mutex_lock();
5769     wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5770     if (!wined3d_sb)
5771     {
5772         WARN("Invalid stateblock handle.\n");
5773         wined3d_mutex_unlock();
5774         return D3DERR_INVALIDSTATEBLOCK;
5775     }
5776
5777     hr = wined3d_stateblock_apply(wined3d_sb);
5778     wined3d_mutex_unlock();
5779
5780     return hr_ddraw_from_wined3d(hr);
5781 }
5782
5783 static HRESULT WINAPI
5784 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5785                                       DWORD BlockHandle)
5786 {
5787     return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5788 }
5789
5790 static HRESULT WINAPI
5791 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5792                                       DWORD BlockHandle)
5793 {
5794     HRESULT hr;
5795     WORD old_fpucw;
5796
5797     old_fpucw = d3d_fpu_setup();
5798     hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5799     set_fpu_control_word(old_fpucw);
5800
5801     return hr;
5802 }
5803
5804 /*****************************************************************************
5805  * IDirect3DDevice7::CaptureStateBlock
5806  *
5807  * Updates a stateblock's values to the values currently set for the device
5808  *
5809  * Version 7
5810  *
5811  * Params:
5812  *  BlockHandle: Stateblock to update
5813  *
5814  * Returns:
5815  *  D3D_OK on success
5816  *  D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5817  *  See IWineD3DDevice::CaptureStateBlock for more details
5818  *
5819  *****************************************************************************/
5820 static HRESULT
5821 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5822                                         DWORD BlockHandle)
5823 {
5824     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5825     struct wined3d_stateblock *wined3d_sb;
5826     HRESULT hr;
5827
5828     TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5829
5830     wined3d_mutex_lock();
5831     wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5832     if (!wined3d_sb)
5833     {
5834         WARN("Invalid stateblock handle.\n");
5835         wined3d_mutex_unlock();
5836         return D3DERR_INVALIDSTATEBLOCK;
5837     }
5838
5839     hr = wined3d_stateblock_capture(wined3d_sb);
5840     wined3d_mutex_unlock();
5841
5842     return hr_ddraw_from_wined3d(hr);
5843 }
5844
5845 static HRESULT WINAPI
5846 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5847                                         DWORD BlockHandle)
5848 {
5849     return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5850 }
5851
5852 static HRESULT WINAPI
5853 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5854                                         DWORD BlockHandle)
5855 {
5856     HRESULT hr;
5857     WORD old_fpucw;
5858
5859     old_fpucw = d3d_fpu_setup();
5860     hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5861     set_fpu_control_word(old_fpucw);
5862
5863     return hr;
5864 }
5865
5866 /*****************************************************************************
5867  * IDirect3DDevice7::DeleteStateBlock
5868  *
5869  * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5870  *
5871  * Version 7
5872  *
5873  * Params:
5874  *  BlockHandle: Stateblock handle to delete
5875  *
5876  * Returns:
5877  *  D3D_OK on success
5878  *  D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5879  *
5880  *****************************************************************************/
5881 static HRESULT
5882 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5883                                        DWORD BlockHandle)
5884 {
5885     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5886     struct wined3d_stateblock *wined3d_sb;
5887     ULONG ref;
5888
5889     TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5890
5891     wined3d_mutex_lock();
5892
5893     wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5894     if (!wined3d_sb)
5895     {
5896         WARN("Invalid stateblock handle.\n");
5897         wined3d_mutex_unlock();
5898         return D3DERR_INVALIDSTATEBLOCK;
5899     }
5900
5901     if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5902     {
5903         ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5904     }
5905
5906     wined3d_mutex_unlock();
5907
5908     return D3D_OK;
5909 }
5910
5911 static HRESULT WINAPI
5912 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5913                                        DWORD BlockHandle)
5914 {
5915     return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5916 }
5917
5918 static HRESULT WINAPI
5919 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5920                                        DWORD BlockHandle)
5921 {
5922     HRESULT hr;
5923     WORD old_fpucw;
5924
5925     old_fpucw = d3d_fpu_setup();
5926     hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5927     set_fpu_control_word(old_fpucw);
5928
5929     return hr;
5930 }
5931
5932 /*****************************************************************************
5933  * IDirect3DDevice7::CreateStateBlock
5934  *
5935  * Creates a new state block handle.
5936  *
5937  * Version 7
5938  *
5939  * Params:
5940  *  Type: The state block type
5941  *  BlockHandle: Address to write the created handle to
5942  *
5943  * Returns:
5944  *   D3D_OK on success
5945  *   DDERR_INVALIDPARAMS if BlockHandle is NULL
5946  *
5947  *****************************************************************************/
5948 static HRESULT
5949 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5950                                        D3DSTATEBLOCKTYPE Type,
5951                                        DWORD *BlockHandle)
5952 {
5953     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5954     struct wined3d_stateblock *wined3d_sb;
5955     HRESULT hr;
5956     DWORD h;
5957
5958     TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5959
5960     if(!BlockHandle)
5961     {
5962         WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5963         return DDERR_INVALIDPARAMS;
5964     }
5965     if(Type != D3DSBT_ALL         && Type != D3DSBT_PIXELSTATE &&
5966        Type != D3DSBT_VERTEXSTATE                              ) {
5967         WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5968         return DDERR_INVALIDPARAMS;
5969     }
5970
5971     wined3d_mutex_lock();
5972
5973     /* The D3DSTATEBLOCKTYPE enum is fine here. */
5974     hr = wined3d_stateblock_create(This->wined3d_device, Type, &wined3d_sb);
5975     if (FAILED(hr))
5976     {
5977         WARN("Failed to create stateblock, hr %#x.\n", hr);
5978         wined3d_mutex_unlock();
5979         return hr_ddraw_from_wined3d(hr);
5980     }
5981
5982     h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5983     if (h == DDRAW_INVALID_HANDLE)
5984     {
5985         ERR("Failed to allocate stateblock handle.\n");
5986         wined3d_stateblock_decref(wined3d_sb);
5987         wined3d_mutex_unlock();
5988         return DDERR_OUTOFMEMORY;
5989     }
5990
5991     *BlockHandle = h + 1;
5992     wined3d_mutex_unlock();
5993
5994     return hr_ddraw_from_wined3d(hr);
5995 }
5996
5997 static HRESULT WINAPI
5998 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5999                                        D3DSTATEBLOCKTYPE Type,
6000                                        DWORD *BlockHandle)
6001 {
6002     return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6003 }
6004
6005 static HRESULT WINAPI
6006 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
6007                                        D3DSTATEBLOCKTYPE Type,
6008                                        DWORD *BlockHandle)
6009 {
6010     HRESULT hr;
6011     WORD old_fpucw;
6012
6013     old_fpucw = d3d_fpu_setup();
6014     hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6015     set_fpu_control_word(old_fpucw);
6016
6017     return hr;
6018 }
6019
6020 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6021 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
6022                                 IDirectDrawSurfaceImpl *src)
6023 {
6024     IDirectDrawSurfaceImpl *src_level, *dest_level;
6025     IDirectDrawSurface7 *temp;
6026     DDSURFACEDESC2 ddsd;
6027     BOOL levelFound; /* at least one suitable sublevel in dest found */
6028
6029     /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
6030      * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
6031      * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
6032      */
6033     levelFound = FALSE;
6034
6035     src_level = src;
6036     dest_level = dest;
6037
6038     for (;src_level && dest_level;)
6039     {
6040         if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6041             src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6042         {
6043             levelFound = TRUE;
6044
6045             ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6046             ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6047             IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6048
6049             if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6050
6051             dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6052         }
6053
6054         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6055         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6056         IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6057
6058         if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6059
6060         src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6061     }
6062
6063     if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6064     if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6065
6066     return !dest_level && levelFound;
6067 }
6068
6069 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6070 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
6071                               IDirectDrawSurfaceImpl *dest,
6072                               IDirectDrawSurfaceImpl *src,
6073                               const POINT *DestPoint,
6074                               const RECT *SrcRect)
6075 {
6076     IDirectDrawSurfaceImpl *src_level, *dest_level;
6077     IDirectDrawSurface7 *temp;
6078     DDSURFACEDESC2 ddsd;
6079     POINT point;
6080     RECT src_rect;
6081     HRESULT hr;
6082     IDirectDrawPalette *pal = NULL, *pal_src = NULL;
6083     DWORD ckeyflag;
6084     DDCOLORKEY ddckey;
6085
6086     /* Copy palette, if possible. */
6087     IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
6088     IDirectDrawSurface7_GetPalette(&dest->IDirectDrawSurface7_iface, &pal);
6089
6090     if (pal_src != NULL && pal != NULL)
6091     {
6092         PALETTEENTRY palent[256];
6093
6094         IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
6095         IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
6096     }
6097
6098     if (pal) IDirectDrawPalette_Release(pal);
6099     if (pal_src) IDirectDrawPalette_Release(pal_src);
6100
6101     /* Copy colorkeys, if present. */
6102     for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6103     {
6104         hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6105
6106         if (SUCCEEDED(hr))
6107         {
6108             IDirectDrawSurface7_SetColorKey(&dest->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6109         }
6110     }
6111
6112     src_level = src;
6113     dest_level = dest;
6114
6115     point = *DestPoint;
6116     src_rect = *SrcRect;
6117
6118     for (;src_level && dest_level;)
6119     {
6120         if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6121             src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6122         {
6123             UINT src_w = src_rect.right - src_rect.left;
6124             UINT src_h = src_rect.bottom - src_rect.top;
6125             RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
6126
6127             if (FAILED(hr = wined3d_surface_blt(dest_level->wined3d_surface, &dst_rect,
6128                     src_level->wined3d_surface, &src_rect, 0, NULL, WINED3DTEXF_POINT)))
6129                 ERR("Blit failed, hr %#x.\n", hr);
6130
6131             ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6132             ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6133             IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6134
6135             if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6136
6137             dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6138         }
6139
6140         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6141         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6142         IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6143
6144         if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6145
6146         src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6147
6148         point.x /= 2;
6149         point.y /= 2;
6150
6151         src_rect.top /= 2;
6152         src_rect.left /= 2;
6153         src_rect.right = (src_rect.right + 1) / 2;
6154         src_rect.bottom = (src_rect.bottom + 1) / 2;
6155     }
6156
6157     if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6158     if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6159 }
6160
6161 /*****************************************************************************
6162  * IDirect3DDevice7::Load
6163  *
6164  * Loads a rectangular area from the source into the destination texture.
6165  * It can also copy the source to the faces of a cubic environment map
6166  *
6167  * Version 7
6168  *
6169  * Params:
6170  *  DestTex: Destination texture
6171  *  DestPoint: Point in the destination where the source image should be
6172  *             written to
6173  *  SrcTex: Source texture
6174  *  SrcRect: Source rectangle
6175  *  Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6176  *          DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6177  *          DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6178  *
6179  * Returns:
6180  *  D3D_OK on success
6181  *  DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6182  *
6183  *
6184  *****************************************************************************/
6185
6186 static HRESULT
6187 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6188                            IDirectDrawSurface7 *DestTex,
6189                            POINT *DestPoint,
6190                            IDirectDrawSurface7 *SrcTex,
6191                            RECT *SrcRect,
6192                            DWORD Flags)
6193 {
6194     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6195     IDirectDrawSurfaceImpl *dest = unsafe_impl_from_IDirectDrawSurface7(DestTex);
6196     IDirectDrawSurfaceImpl *src = unsafe_impl_from_IDirectDrawSurface7(SrcTex);
6197     POINT destpoint;
6198     RECT srcrect;
6199
6200     TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6201             iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6202
6203     if( (!src) || (!dest) )
6204         return DDERR_INVALIDPARAMS;
6205
6206     wined3d_mutex_lock();
6207
6208     if (SrcRect) srcrect = *SrcRect;
6209     else
6210     {
6211         srcrect.left = srcrect.top = 0;
6212         srcrect.right = src->surface_desc.dwWidth;
6213         srcrect.bottom = src->surface_desc.dwHeight;
6214     }
6215
6216     if (DestPoint) destpoint = *DestPoint;
6217     else
6218     {
6219         destpoint.x = destpoint.y = 0;
6220     }
6221     /* Check bad dimensions. DestPoint is validated against src, not dest, because
6222      * destination can be a subset of mip levels, in which case actual coordinates used
6223      * for it may be divided. If any dimension of dest is larger than source, it can't be
6224      * mip level subset, so an error can be returned early.
6225      */
6226     if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6227         srcrect.right > src->surface_desc.dwWidth ||
6228         srcrect.bottom > src->surface_desc.dwHeight ||
6229         destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6230         destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6231         dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6232         dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6233     {
6234         wined3d_mutex_unlock();
6235         return DDERR_INVALIDPARAMS;
6236     }
6237
6238     /* Must be top level surfaces. */
6239     if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6240         dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6241     {
6242         wined3d_mutex_unlock();
6243         return DDERR_INVALIDPARAMS;
6244     }
6245
6246     if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6247     {
6248         DWORD src_face_flag, dest_face_flag;
6249         IDirectDrawSurfaceImpl *src_face, *dest_face;
6250         IDirectDrawSurface7 *temp;
6251         DDSURFACEDESC2 ddsd;
6252         int i;
6253
6254         if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6255         {
6256             wined3d_mutex_unlock();
6257             return DDERR_INVALIDPARAMS;
6258         }
6259
6260         /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6261          * time it's actual surface loading. */
6262         for (i = 0; i < 2; i++)
6263         {
6264             dest_face = dest;
6265             src_face = src;
6266
6267             for (;dest_face && src_face;)
6268             {
6269                 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6270                 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6271
6272                 if (src_face_flag == dest_face_flag)
6273                 {
6274                     if (i == 0)
6275                     {
6276                         /* Destination mip levels must be subset of source mip levels. */
6277                         if (!is_mip_level_subset(dest_face, src_face))
6278                         {
6279                             wined3d_mutex_unlock();
6280                             return DDERR_INVALIDPARAMS;
6281                         }
6282                     }
6283                     else if (Flags & dest_face_flag)
6284                     {
6285                         copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6286                     }
6287
6288                     if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6289                     {
6290                         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6291                         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6292                         IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6293
6294                         if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6295
6296                         src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6297                     }
6298                     else
6299                     {
6300                         if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6301
6302                         src_face = NULL;
6303                     }
6304                 }
6305
6306                 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6307                 {
6308                     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6309                     ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6310                     IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6311
6312                     if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6313
6314                     dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6315                 }
6316                 else
6317                 {
6318                     if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6319
6320                     dest_face = NULL;
6321                 }
6322             }
6323
6324             if (i == 0)
6325             {
6326                 /* Native returns error if src faces are not subset of dest faces. */
6327                 if (src_face)
6328                 {
6329                     wined3d_mutex_unlock();
6330                     return DDERR_INVALIDPARAMS;
6331                 }
6332             }
6333         }
6334
6335         wined3d_mutex_unlock();
6336         return D3D_OK;
6337     }
6338     else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6339     {
6340         wined3d_mutex_unlock();
6341         return DDERR_INVALIDPARAMS;
6342     }
6343
6344     /* Handle non cube map textures. */
6345
6346     /* Destination mip levels must be subset of source mip levels. */
6347     if (!is_mip_level_subset(dest, src))
6348     {
6349         wined3d_mutex_unlock();
6350         return DDERR_INVALIDPARAMS;
6351     }
6352
6353     copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6354
6355     wined3d_mutex_unlock();
6356
6357     return D3D_OK;
6358 }
6359
6360 static HRESULT WINAPI
6361 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6362                            IDirectDrawSurface7 *DestTex,
6363                            POINT *DestPoint,
6364                            IDirectDrawSurface7 *SrcTex,
6365                            RECT *SrcRect,
6366                            DWORD Flags)
6367 {
6368     return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6369 }
6370
6371 static HRESULT WINAPI
6372 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6373                            IDirectDrawSurface7 *DestTex,
6374                            POINT *DestPoint,
6375                            IDirectDrawSurface7 *SrcTex,
6376                            RECT *SrcRect,
6377                            DWORD Flags)
6378 {
6379     HRESULT hr;
6380     WORD old_fpucw;
6381
6382     old_fpucw = d3d_fpu_setup();
6383     hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6384     set_fpu_control_word(old_fpucw);
6385
6386     return hr;
6387 }
6388
6389 /*****************************************************************************
6390  * IDirect3DDevice7::LightEnable
6391  *
6392  * Enables or disables a light
6393  *
6394  * Version 7, IDirect3DLight uses this method too.
6395  *
6396  * Params:
6397  *  LightIndex: The index of the light to enable / disable
6398  *  Enable: Enable or disable the light
6399  *
6400  * Returns:
6401  *  D3D_OK on success
6402  *  For more details, see IWineD3DDevice::SetLightEnable
6403  *
6404  *****************************************************************************/
6405 static HRESULT
6406 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6407                                   DWORD LightIndex,
6408                                   BOOL Enable)
6409 {
6410     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6411     HRESULT hr;
6412
6413     TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6414
6415     wined3d_mutex_lock();
6416     hr = wined3d_device_set_light_enable(This->wined3d_device, LightIndex, Enable);
6417     wined3d_mutex_unlock();
6418
6419     return hr_ddraw_from_wined3d(hr);
6420 }
6421
6422 static HRESULT WINAPI
6423 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6424                                   DWORD LightIndex,
6425                                   BOOL Enable)
6426 {
6427     return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6428 }
6429
6430 static HRESULT WINAPI
6431 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6432                                   DWORD LightIndex,
6433                                   BOOL Enable)
6434 {
6435     HRESULT hr;
6436     WORD old_fpucw;
6437
6438     old_fpucw = d3d_fpu_setup();
6439     hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6440     set_fpu_control_word(old_fpucw);
6441
6442     return hr;
6443 }
6444
6445 /*****************************************************************************
6446  * IDirect3DDevice7::GetLightEnable
6447  *
6448  * Retrieves if the light with the given index is enabled or not
6449  *
6450  * Version 7
6451  *
6452  * Params:
6453  *  LightIndex: Index of desired light
6454  *  Enable: Pointer to a BOOL which contains the result
6455  *
6456  * Returns:
6457  *  D3D_OK on success
6458  *  DDERR_INVALIDPARAMS if Enable is NULL
6459  *  See IWineD3DDevice::GetLightEnable for more details
6460  *
6461  *****************************************************************************/
6462 static HRESULT
6463 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6464                                      DWORD LightIndex,
6465                                      BOOL* Enable)
6466 {
6467     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6468     HRESULT hr;
6469
6470     TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6471
6472     if(!Enable)
6473         return DDERR_INVALIDPARAMS;
6474
6475     wined3d_mutex_lock();
6476     hr = wined3d_device_get_light_enable(This->wined3d_device, LightIndex, Enable);
6477     wined3d_mutex_unlock();
6478
6479     return hr_ddraw_from_wined3d(hr);
6480 }
6481
6482 static HRESULT WINAPI
6483 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6484                                      DWORD LightIndex,
6485                                      BOOL* Enable)
6486 {
6487     return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6488 }
6489
6490 static HRESULT WINAPI
6491 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6492                                      DWORD LightIndex,
6493                                      BOOL* Enable)
6494 {
6495     HRESULT hr;
6496     WORD old_fpucw;
6497
6498     old_fpucw = d3d_fpu_setup();
6499     hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6500     set_fpu_control_word(old_fpucw);
6501
6502     return hr;
6503 }
6504
6505 /*****************************************************************************
6506  * IDirect3DDevice7::SetClipPlane
6507  *
6508  * Sets custom clipping plane
6509  *
6510  * Version 7
6511  *
6512  * Params:
6513  *  Index: The index of the clipping plane
6514  *  PlaneEquation: An equation defining the clipping plane
6515  *
6516  * Returns:
6517  *  D3D_OK on success
6518  *  DDERR_INVALIDPARAMS if PlaneEquation is NULL
6519  *  See IWineD3DDevice::SetClipPlane for more details
6520  *
6521  *****************************************************************************/
6522 static HRESULT
6523 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6524                                    DWORD Index,
6525                                    D3DVALUE* PlaneEquation)
6526 {
6527     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6528     HRESULT hr;
6529
6530     TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6531
6532     if(!PlaneEquation)
6533         return DDERR_INVALIDPARAMS;
6534
6535     wined3d_mutex_lock();
6536     hr = wined3d_device_set_clip_plane(This->wined3d_device, Index, PlaneEquation);
6537     wined3d_mutex_unlock();
6538
6539     return hr;
6540 }
6541
6542 static HRESULT WINAPI
6543 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6544                                    DWORD Index,
6545                                    D3DVALUE* PlaneEquation)
6546 {
6547     return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6548 }
6549
6550 static HRESULT WINAPI
6551 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6552                                    DWORD Index,
6553                                    D3DVALUE* PlaneEquation)
6554 {
6555     HRESULT hr;
6556     WORD old_fpucw;
6557
6558     old_fpucw = d3d_fpu_setup();
6559     hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6560     set_fpu_control_word(old_fpucw);
6561
6562     return hr;
6563 }
6564
6565 /*****************************************************************************
6566  * IDirect3DDevice7::GetClipPlane
6567  *
6568  * Returns the clipping plane with a specific index
6569  *
6570  * Params:
6571  *  Index: The index of the desired plane
6572  *  PlaneEquation: Address to store the plane equation to
6573  *
6574  * Returns:
6575  *  D3D_OK on success
6576  *  DDERR_INVALIDPARAMS if PlaneEquation is NULL
6577  *  See IWineD3DDevice::GetClipPlane for more details
6578  *
6579  *****************************************************************************/
6580 static HRESULT
6581 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6582                                    DWORD Index,
6583                                    D3DVALUE* PlaneEquation)
6584 {
6585     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6586     HRESULT hr;
6587
6588     TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6589
6590     if(!PlaneEquation)
6591         return DDERR_INVALIDPARAMS;
6592
6593     wined3d_mutex_lock();
6594     hr = wined3d_device_get_clip_plane(This->wined3d_device, Index, PlaneEquation);
6595     wined3d_mutex_unlock();
6596
6597     return hr;
6598 }
6599
6600 static HRESULT WINAPI
6601 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6602                                    DWORD Index,
6603                                    D3DVALUE* PlaneEquation)
6604 {
6605     return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6606 }
6607
6608 static HRESULT WINAPI
6609 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6610                                    DWORD Index,
6611                                    D3DVALUE* PlaneEquation)
6612 {
6613     HRESULT hr;
6614     WORD old_fpucw;
6615
6616     old_fpucw = d3d_fpu_setup();
6617     hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6618     set_fpu_control_word(old_fpucw);
6619
6620     return hr;
6621 }
6622
6623 /*****************************************************************************
6624  * IDirect3DDevice7::GetInfo
6625  *
6626  * Retrieves some information about the device. The DirectX sdk says that
6627  * this version returns S_FALSE for all retail builds of DirectX, that's what
6628  * this implementation does.
6629  *
6630  * Params:
6631  *  DevInfoID: Information type requested
6632  *  DevInfoStruct: Pointer to a structure to store the info to
6633  *  Size: Size of the structure
6634  *
6635  * Returns:
6636  *  S_FALSE, because it's a non-debug driver
6637  *
6638  *****************************************************************************/
6639 static HRESULT WINAPI
6640 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6641                               DWORD DevInfoID,
6642                               void *DevInfoStruct,
6643                               DWORD Size)
6644 {
6645     TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6646             iface, DevInfoID, DevInfoStruct, Size);
6647
6648     if (TRACE_ON(ddraw))
6649     {
6650         TRACE(" info requested : ");
6651         switch (DevInfoID)
6652         {
6653             case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6654             case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6655             case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6656             default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6657         }
6658     }
6659
6660     return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6661 }
6662
6663 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6664  * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6665  * are not duplicated.
6666
6667  * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6668  * has already been setup for optimal d3d operation.
6669
6670  * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6671  * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6672  * by Sacrifice (game). */
6673 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6674 {
6675     /*** IUnknown Methods ***/
6676     IDirect3DDeviceImpl_7_QueryInterface,
6677     IDirect3DDeviceImpl_7_AddRef,
6678     IDirect3DDeviceImpl_7_Release,
6679     /*** IDirect3DDevice7 ***/
6680     IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6681     IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6682     IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6683     IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6684     IDirect3DDeviceImpl_7_GetDirect3D,
6685     IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6686     IDirect3DDeviceImpl_7_GetRenderTarget,
6687     IDirect3DDeviceImpl_7_Clear_FPUSetup,
6688     IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6689     IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6690     IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6691     IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6692     IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6693     IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6694     IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6695     IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6696     IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6697     IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6698     IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6699     IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6700     IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6701     IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6702     IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6703     IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6704     IDirect3DDeviceImpl_7_SetClipStatus,
6705     IDirect3DDeviceImpl_7_GetClipStatus,
6706     IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6707     IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6708     IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6709     IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6710     IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6711     IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6712     IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6713     IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6714     IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6715     IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6716     IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6717     IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6718     IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6719     IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6720     IDirect3DDeviceImpl_7_Load_FPUSetup,
6721     IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6722     IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6723     IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6724     IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6725     IDirect3DDeviceImpl_7_GetInfo
6726 };
6727
6728 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6729 {
6730     /*** IUnknown Methods ***/
6731     IDirect3DDeviceImpl_7_QueryInterface,
6732     IDirect3DDeviceImpl_7_AddRef,
6733     IDirect3DDeviceImpl_7_Release,
6734     /*** IDirect3DDevice7 ***/
6735     IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6736     IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6737     IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6738     IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6739     IDirect3DDeviceImpl_7_GetDirect3D,
6740     IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6741     IDirect3DDeviceImpl_7_GetRenderTarget,
6742     IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6743     IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6744     IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6745     IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6746     IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6747     IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6748     IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6749     IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6750     IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6751     IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6752     IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6753     IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6754     IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6755     IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6756     IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6757     IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6758     IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6759     IDirect3DDeviceImpl_7_SetClipStatus,
6760     IDirect3DDeviceImpl_7_GetClipStatus,
6761     IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6762     IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6763     IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6764     IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6765     IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6766     IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6767     IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6768     IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6769     IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6770     IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6771     IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6772     IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6773     IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6774     IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6775     IDirect3DDeviceImpl_7_Load_FPUPreserve,
6776     IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6777     IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6778     IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6779     IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6780     IDirect3DDeviceImpl_7_GetInfo
6781 };
6782
6783 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6784 {
6785     /*** IUnknown Methods ***/
6786     IDirect3DDeviceImpl_3_QueryInterface,
6787     IDirect3DDeviceImpl_3_AddRef,
6788     IDirect3DDeviceImpl_3_Release,
6789     /*** IDirect3DDevice3 ***/
6790     IDirect3DDeviceImpl_3_GetCaps,
6791     IDirect3DDeviceImpl_3_GetStats,
6792     IDirect3DDeviceImpl_3_AddViewport,
6793     IDirect3DDeviceImpl_3_DeleteViewport,
6794     IDirect3DDeviceImpl_3_NextViewport,
6795     IDirect3DDeviceImpl_3_EnumTextureFormats,
6796     IDirect3DDeviceImpl_3_BeginScene,
6797     IDirect3DDeviceImpl_3_EndScene,
6798     IDirect3DDeviceImpl_3_GetDirect3D,
6799     IDirect3DDeviceImpl_3_SetCurrentViewport,
6800     IDirect3DDeviceImpl_3_GetCurrentViewport,
6801     IDirect3DDeviceImpl_3_SetRenderTarget,
6802     IDirect3DDeviceImpl_3_GetRenderTarget,
6803     IDirect3DDeviceImpl_3_Begin,
6804     IDirect3DDeviceImpl_3_BeginIndexed,
6805     IDirect3DDeviceImpl_3_Vertex,
6806     IDirect3DDeviceImpl_3_Index,
6807     IDirect3DDeviceImpl_3_End,
6808     IDirect3DDeviceImpl_3_GetRenderState,
6809     IDirect3DDeviceImpl_3_SetRenderState,
6810     IDirect3DDeviceImpl_3_GetLightState,
6811     IDirect3DDeviceImpl_3_SetLightState,
6812     IDirect3DDeviceImpl_3_SetTransform,
6813     IDirect3DDeviceImpl_3_GetTransform,
6814     IDirect3DDeviceImpl_3_MultiplyTransform,
6815     IDirect3DDeviceImpl_3_DrawPrimitive,
6816     IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6817     IDirect3DDeviceImpl_3_SetClipStatus,
6818     IDirect3DDeviceImpl_3_GetClipStatus,
6819     IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6820     IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6821     IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6822     IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6823     IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6824     IDirect3DDeviceImpl_3_GetTexture,
6825     IDirect3DDeviceImpl_3_SetTexture,
6826     IDirect3DDeviceImpl_3_GetTextureStageState,
6827     IDirect3DDeviceImpl_3_SetTextureStageState,
6828     IDirect3DDeviceImpl_3_ValidateDevice
6829 };
6830
6831 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6832 {
6833     /*** IUnknown Methods ***/
6834     IDirect3DDeviceImpl_2_QueryInterface,
6835     IDirect3DDeviceImpl_2_AddRef,
6836     IDirect3DDeviceImpl_2_Release,
6837     /*** IDirect3DDevice2 ***/
6838     IDirect3DDeviceImpl_2_GetCaps,
6839     IDirect3DDeviceImpl_2_SwapTextureHandles,
6840     IDirect3DDeviceImpl_2_GetStats,
6841     IDirect3DDeviceImpl_2_AddViewport,
6842     IDirect3DDeviceImpl_2_DeleteViewport,
6843     IDirect3DDeviceImpl_2_NextViewport,
6844     IDirect3DDeviceImpl_2_EnumTextureFormats,
6845     IDirect3DDeviceImpl_2_BeginScene,
6846     IDirect3DDeviceImpl_2_EndScene,
6847     IDirect3DDeviceImpl_2_GetDirect3D,
6848     IDirect3DDeviceImpl_2_SetCurrentViewport,
6849     IDirect3DDeviceImpl_2_GetCurrentViewport,
6850     IDirect3DDeviceImpl_2_SetRenderTarget,
6851     IDirect3DDeviceImpl_2_GetRenderTarget,
6852     IDirect3DDeviceImpl_2_Begin,
6853     IDirect3DDeviceImpl_2_BeginIndexed,
6854     IDirect3DDeviceImpl_2_Vertex,
6855     IDirect3DDeviceImpl_2_Index,
6856     IDirect3DDeviceImpl_2_End,
6857     IDirect3DDeviceImpl_2_GetRenderState,
6858     IDirect3DDeviceImpl_2_SetRenderState,
6859     IDirect3DDeviceImpl_2_GetLightState,
6860     IDirect3DDeviceImpl_2_SetLightState,
6861     IDirect3DDeviceImpl_2_SetTransform,
6862     IDirect3DDeviceImpl_2_GetTransform,
6863     IDirect3DDeviceImpl_2_MultiplyTransform,
6864     IDirect3DDeviceImpl_2_DrawPrimitive,
6865     IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6866     IDirect3DDeviceImpl_2_SetClipStatus,
6867     IDirect3DDeviceImpl_2_GetClipStatus
6868 };
6869
6870 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6871 {
6872     /*** IUnknown Methods ***/
6873     IDirect3DDeviceImpl_1_QueryInterface,
6874     IDirect3DDeviceImpl_1_AddRef,
6875     IDirect3DDeviceImpl_1_Release,
6876     /*** IDirect3DDevice1 ***/
6877     IDirect3DDeviceImpl_1_Initialize,
6878     IDirect3DDeviceImpl_1_GetCaps,
6879     IDirect3DDeviceImpl_1_SwapTextureHandles,
6880     IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6881     IDirect3DDeviceImpl_1_GetStats,
6882     IDirect3DDeviceImpl_1_Execute,
6883     IDirect3DDeviceImpl_1_AddViewport,
6884     IDirect3DDeviceImpl_1_DeleteViewport,
6885     IDirect3DDeviceImpl_1_NextViewport,
6886     IDirect3DDeviceImpl_1_Pick,
6887     IDirect3DDeviceImpl_1_GetPickRecords,
6888     IDirect3DDeviceImpl_1_EnumTextureFormats,
6889     IDirect3DDeviceImpl_1_CreateMatrix,
6890     IDirect3DDeviceImpl_1_SetMatrix,
6891     IDirect3DDeviceImpl_1_GetMatrix,
6892     IDirect3DDeviceImpl_1_DeleteMatrix,
6893     IDirect3DDeviceImpl_1_BeginScene,
6894     IDirect3DDeviceImpl_1_EndScene,
6895     IDirect3DDeviceImpl_1_GetDirect3D
6896 };
6897
6898 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6899 {
6900     if (!iface) return NULL;
6901     assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6902     return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice7_iface);
6903 }
6904
6905 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6906 {
6907     if (!iface) return NULL;
6908     assert(iface->lpVtbl == &d3d_device3_vtbl);
6909     return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice3_iface);
6910 }
6911
6912 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6913 {
6914     if (!iface) return NULL;
6915     assert(iface->lpVtbl == &d3d_device2_vtbl);
6916     return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice2_iface);
6917 }
6918
6919 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6920 {
6921     if (!iface) return NULL;
6922     assert(iface->lpVtbl == &d3d_device1_vtbl);
6923     return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice_iface);
6924 }
6925
6926 /*****************************************************************************
6927  * IDirect3DDeviceImpl_UpdateDepthStencil
6928  *
6929  * Checks the current render target for attached depth stencils and sets the
6930  * WineD3D depth stencil accordingly.
6931  *
6932  * Returns:
6933  *  The depth stencil state to set if creating the device
6934  *
6935  *****************************************************************************/
6936 enum wined3d_depth_buffer_type IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6937 {
6938     IDirectDrawSurface7 *depthStencil = NULL;
6939     IDirectDrawSurfaceImpl *dsi;
6940     static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6941
6942     IDirectDrawSurface7_GetAttachedSurface(&This->target->IDirectDrawSurface7_iface, &depthcaps, &depthStencil);
6943     if(!depthStencil)
6944     {
6945         TRACE("Setting wined3d depth stencil to NULL\n");
6946         wined3d_device_set_depth_stencil(This->wined3d_device, NULL);
6947         return WINED3D_ZB_FALSE;
6948     }
6949
6950     dsi = impl_from_IDirectDrawSurface7(depthStencil);
6951     TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
6952     wined3d_device_set_depth_stencil(This->wined3d_device, dsi->wined3d_surface);
6953
6954     IDirectDrawSurface7_Release(depthStencil);
6955     return WINED3D_ZB_TRUE;
6956 }
6957
6958 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
6959 {
6960     static const D3DMATRIX ident =
6961     {
6962         1.0f, 0.0f, 0.0f, 0.0f,
6963         0.0f, 1.0f, 0.0f, 0.0f,
6964         0.0f, 0.0f, 1.0f, 0.0f,
6965         0.0f, 0.0f, 0.0f, 1.0f,
6966     };
6967     HRESULT hr;
6968
6969     if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6970         device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6971     else
6972         device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
6973
6974     device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6975     device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6976     device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6977     device->ref = 1;
6978     device->ddraw = ddraw;
6979     device->target = target;
6980     list_init(&device->viewport_list);
6981
6982     if (!ddraw_handle_table_init(&device->handle_table, 64))
6983     {
6984         ERR("Failed to initialize handle table.\n");
6985         return DDERR_OUTOFMEMORY;
6986     }
6987
6988     device->legacyTextureBlending = FALSE;
6989     device->legacy_projection = ident;
6990     device->legacy_clipspace = ident;
6991
6992     /* Create an index buffer, it's needed for indexed drawing */
6993     hr = wined3d_buffer_create_ib(ddraw->wined3d_device, 0x40000 /* Length. Don't know how long it should be */,
6994             WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, NULL,
6995             &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
6996     if (FAILED(hr))
6997     {
6998         ERR("Failed to create an index buffer, hr %#x.\n", hr);
6999         ddraw_handle_table_destroy(&device->handle_table);
7000         return hr;
7001     }
7002
7003     /* This is for convenience. */
7004     device->wined3d_device = ddraw->wined3d_device;
7005     wined3d_device_incref(ddraw->wined3d_device);
7006
7007     /* Render to the back buffer */
7008     hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
7009     if (FAILED(hr))
7010     {
7011         ERR("Failed to set render target, hr %#x.\n", hr);
7012         wined3d_buffer_decref(device->indexbuffer);
7013         ddraw_handle_table_destroy(&device->handle_table);
7014         return hr;
7015     }
7016
7017     /* FIXME: This is broken. The target AddRef() makes some sense, because
7018      * we store a pointer during initialization, but then that's also where
7019      * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
7020     /* AddRef the render target. Also AddRef the render target from ddraw,
7021      * because if it is released before the app releases the D3D device, the
7022      * D3D capabilities of wined3d will be uninitialized, which has bad effects.
7023      *
7024      * In most cases, those surfaces are the same anyway, but this will simply
7025      * add another ref which is released when the device is destroyed. */
7026     IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
7027
7028     ddraw->d3ddevice = device;
7029
7030     wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE,
7031             IDirect3DDeviceImpl_UpdateDepthStencil(device));
7032
7033     return D3D_OK;
7034 }