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