urlmon: Implemented IUriBuilder_RemoveProperties.
[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      */
4350     hr = IWineD3DBuffer_GetDesc(This->indexbuffer, &desc);
4351     if(desc.Size < IndexCount * sizeof(WORD))
4352     {
4353         UINT size = max(desc.Size * 2, IndexCount * sizeof(WORD));
4354         IWineD3DBuffer *buffer;
4355         IParentImpl *parent;
4356
4357         TRACE("Growing index buffer to %u bytes\n", size);
4358
4359         parent = IWineD3DBuffer_GetParent(This->indexbuffer);
4360         hr = IWineD3DDevice_CreateIndexBuffer(This->wineD3DDevice, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4361                 WINED3DPOOL_DEFAULT, parent, &ddraw_null_wined3d_parent_ops, &buffer);
4362         if (FAILED(hr))
4363         {
4364             ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4365             LeaveCriticalSection(&ddraw_cs);
4366             return hr;
4367         }
4368
4369         IWineD3DBuffer_Release(This->indexbuffer);
4370         This->indexbuffer = buffer;
4371
4372         parent->child = (IUnknown *)buffer;
4373     }
4374
4375     /* copy the index stream into the index buffer.
4376      * A new IWineD3DDevice method could be created
4377      * which takes an user pointer containing the indices
4378      * or a SetData-Method for the index buffer, which
4379      * overrides the index buffer data with our pointer.
4380      */
4381     hr = IWineD3DBuffer_Map(This->indexbuffer,
4382                             0 /* OffSetToLock */,
4383                             IndexCount * sizeof(WORD),
4384                             (BYTE **) &LockedIndices,
4385                             0 /* Flags */);
4386     if(hr != D3D_OK)
4387     {
4388         ERR("(%p) IWineD3DBuffer::Map failed with hr = %08x\n", This, hr);
4389         LeaveCriticalSection(&ddraw_cs);
4390         return hr;
4391     }
4392     memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4393     hr = IWineD3DBuffer_Unmap(This->indexbuffer);
4394     if(hr != D3D_OK)
4395     {
4396         ERR("(%p) IWineD3DBuffer::Unmap failed with hr = %08x\n", This, hr);
4397         LeaveCriticalSection(&ddraw_cs);
4398         return hr;
4399     }
4400
4401     /* Set the index stream */
4402     IWineD3DDevice_SetBaseVertexIndex(This->wineD3DDevice, StartVertex);
4403     hr = IWineD3DDevice_SetIndexBuffer(This->wineD3DDevice, This->indexbuffer,
4404                                    WINED3DFMT_R16_UINT);
4405
4406     /* Set the vertex stream source */
4407     hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4408                                         0 /* StreamNumber */,
4409                                         vb->wineD3DVertexBuffer,
4410                                         0 /* offset, we pass this to DrawIndexedPrimitive */,
4411                                         stride);
4412     if(hr != D3D_OK)
4413     {
4414         ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4415         LeaveCriticalSection(&ddraw_cs);
4416         return hr;
4417     }
4418
4419
4420     IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4421     hr = IWineD3DDevice_DrawIndexedPrimitive(This->wineD3DDevice, 0 /* StartIndex */, IndexCount);
4422
4423     LeaveCriticalSection(&ddraw_cs);
4424     return hr;
4425 }
4426
4427 static HRESULT WINAPI
4428 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4429                                              D3DPRIMITIVETYPE PrimitiveType,
4430                                              IDirect3DVertexBuffer7 *D3DVertexBuf,
4431                                              DWORD StartVertex,
4432                                              DWORD NumVertices,
4433                                              WORD *Indices,
4434                                              DWORD IndexCount,
4435                                              DWORD Flags)
4436 {
4437     return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4438 }
4439
4440 static HRESULT WINAPI
4441 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4442                                              D3DPRIMITIVETYPE PrimitiveType,
4443                                              IDirect3DVertexBuffer7 *D3DVertexBuf,
4444                                              DWORD StartVertex,
4445                                              DWORD NumVertices,
4446                                              WORD *Indices,
4447                                              DWORD IndexCount,
4448                                              DWORD Flags)
4449 {
4450     HRESULT hr;
4451     WORD old_fpucw;
4452
4453     old_fpucw = d3d_fpu_setup();
4454     hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4455     set_fpu_control_word(old_fpucw);
4456
4457     return hr;
4458 }
4459
4460 static HRESULT WINAPI
4461 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4462                                                    D3DPRIMITIVETYPE PrimitiveType,
4463                                                    IDirect3DVertexBuffer *D3DVertexBuf,
4464                                                    WORD *Indices,
4465                                                    DWORD IndexCount,
4466                                                    DWORD Flags)
4467 {
4468     IDirect3DVertexBufferImpl *VB = vb_from_vb1(D3DVertexBuf);
4469
4470     TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4471             iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4472
4473     return IDirect3DDevice7_DrawIndexedPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4474             PrimitiveType, (IDirect3DVertexBuffer7 *)VB, 0, IndexCount, Indices, IndexCount, Flags);
4475 }
4476
4477 /*****************************************************************************
4478  * IDirect3DDevice7::ComputeSphereVisibility
4479  *
4480  * Calculates the visibility of spheres in the current viewport. The spheres
4481  * are passed in the Centers and Radii arrays, the results are passed back
4482  * in the ReturnValues array. Return values are either completely visible,
4483  * partially visible or completely invisible.
4484  * The return value consist of a combination of D3DCLIP_* flags, or it's
4485  * 0 if the sphere is completely visible(according to the SDK, not checked)
4486  *
4487  * Version 3 and 7
4488  *
4489  * Params:
4490  *  Centers: Array containing the sphere centers
4491  *  Radii: Array containing the sphere radii
4492  *  NumSpheres: The number of centers and radii in the arrays
4493  *  Flags: Some flags
4494  *  ReturnValues: Array to write the results to
4495  *
4496  * Returns:
4497  *  D3D_OK
4498  *  (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4499  *  (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4500  *  is singular)
4501  *
4502  *****************************************************************************/
4503
4504 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4505 {
4506     float distance, norm;
4507
4508     norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4509     distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4510
4511     if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4512     if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT  | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4513     return 0;
4514 }
4515
4516 static HRESULT WINAPI
4517 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4518                                               D3DVECTOR *Centers,
4519                                               D3DVALUE *Radii,
4520                                               DWORD NumSpheres,
4521                                               DWORD Flags,
4522                                               DWORD *ReturnValues)
4523 {
4524     D3DMATRIX m, temp;
4525     D3DVALUE origin_plane[6];
4526     D3DVECTOR vec[6];
4527     HRESULT hr;
4528     UINT i, j;
4529
4530     TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4531             iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4532
4533     hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4534     if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4535     hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4536     if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4537     multiply_matrix_D3D_way(&m, &m, &temp);
4538
4539     hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4540     if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4541     multiply_matrix_D3D_way(&m, &m, &temp);
4542
4543 /* Left plane */
4544     vec[0].u1.x = m._14 + m._11;
4545     vec[0].u2.y = m._24 + m._21;
4546     vec[0].u3.z = m._34 + m._31;
4547     origin_plane[0] = m._44 + m._41;
4548
4549 /* Right plane */
4550     vec[1].u1.x = m._14 - m._11;
4551     vec[1].u2.y = m._24 - m._21;
4552     vec[1].u3.z = m._34 - m._31;
4553     origin_plane[1] = m._44 - m._41;
4554
4555 /* Top plane */
4556     vec[2].u1.x = m._14 - m._12;
4557     vec[2].u2.y = m._24 - m._22;
4558     vec[2].u3.z = m._34 - m._32;
4559     origin_plane[2] = m._44 - m._42;
4560
4561 /* Bottom plane */
4562     vec[3].u1.x = m._14 + m._12;
4563     vec[3].u2.y = m._24 + m._22;
4564     vec[3].u3.z = m._34 + m._32;
4565     origin_plane[3] = m._44 + m._42;
4566
4567 /* Front plane */
4568     vec[4].u1.x = m._13;
4569     vec[4].u2.y = m._23;
4570     vec[4].u3.z = m._33;
4571     origin_plane[4] = m._43;
4572
4573 /* Back plane*/
4574     vec[5].u1.x = m._14 - m._13;
4575     vec[5].u2.y = m._24 - m._23;
4576     vec[5].u3.z = m._34 - m._33;
4577     origin_plane[5] = m._44 - m._43;
4578
4579     for(i=0; i<NumSpheres; i++)
4580     {
4581         ReturnValues[i] = 0;
4582         for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4583     }
4584
4585     return D3D_OK;
4586 }
4587
4588 static HRESULT WINAPI
4589 Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4590                                                     D3DVECTOR *Centers,
4591                                                     D3DVALUE *Radii,
4592                                                     DWORD NumSpheres,
4593                                                     DWORD Flags,
4594                                                     DWORD *ReturnValues)
4595 {
4596     TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4597             iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4598
4599     return IDirect3DDevice7_ComputeSphereVisibility((IDirect3DDevice7 *)device_from_device3(iface),
4600             Centers, Radii, NumSpheres, Flags, ReturnValues);
4601 }
4602
4603 /*****************************************************************************
4604  * IDirect3DDevice7::GetTexture
4605  *
4606  * Returns the texture interface handle assigned to a texture stage.
4607  * The returned texture is AddRefed. This is taken from old ddraw,
4608  * not checked in Windows.
4609  *
4610  * Version 3 and 7
4611  *
4612  * Params:
4613  *  Stage: Texture stage to read the texture from
4614  *  Texture: Address to store the interface pointer at
4615  *
4616  * Returns:
4617  *  D3D_OK on success
4618  *  DDERR_INVALIDPARAMS if Texture is NULL
4619  *  For details, see IWineD3DDevice::GetTexture
4620  *
4621  *****************************************************************************/
4622 static HRESULT
4623 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4624                                  DWORD Stage,
4625                                  IDirectDrawSurface7 **Texture)
4626 {
4627     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4628     IWineD3DBaseTexture *Surf;
4629     HRESULT hr;
4630
4631     TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4632
4633     if(!Texture)
4634     {
4635         TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4636         return DDERR_INVALIDPARAMS;
4637     }
4638
4639     EnterCriticalSection(&ddraw_cs);
4640     hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, Stage, &Surf);
4641     if( (hr != D3D_OK) || (!Surf) )
4642     {
4643         *Texture = NULL;
4644         LeaveCriticalSection(&ddraw_cs);
4645         return hr;
4646     }
4647
4648     *Texture = IWineD3DBaseTexture_GetParent(Surf);
4649     IDirectDrawSurface7_AddRef(*Texture);
4650     LeaveCriticalSection(&ddraw_cs);
4651     return hr;
4652 }
4653
4654 static HRESULT WINAPI
4655 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4656                                  DWORD Stage,
4657                                  IDirectDrawSurface7 **Texture)
4658 {
4659     return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4660 }
4661
4662 static HRESULT WINAPI
4663 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4664                                  DWORD Stage,
4665                                  IDirectDrawSurface7 **Texture)
4666 {
4667     HRESULT hr;
4668     WORD old_fpucw;
4669
4670     old_fpucw = d3d_fpu_setup();
4671     hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4672     set_fpu_control_word(old_fpucw);
4673
4674     return hr;
4675 }
4676
4677 static HRESULT WINAPI
4678 Thunk_IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface,
4679                                        DWORD Stage,
4680                                        IDirect3DTexture2 **Texture2)
4681 {
4682     HRESULT ret;
4683     IDirectDrawSurface7 *ret_val;
4684
4685     TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4686
4687     ret = IDirect3DDevice7_GetTexture((IDirect3DDevice7 *)device_from_device3(iface), Stage, &ret_val);
4688
4689     *Texture2 = ret_val ? (IDirect3DTexture2 *)&((IDirectDrawSurfaceImpl *)ret_val)->IDirect3DTexture2_vtbl : NULL;
4690
4691     TRACE("Returning texture %p.\n", *Texture2);
4692
4693     return ret;
4694 }
4695
4696 /*****************************************************************************
4697  * IDirect3DDevice7::SetTexture
4698  *
4699  * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4700  *
4701  * Version 3 and 7
4702  *
4703  * Params:
4704  *  Stage: The stage to assign the texture to
4705  *  Texture: Interface pointer to the texture surface
4706  *
4707  * Returns
4708  * D3D_OK on success
4709  * For details, see IWineD3DDevice::SetTexture
4710  *
4711  *****************************************************************************/
4712 static HRESULT
4713 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4714                                  DWORD Stage,
4715                                  IDirectDrawSurface7 *Texture)
4716 {
4717     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4718     IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
4719     HRESULT hr;
4720
4721     TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4722
4723     /* Texture may be NULL here */
4724     EnterCriticalSection(&ddraw_cs);
4725     hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
4726                                    Stage,
4727                                    surf ? surf->wineD3DTexture : NULL);
4728     LeaveCriticalSection(&ddraw_cs);
4729     return hr;
4730 }
4731
4732 static HRESULT WINAPI
4733 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4734                                  DWORD Stage,
4735                                  IDirectDrawSurface7 *Texture)
4736 {
4737     return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4738 }
4739
4740 static HRESULT WINAPI
4741 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4742                                  DWORD Stage,
4743                                  IDirectDrawSurface7 *Texture)
4744 {
4745     HRESULT hr;
4746     WORD old_fpucw;
4747
4748     old_fpucw = d3d_fpu_setup();
4749     hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4750     set_fpu_control_word(old_fpucw);
4751
4752     return hr;
4753 }
4754
4755 static HRESULT WINAPI
4756 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4757                                  DWORD Stage,
4758                                  IDirect3DTexture2 *Texture2)
4759 {
4760     IDirect3DDeviceImpl *This = device_from_device3(iface);
4761     IDirectDrawSurfaceImpl *tex = Texture2 ? surface_from_texture2(Texture2) : NULL;
4762     DWORD texmapblend;
4763     HRESULT hr;
4764
4765     TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4766
4767     EnterCriticalSection(&ddraw_cs);
4768
4769     if (This->legacyTextureBlending)
4770         IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4771
4772     hr = IDirect3DDevice7_SetTexture((IDirect3DDevice7 *)This, Stage, (IDirectDrawSurface7 *)tex);
4773
4774     if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4775     {
4776         /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4777            See IDirect3DDeviceImpl_3_SetRenderState for details. */
4778         BOOL tex_alpha = FALSE;
4779         IWineD3DBaseTexture *tex = NULL;
4780         WINED3DSURFACE_DESC desc;
4781         DDPIXELFORMAT ddfmt;
4782         HRESULT result;
4783
4784         result = IWineD3DDevice_GetTexture(This->wineD3DDevice,
4785                                     0,
4786                                     &tex);
4787
4788         if(result == WINED3D_OK && tex)
4789         {
4790             memset(&desc, 0, sizeof(desc));
4791             result = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
4792             if (SUCCEEDED(result))
4793             {
4794                 ddfmt.dwSize = sizeof(ddfmt);
4795                 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4796                 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4797             }
4798
4799             IWineD3DBaseTexture_Release(tex);
4800         }
4801
4802         /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4803         if (tex_alpha)
4804             IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4805         else
4806             IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4807     }
4808
4809     LeaveCriticalSection(&ddraw_cs);
4810
4811     return hr;
4812 }
4813
4814 static const struct tss_lookup
4815 {
4816     BOOL sampler_state;
4817     DWORD state;
4818 }
4819 tss_lookup[] =
4820 {
4821     {FALSE, WINED3DTSS_FORCE_DWORD},            /*  0, unused */
4822     {FALSE, WINED3DTSS_COLOROP},                /*  1, D3DTSS_COLOROP */
4823     {FALSE, WINED3DTSS_COLORARG1},              /*  2, D3DTSS_COLORARG1 */
4824     {FALSE, WINED3DTSS_COLORARG2},              /*  3, D3DTSS_COLORARG2 */
4825     {FALSE, WINED3DTSS_ALPHAOP},                /*  4, D3DTSS_ALPHAOP */
4826     {FALSE, WINED3DTSS_ALPHAARG1},              /*  5, D3DTSS_ALPHAARG1 */
4827     {FALSE, WINED3DTSS_ALPHAARG2},              /*  6, D3DTSS_ALPHAARG2 */
4828     {FALSE, WINED3DTSS_BUMPENVMAT00},           /*  7, D3DTSS_BUMPENVMAT00 */
4829     {FALSE, WINED3DTSS_BUMPENVMAT01},           /*  8, D3DTSS_BUMPENVMAT01 */
4830     {FALSE, WINED3DTSS_BUMPENVMAT10},           /*  9, D3DTSS_BUMPENVMAT10 */
4831     {FALSE, WINED3DTSS_BUMPENVMAT11},           /* 10, D3DTSS_BUMPENVMAT11 */
4832     {FALSE, WINED3DTSS_TEXCOORDINDEX},          /* 11, D3DTSS_TEXCOORDINDEX */
4833     {TRUE,  WINED3DSAMP_ADDRESSU},              /* 12, D3DTSS_ADDRESS */
4834     {TRUE,  WINED3DSAMP_ADDRESSU},              /* 13, D3DTSS_ADDRESSU */
4835     {TRUE,  WINED3DSAMP_ADDRESSV},              /* 14, D3DTSS_ADDRESSV */
4836     {TRUE,  WINED3DSAMP_BORDERCOLOR},           /* 15, D3DTSS_BORDERCOLOR */
4837     {TRUE,  WINED3DSAMP_MAGFILTER},             /* 16, D3DTSS_MAGFILTER */
4838     {TRUE,  WINED3DSAMP_MINFILTER},             /* 17, D3DTSS_MINFILTER */
4839     {TRUE,  WINED3DSAMP_MIPFILTER},             /* 18, D3DTSS_MIPFILTER */
4840     {TRUE,  WINED3DSAMP_MIPMAPLODBIAS},         /* 19, D3DTSS_MIPMAPLODBIAS */
4841     {TRUE,  WINED3DSAMP_MAXMIPLEVEL},           /* 20, D3DTSS_MAXMIPLEVEL */
4842     {TRUE,  WINED3DSAMP_MAXANISOTROPY},         /* 21, D3DTSS_MAXANISOTROPY */
4843     {FALSE, WINED3DTSS_BUMPENVLSCALE},          /* 22, D3DTSS_BUMPENVLSCALE */
4844     {FALSE, WINED3DTSS_BUMPENVLOFFSET},         /* 23, D3DTSS_BUMPENVLOFFSET */
4845     {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS},  /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4846 };
4847
4848 /*****************************************************************************
4849  * IDirect3DDevice7::GetTextureStageState
4850  *
4851  * Retrieves a state from a texture stage.
4852  *
4853  * Version 3 and 7
4854  *
4855  * Params:
4856  *  Stage: The stage to retrieve the state from
4857  *  TexStageStateType: The state type to retrieve
4858  *  State: Address to store the state's value at
4859  *
4860  * Returns:
4861  *  D3D_OK on success
4862  *  DDERR_INVALIDPARAMS if State is NULL
4863  *  For details, see IWineD3DDevice::GetTextureStageState
4864  *
4865  *****************************************************************************/
4866 static HRESULT
4867 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4868                                            DWORD Stage,
4869                                            D3DTEXTURESTAGESTATETYPE TexStageStateType,
4870                                            DWORD *State)
4871 {
4872     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4873     HRESULT hr;
4874     const struct tss_lookup *l = &tss_lookup[TexStageStateType];
4875
4876     TRACE("iface %p, stage %u, state %#x, value %p.\n",
4877             iface, Stage, TexStageStateType, State);
4878
4879     if(!State)
4880         return DDERR_INVALIDPARAMS;
4881
4882     if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4883     {
4884         WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4885         *State = 0;
4886         return DD_OK;
4887     }
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 = &tss_lookup[TexStageStateType];
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     EnterCriticalSection(&ddraw_cs);
5020
5021     if (l->sampler_state)
5022     {
5023         switch(TexStageStateType)
5024         {
5025             /* Mipfilter is a sampler state with different values */
5026             case D3DTSS_MIPFILTER:
5027             {
5028                 switch(State)
5029                 {
5030                     case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
5031                     case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
5032                     case 0: /* Unchecked */
5033                     case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
5034                     default:
5035                         ERR("Unexpected mipfilter value %d\n", State);
5036                         State = WINED3DTEXF_NONE;
5037                         break;
5038                 }
5039                 break;
5040             }
5041
5042             /* Magfilter has slightly different values */
5043             case D3DTSS_MAGFILTER:
5044             {
5045                 switch(State)
5046                 {
5047                     case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
5048                     case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
5049                     case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
5050                     case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
5051                     case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
5052                     default:
5053                         ERR("Unexpected d3d7 mag filter type %d\n", State);
5054                         State = WINED3DTEXF_POINT;
5055                         break;
5056                 }
5057                 break;
5058             }
5059
5060             case D3DTSS_ADDRESS:
5061                 IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, WINED3DSAMP_ADDRESSV, State);
5062                 break;
5063
5064             default:
5065                 break;
5066         }
5067
5068         hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, l->state, State);
5069     }
5070     else
5071     {
5072         hr = IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
5073     }
5074
5075     LeaveCriticalSection(&ddraw_cs);
5076     return hr;
5077 }
5078
5079 static HRESULT WINAPI
5080 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5081                                            DWORD Stage,
5082                                            D3DTEXTURESTAGESTATETYPE TexStageStateType,
5083                                            DWORD State)
5084 {
5085     return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5086 }
5087
5088 static HRESULT WINAPI
5089 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5090                                            DWORD Stage,
5091                                            D3DTEXTURESTAGESTATETYPE TexStageStateType,
5092                                            DWORD State)
5093 {
5094     HRESULT hr;
5095     WORD old_fpucw;
5096
5097     old_fpucw = d3d_fpu_setup();
5098     hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5099     set_fpu_control_word(old_fpucw);
5100
5101     return hr;
5102 }
5103
5104 static HRESULT WINAPI
5105 Thunk_IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
5106                                                  DWORD Stage,
5107                                                  D3DTEXTURESTAGESTATETYPE TexStageStateType,
5108                                                  DWORD State)
5109 {
5110     TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5111             iface, Stage, TexStageStateType, State);
5112
5113     return IDirect3DDevice7_SetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
5114             Stage, TexStageStateType, State);
5115 }
5116
5117 /*****************************************************************************
5118  * IDirect3DDevice7::ValidateDevice
5119  *
5120  * SDK: "Reports the device's ability to render the currently set
5121  * texture-blending operations in a single pass". Whatever that means
5122  * exactly...
5123  *
5124  * Version 3 and 7
5125  *
5126  * Params:
5127  *  NumPasses: Address to write the number of necessary passes for the
5128  *             desired effect to.
5129  *
5130  * Returns:
5131  *  D3D_OK on success
5132  *  See IWineD3DDevice::ValidateDevice for more details
5133  *
5134  *****************************************************************************/
5135 static HRESULT
5136 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
5137                                      DWORD *NumPasses)
5138 {
5139     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5140     HRESULT hr;
5141
5142     TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
5143
5144     EnterCriticalSection(&ddraw_cs);
5145     hr = IWineD3DDevice_ValidateDevice(This->wineD3DDevice, NumPasses);
5146     LeaveCriticalSection(&ddraw_cs);
5147     return hr;
5148 }
5149
5150 static HRESULT WINAPI
5151 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
5152                                      DWORD *NumPasses)
5153 {
5154     return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5155 }
5156
5157 static HRESULT WINAPI
5158 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
5159                                      DWORD *NumPasses)
5160 {
5161     HRESULT hr;
5162     WORD old_fpucw;
5163
5164     old_fpucw = d3d_fpu_setup();
5165     hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5166     set_fpu_control_word(old_fpucw);
5167
5168     return hr;
5169 }
5170
5171 static HRESULT WINAPI
5172 Thunk_IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface,
5173                                            DWORD *Passes)
5174 {
5175     TRACE("iface %p, pass_count %p.\n", iface, Passes);
5176
5177     return IDirect3DDevice7_ValidateDevice((IDirect3DDevice7 *)device_from_device3(iface), Passes);
5178 }
5179
5180 /*****************************************************************************
5181  * IDirect3DDevice7::Clear
5182  *
5183  * Fills the render target, the z buffer and the stencil buffer with a
5184  * clear color / value
5185  *
5186  * Version 7 only
5187  *
5188  * Params:
5189  *  Count: Number of rectangles in Rects must be 0 if Rects is NULL
5190  *  Rects: Rectangles to clear. If NULL, the whole surface is cleared
5191  *  Flags: Some flags, as usual
5192  *  Color: Clear color for the render target
5193  *  Z: Clear value for the Z buffer
5194  *  Stencil: Clear value to store in each stencil buffer entry
5195  *
5196  * Returns:
5197  *  D3D_OK on success
5198  *  For details, see IWineD3DDevice::Clear
5199  *
5200  *****************************************************************************/
5201 static HRESULT
5202 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
5203                             DWORD Count,
5204                             D3DRECT *Rects,
5205                             DWORD Flags,
5206                             D3DCOLOR Color,
5207                             D3DVALUE Z,
5208                             DWORD Stencil)
5209 {
5210     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5211     HRESULT hr;
5212
5213     TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5214             iface, Count, Rects, Flags, Color, Z, Stencil);
5215
5216     EnterCriticalSection(&ddraw_cs);
5217     hr = IWineD3DDevice_Clear(This->wineD3DDevice, Count, (RECT *)Rects, Flags, Color, Z, Stencil);
5218     LeaveCriticalSection(&ddraw_cs);
5219     return hr;
5220 }
5221
5222 static HRESULT WINAPI
5223 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5224                             DWORD Count,
5225                             D3DRECT *Rects,
5226                             DWORD Flags,
5227                             D3DCOLOR Color,
5228                             D3DVALUE Z,
5229                             DWORD Stencil)
5230 {
5231     return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5232 }
5233
5234 static HRESULT WINAPI
5235 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5236                             DWORD Count,
5237                             D3DRECT *Rects,
5238                             DWORD Flags,
5239                             D3DCOLOR Color,
5240                             D3DVALUE Z,
5241                             DWORD Stencil)
5242 {
5243     HRESULT hr;
5244     WORD old_fpucw;
5245
5246     old_fpucw = d3d_fpu_setup();
5247     hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5248     set_fpu_control_word(old_fpucw);
5249
5250     return hr;
5251 }
5252
5253 /*****************************************************************************
5254  * IDirect3DDevice7::SetViewport
5255  *
5256  * Sets the current viewport.
5257  *
5258  * Version 7 only, but IDirect3DViewport uses this call for older
5259  * versions
5260  *
5261  * Params:
5262  *  Data: The new viewport to set
5263  *
5264  * Returns:
5265  *  D3D_OK on success
5266  *  DDERR_INVALIDPARAMS if Data is NULL
5267  *  For more details, see IWineDDDevice::SetViewport
5268  *
5269  *****************************************************************************/
5270 static HRESULT
5271 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5272                                   D3DVIEWPORT7 *Data)
5273 {
5274     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5275     HRESULT hr;
5276
5277     TRACE("iface %p, viewport %p.\n", iface, Data);
5278
5279     if(!Data)
5280         return DDERR_INVALIDPARAMS;
5281
5282     /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5283     EnterCriticalSection(&ddraw_cs);
5284     hr = IWineD3DDevice_SetViewport(This->wineD3DDevice,
5285                                     (WINED3DVIEWPORT*) Data);
5286     LeaveCriticalSection(&ddraw_cs);
5287     return hr;
5288 }
5289
5290 static HRESULT WINAPI
5291 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5292                                   D3DVIEWPORT7 *Data)
5293 {
5294     return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5295 }
5296
5297 static HRESULT WINAPI
5298 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5299                                   D3DVIEWPORT7 *Data)
5300 {
5301     HRESULT hr;
5302     WORD old_fpucw;
5303
5304     old_fpucw = d3d_fpu_setup();
5305     hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5306     set_fpu_control_word(old_fpucw);
5307
5308     return hr;
5309 }
5310
5311 /*****************************************************************************
5312  * IDirect3DDevice::GetViewport
5313  *
5314  * Returns the current viewport
5315  *
5316  * Version 7
5317  *
5318  * Params:
5319  *  Data: D3D7Viewport structure to write the viewport information to
5320  *
5321  * Returns:
5322  *  D3D_OK on success
5323  *  DDERR_INVALIDPARAMS if Data is NULL
5324  *  For more details, see IWineD3DDevice::GetViewport
5325  *
5326  *****************************************************************************/
5327 static HRESULT
5328 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5329                                   D3DVIEWPORT7 *Data)
5330 {
5331     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5332     HRESULT hr;
5333
5334     TRACE("iface %p, viewport %p.\n", iface, Data);
5335
5336     if(!Data)
5337         return DDERR_INVALIDPARAMS;
5338
5339     /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5340     EnterCriticalSection(&ddraw_cs);
5341     hr = IWineD3DDevice_GetViewport(This->wineD3DDevice,
5342                                     (WINED3DVIEWPORT*) Data);
5343
5344     LeaveCriticalSection(&ddraw_cs);
5345     return hr_ddraw_from_wined3d(hr);
5346 }
5347
5348 static HRESULT WINAPI
5349 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5350                                   D3DVIEWPORT7 *Data)
5351 {
5352     return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5353 }
5354
5355 static HRESULT WINAPI
5356 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5357                                   D3DVIEWPORT7 *Data)
5358 {
5359     HRESULT hr;
5360     WORD old_fpucw;
5361
5362     old_fpucw = d3d_fpu_setup();
5363     hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5364     set_fpu_control_word(old_fpucw);
5365
5366     return hr;
5367 }
5368
5369 /*****************************************************************************
5370  * IDirect3DDevice7::SetMaterial
5371  *
5372  * Sets the Material
5373  *
5374  * Version 7
5375  *
5376  * Params:
5377  *  Mat: The material to set
5378  *
5379  * Returns:
5380  *  D3D_OK on success
5381  *  DDERR_INVALIDPARAMS if Mat is NULL.
5382  *  For more details, see IWineD3DDevice::SetMaterial
5383  *
5384  *****************************************************************************/
5385 static HRESULT
5386 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5387                                   D3DMATERIAL7 *Mat)
5388 {
5389     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5390     HRESULT hr;
5391
5392     TRACE("iface %p, material %p.\n", iface, Mat);
5393
5394     if (!Mat) return DDERR_INVALIDPARAMS;
5395     /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5396     EnterCriticalSection(&ddraw_cs);
5397     hr = IWineD3DDevice_SetMaterial(This->wineD3DDevice,
5398                                     (WINED3DMATERIAL*) Mat);
5399     LeaveCriticalSection(&ddraw_cs);
5400     return hr_ddraw_from_wined3d(hr);
5401 }
5402
5403 static HRESULT WINAPI
5404 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5405                                   D3DMATERIAL7 *Mat)
5406 {
5407     return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5408 }
5409
5410 static HRESULT WINAPI
5411 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5412                                   D3DMATERIAL7 *Mat)
5413 {
5414     HRESULT hr;
5415     WORD old_fpucw;
5416
5417     old_fpucw = d3d_fpu_setup();
5418     hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5419     set_fpu_control_word(old_fpucw);
5420
5421     return hr;
5422 }
5423
5424 /*****************************************************************************
5425  * IDirect3DDevice7::GetMaterial
5426  *
5427  * Returns the current material
5428  *
5429  * Version 7
5430  *
5431  * Params:
5432  *  Mat: D3DMATERIAL7 structure to write the material parameters to
5433  *
5434  * Returns:
5435  *  D3D_OK on success
5436  *  DDERR_INVALIDPARAMS if Mat is NULL
5437  *  For more details, see IWineD3DDevice::GetMaterial
5438  *
5439  *****************************************************************************/
5440 static HRESULT
5441 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5442                                   D3DMATERIAL7 *Mat)
5443 {
5444     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5445     HRESULT hr;
5446
5447     TRACE("iface %p, material %p.\n", iface, Mat);
5448
5449     EnterCriticalSection(&ddraw_cs);
5450     /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5451     hr = IWineD3DDevice_GetMaterial(This->wineD3DDevice,
5452                                     (WINED3DMATERIAL*) Mat);
5453     LeaveCriticalSection(&ddraw_cs);
5454     return hr_ddraw_from_wined3d(hr);
5455 }
5456
5457 static HRESULT WINAPI
5458 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5459                                   D3DMATERIAL7 *Mat)
5460 {
5461     return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5462 }
5463
5464 static HRESULT WINAPI
5465 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5466                                   D3DMATERIAL7 *Mat)
5467 {
5468     HRESULT hr;
5469     WORD old_fpucw;
5470
5471     old_fpucw = d3d_fpu_setup();
5472     hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5473     set_fpu_control_word(old_fpucw);
5474
5475     return hr;
5476 }
5477
5478 /*****************************************************************************
5479  * IDirect3DDevice7::SetLight
5480  *
5481  * Assigns a light to a light index, but doesn't activate it yet.
5482  *
5483  * Version 7, IDirect3DLight uses this method for older versions
5484  *
5485  * Params:
5486  *  LightIndex: The index of the new light
5487  *  Light: A D3DLIGHT7 structure describing the light
5488  *
5489  * Returns:
5490  *  D3D_OK on success
5491  *  For more details, see IWineD3DDevice::SetLight
5492  *
5493  *****************************************************************************/
5494 static HRESULT
5495 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5496                                DWORD LightIndex,
5497                                D3DLIGHT7 *Light)
5498 {
5499     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5500     HRESULT hr;
5501
5502     TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5503
5504     EnterCriticalSection(&ddraw_cs);
5505     /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5506     hr = IWineD3DDevice_SetLight(This->wineD3DDevice,
5507                                  LightIndex,
5508                                  (WINED3DLIGHT*) Light);
5509     LeaveCriticalSection(&ddraw_cs);
5510     return hr_ddraw_from_wined3d(hr);
5511 }
5512
5513 static HRESULT WINAPI
5514 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5515                                DWORD LightIndex,
5516                                D3DLIGHT7 *Light)
5517 {
5518     return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5519 }
5520
5521 static HRESULT WINAPI
5522 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5523                                DWORD LightIndex,
5524                                D3DLIGHT7 *Light)
5525 {
5526     HRESULT hr;
5527     WORD old_fpucw;
5528
5529     old_fpucw = d3d_fpu_setup();
5530     hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5531     set_fpu_control_word(old_fpucw);
5532
5533     return hr;
5534 }
5535
5536 /*****************************************************************************
5537  * IDirect3DDevice7::GetLight
5538  *
5539  * Returns the light assigned to a light index
5540  *
5541  * Params:
5542  *  Light: Structure to write the light information to
5543  *
5544  * Returns:
5545  *  D3D_OK on success
5546  *  DDERR_INVALIDPARAMS if Light is NULL
5547  *  For details, see IWineD3DDevice::GetLight
5548  *
5549  *****************************************************************************/
5550 static HRESULT
5551 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5552                                DWORD LightIndex,
5553                                D3DLIGHT7 *Light)
5554 {
5555     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5556     HRESULT rc;
5557
5558     TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5559
5560     EnterCriticalSection(&ddraw_cs);
5561     /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5562     rc =  IWineD3DDevice_GetLight(This->wineD3DDevice,
5563                                   LightIndex,
5564                                   (WINED3DLIGHT*) Light);
5565
5566     /* Translate the result. WineD3D returns other values than D3D7 */
5567     LeaveCriticalSection(&ddraw_cs);
5568     return hr_ddraw_from_wined3d(rc);
5569 }
5570
5571 static HRESULT WINAPI
5572 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5573                                DWORD LightIndex,
5574                                D3DLIGHT7 *Light)
5575 {
5576     return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5577 }
5578
5579 static HRESULT WINAPI
5580 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5581                                DWORD LightIndex,
5582                                D3DLIGHT7 *Light)
5583 {
5584     HRESULT hr;
5585     WORD old_fpucw;
5586
5587     old_fpucw = d3d_fpu_setup();
5588     hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5589     set_fpu_control_word(old_fpucw);
5590
5591     return hr;
5592 }
5593
5594 /*****************************************************************************
5595  * IDirect3DDevice7::BeginStateBlock
5596  *
5597  * Begins recording to a stateblock
5598  *
5599  * Version 7
5600  *
5601  * Returns:
5602  *  D3D_OK on success
5603  *  For details see IWineD3DDevice::BeginStateBlock
5604  *
5605  *****************************************************************************/
5606 static HRESULT
5607 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5608 {
5609     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5610     HRESULT hr;
5611
5612     TRACE("iface %p.\n", iface);
5613
5614     EnterCriticalSection(&ddraw_cs);
5615     hr = IWineD3DDevice_BeginStateBlock(This->wineD3DDevice);
5616     LeaveCriticalSection(&ddraw_cs);
5617     return hr_ddraw_from_wined3d(hr);
5618 }
5619
5620 static HRESULT WINAPI
5621 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5622 {
5623     return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5624 }
5625
5626 static HRESULT WINAPI
5627 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5628 {
5629     HRESULT hr;
5630     WORD old_fpucw;
5631
5632     old_fpucw = d3d_fpu_setup();
5633     hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5634     set_fpu_control_word(old_fpucw);
5635
5636     return hr;
5637 }
5638
5639 /*****************************************************************************
5640  * IDirect3DDevice7::EndStateBlock
5641  *
5642  * Stops recording to a state block and returns the created stateblock
5643  * handle.
5644  *
5645  * Version 7
5646  *
5647  * Params:
5648  *  BlockHandle: Address to store the stateblock's handle to
5649  *
5650  * Returns:
5651  *  D3D_OK on success
5652  *  DDERR_INVALIDPARAMS if BlockHandle is NULL
5653  *  See IWineD3DDevice::EndStateBlock for more details
5654  *
5655  *****************************************************************************/
5656 static HRESULT
5657 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5658                                     DWORD *BlockHandle)
5659 {
5660     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5661     IWineD3DStateBlock *wined3d_sb;
5662     HRESULT hr;
5663     DWORD h;
5664
5665     TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5666
5667     if(!BlockHandle)
5668     {
5669         WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5670         return DDERR_INVALIDPARAMS;
5671     }
5672
5673     EnterCriticalSection(&ddraw_cs);
5674
5675     hr = IWineD3DDevice_EndStateBlock(This->wineD3DDevice, &wined3d_sb);
5676     if (FAILED(hr))
5677     {
5678         WARN("Failed to end stateblock, hr %#x.\n", hr);
5679         LeaveCriticalSection(&ddraw_cs);
5680         *BlockHandle = 0;
5681         return hr_ddraw_from_wined3d(hr);
5682     }
5683
5684     h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5685     if (h == DDRAW_INVALID_HANDLE)
5686     {
5687         ERR("Failed to allocate a stateblock handle.\n");
5688         IWineD3DStateBlock_Release(wined3d_sb);
5689         LeaveCriticalSection(&ddraw_cs);
5690         *BlockHandle = 0;
5691         return DDERR_OUTOFMEMORY;
5692     }
5693
5694     LeaveCriticalSection(&ddraw_cs);
5695     *BlockHandle = h + 1;
5696
5697     return hr_ddraw_from_wined3d(hr);
5698 }
5699
5700 static HRESULT WINAPI
5701 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5702                                     DWORD *BlockHandle)
5703 {
5704     return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5705 }
5706
5707 static HRESULT WINAPI
5708 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5709                                     DWORD *BlockHandle)
5710 {
5711     HRESULT hr;
5712     WORD old_fpucw;
5713
5714     old_fpucw = d3d_fpu_setup();
5715     hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5716     set_fpu_control_word(old_fpucw);
5717
5718     return hr;
5719 }
5720
5721 /*****************************************************************************
5722  * IDirect3DDevice7::PreLoad
5723  *
5724  * Allows the app to signal that a texture will be used soon, to allow
5725  * the Direct3DDevice to load it to the video card in the meantime.
5726  *
5727  * Version 7
5728  *
5729  * Params:
5730  *  Texture: The texture to preload
5731  *
5732  * Returns:
5733  *  D3D_OK on success
5734  *  DDERR_INVALIDPARAMS if Texture is NULL
5735  *  See IWineD3DSurface::PreLoad for details
5736  *
5737  *****************************************************************************/
5738 static HRESULT
5739 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5740                               IDirectDrawSurface7 *Texture)
5741 {
5742     IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
5743
5744     TRACE("iface %p, texture %p.\n", iface, Texture);
5745
5746     if(!Texture)
5747         return DDERR_INVALIDPARAMS;
5748
5749     EnterCriticalSection(&ddraw_cs);
5750     IWineD3DSurface_PreLoad(surf->WineD3DSurface);
5751     LeaveCriticalSection(&ddraw_cs);
5752     return D3D_OK;
5753 }
5754
5755 static HRESULT WINAPI
5756 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5757                               IDirectDrawSurface7 *Texture)
5758 {
5759     return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5760 }
5761
5762 static HRESULT WINAPI
5763 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5764                               IDirectDrawSurface7 *Texture)
5765 {
5766     HRESULT hr;
5767     WORD old_fpucw;
5768
5769     old_fpucw = d3d_fpu_setup();
5770     hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5771     set_fpu_control_word(old_fpucw);
5772
5773     return hr;
5774 }
5775
5776 /*****************************************************************************
5777  * IDirect3DDevice7::ApplyStateBlock
5778  *
5779  * Activates the state stored in a state block handle.
5780  *
5781  * Params:
5782  *  BlockHandle: The stateblock handle to activate
5783  *
5784  * Returns:
5785  *  D3D_OK on success
5786  *  D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5787  *
5788  *****************************************************************************/
5789 static HRESULT
5790 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5791                                       DWORD BlockHandle)
5792 {
5793     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5794     IWineD3DStateBlock *wined3d_sb;
5795     HRESULT hr;
5796
5797     TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5798
5799     EnterCriticalSection(&ddraw_cs);
5800
5801     wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5802     if (!wined3d_sb)
5803     {
5804         WARN("Invalid stateblock handle.\n");
5805         LeaveCriticalSection(&ddraw_cs);
5806         return D3DERR_INVALIDSTATEBLOCK;
5807     }
5808
5809     hr = IWineD3DStateBlock_Apply(wined3d_sb);
5810     LeaveCriticalSection(&ddraw_cs);
5811
5812     return hr_ddraw_from_wined3d(hr);
5813 }
5814
5815 static HRESULT WINAPI
5816 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5817                                       DWORD BlockHandle)
5818 {
5819     return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5820 }
5821
5822 static HRESULT WINAPI
5823 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5824                                       DWORD BlockHandle)
5825 {
5826     HRESULT hr;
5827     WORD old_fpucw;
5828
5829     old_fpucw = d3d_fpu_setup();
5830     hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5831     set_fpu_control_word(old_fpucw);
5832
5833     return hr;
5834 }
5835
5836 /*****************************************************************************
5837  * IDirect3DDevice7::CaptureStateBlock
5838  *
5839  * Updates a stateblock's values to the values currently set for the device
5840  *
5841  * Version 7
5842  *
5843  * Params:
5844  *  BlockHandle: Stateblock to update
5845  *
5846  * Returns:
5847  *  D3D_OK on success
5848  *  D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5849  *  See IWineD3DDevice::CaptureStateBlock for more details
5850  *
5851  *****************************************************************************/
5852 static HRESULT
5853 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5854                                         DWORD BlockHandle)
5855 {
5856     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5857     IWineD3DStateBlock *wined3d_sb;
5858     HRESULT hr;
5859
5860     TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5861
5862     EnterCriticalSection(&ddraw_cs);
5863
5864     wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5865     if (!wined3d_sb)
5866     {
5867         WARN("Invalid stateblock handle.\n");
5868         LeaveCriticalSection(&ddraw_cs);
5869         return D3DERR_INVALIDSTATEBLOCK;
5870     }
5871
5872     hr = IWineD3DStateBlock_Capture(wined3d_sb);
5873     LeaveCriticalSection(&ddraw_cs);
5874     return hr_ddraw_from_wined3d(hr);
5875 }
5876
5877 static HRESULT WINAPI
5878 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5879                                         DWORD BlockHandle)
5880 {
5881     return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5882 }
5883
5884 static HRESULT WINAPI
5885 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5886                                         DWORD BlockHandle)
5887 {
5888     HRESULT hr;
5889     WORD old_fpucw;
5890
5891     old_fpucw = d3d_fpu_setup();
5892     hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5893     set_fpu_control_word(old_fpucw);
5894
5895     return hr;
5896 }
5897
5898 /*****************************************************************************
5899  * IDirect3DDevice7::DeleteStateBlock
5900  *
5901  * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5902  *
5903  * Version 7
5904  *
5905  * Params:
5906  *  BlockHandle: Stateblock handle to delete
5907  *
5908  * Returns:
5909  *  D3D_OK on success
5910  *  D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5911  *
5912  *****************************************************************************/
5913 static HRESULT
5914 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5915                                        DWORD BlockHandle)
5916 {
5917     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5918     IWineD3DStateBlock *wined3d_sb;
5919     ULONG ref;
5920
5921     TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5922
5923     EnterCriticalSection(&ddraw_cs);
5924
5925     wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5926     if (!wined3d_sb)
5927     {
5928         WARN("Invalid stateblock handle.\n");
5929         LeaveCriticalSection(&ddraw_cs);
5930         return D3DERR_INVALIDSTATEBLOCK;
5931     }
5932
5933     if ((ref = IWineD3DStateBlock_Release(wined3d_sb)))
5934     {
5935         ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5936     }
5937
5938     LeaveCriticalSection(&ddraw_cs);
5939     return D3D_OK;
5940 }
5941
5942 static HRESULT WINAPI
5943 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5944                                        DWORD BlockHandle)
5945 {
5946     return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5947 }
5948
5949 static HRESULT WINAPI
5950 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5951                                        DWORD BlockHandle)
5952 {
5953     HRESULT hr;
5954     WORD old_fpucw;
5955
5956     old_fpucw = d3d_fpu_setup();
5957     hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5958     set_fpu_control_word(old_fpucw);
5959
5960     return hr;
5961 }
5962
5963 /*****************************************************************************
5964  * IDirect3DDevice7::CreateStateBlock
5965  *
5966  * Creates a new state block handle.
5967  *
5968  * Version 7
5969  *
5970  * Params:
5971  *  Type: The state block type
5972  *  BlockHandle: Address to write the created handle to
5973  *
5974  * Returns:
5975  *   D3D_OK on success
5976  *   DDERR_INVALIDPARAMS if BlockHandle is NULL
5977  *
5978  *****************************************************************************/
5979 static HRESULT
5980 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5981                                        D3DSTATEBLOCKTYPE Type,
5982                                        DWORD *BlockHandle)
5983 {
5984     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5985     IWineD3DStateBlock *wined3d_sb;
5986     HRESULT hr;
5987     DWORD h;
5988
5989     TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5990
5991     if(!BlockHandle)
5992     {
5993         WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5994         return DDERR_INVALIDPARAMS;
5995     }
5996     if(Type != D3DSBT_ALL         && Type != D3DSBT_PIXELSTATE &&
5997        Type != D3DSBT_VERTEXSTATE                              ) {
5998         WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5999         return DDERR_INVALIDPARAMS;
6000     }
6001
6002     EnterCriticalSection(&ddraw_cs);
6003
6004     /* The D3DSTATEBLOCKTYPE enum is fine here. */
6005     hr = IWineD3DDevice_CreateStateBlock(This->wineD3DDevice, Type, &wined3d_sb);
6006     if (FAILED(hr))
6007     {
6008         WARN("Failed to create stateblock, hr %#x.\n", hr);
6009         LeaveCriticalSection(&ddraw_cs);
6010         return hr_ddraw_from_wined3d(hr);
6011     }
6012
6013     h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
6014     if (h == DDRAW_INVALID_HANDLE)
6015     {
6016         ERR("Failed to allocate stateblock handle.\n");
6017         IWineD3DStateBlock_Release(wined3d_sb);
6018         LeaveCriticalSection(&ddraw_cs);
6019         return DDERR_OUTOFMEMORY;
6020     }
6021
6022     *BlockHandle = h + 1;
6023     LeaveCriticalSection(&ddraw_cs);
6024
6025     return hr_ddraw_from_wined3d(hr);
6026 }
6027
6028 static HRESULT WINAPI
6029 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
6030                                        D3DSTATEBLOCKTYPE Type,
6031                                        DWORD *BlockHandle)
6032 {
6033     return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6034 }
6035
6036 static HRESULT WINAPI
6037 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
6038                                        D3DSTATEBLOCKTYPE Type,
6039                                        DWORD *BlockHandle)
6040 {
6041     HRESULT hr;
6042     WORD old_fpucw;
6043
6044     old_fpucw = d3d_fpu_setup();
6045     hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6046     set_fpu_control_word(old_fpucw);
6047
6048     return hr;
6049 }
6050
6051 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6052 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
6053                                 IDirectDrawSurfaceImpl *src)
6054 {
6055     IDirectDrawSurfaceImpl *src_level, *dest_level;
6056     IDirectDrawSurface7 *temp;
6057     DDSURFACEDESC2 ddsd;
6058     BOOL levelFound; /* at least one suitable sublevel in dest found */
6059
6060     /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
6061      * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
6062      * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
6063      */
6064     levelFound = FALSE;
6065
6066     src_level = src;
6067     dest_level = dest;
6068
6069     for (;src_level && dest_level;)
6070     {
6071         if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6072             src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6073         {
6074             levelFound = TRUE;
6075
6076             ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6077             ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6078             IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
6079
6080             if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6081
6082             dest_level = (IDirectDrawSurfaceImpl *)temp;
6083         }
6084
6085         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6086         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6087         IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
6088
6089         if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6090
6091         src_level = (IDirectDrawSurfaceImpl *)temp;
6092     }
6093
6094     if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6095     if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6096
6097     return !dest_level && levelFound;
6098 }
6099
6100 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6101 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
6102                               IDirectDrawSurfaceImpl *dest,
6103                               IDirectDrawSurfaceImpl *src,
6104                               const POINT *DestPoint,
6105                               const RECT *SrcRect)
6106 {
6107     IDirectDrawSurfaceImpl *src_level, *dest_level;
6108     IDirectDrawSurface7 *temp;
6109     DDSURFACEDESC2 ddsd;
6110     POINT point;
6111     RECT rect;
6112     HRESULT hr;
6113     IDirectDrawPalette *pal = NULL, *pal_src = NULL;
6114     DWORD ckeyflag;
6115     DDCOLORKEY ddckey;
6116     BOOL palette_missing = FALSE;
6117
6118     /* Copy palette, if possible. */
6119     IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)src, &pal_src);
6120     IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)dest, &pal);
6121
6122     if (pal_src != NULL && pal != NULL)
6123     {
6124         PALETTEENTRY palent[256];
6125
6126         IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
6127         IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
6128     }
6129
6130     if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
6131             DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
6132     {
6133         palette_missing = TRUE;
6134     }
6135
6136     if (pal) IDirectDrawPalette_Release(pal);
6137     if (pal_src) IDirectDrawPalette_Release(pal_src);
6138
6139     /* Copy colorkeys, if present. */
6140     for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6141     {
6142         hr = IDirectDrawSurface7_GetColorKey((IDirectDrawSurface7 *)src, ckeyflag, &ddckey);
6143
6144         if (SUCCEEDED(hr))
6145         {
6146             IDirectDrawSurface7_SetColorKey((IDirectDrawSurface7 *)dest, ckeyflag, &ddckey);
6147         }
6148     }
6149
6150     src_level = src;
6151     dest_level = dest;
6152
6153     point = *DestPoint;
6154     rect = *SrcRect;
6155
6156     for (;src_level && dest_level;)
6157     {
6158         if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6159             src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6160         {
6161             /* Try UpdateSurface that may perform a more direct opengl loading. But skip this if destination is paletted texture and has no palette.
6162              * Some games like Sacrifice set palette after Load, and it is a waste of effort to try to load texture without palette and generates
6163              * warnings in wined3d. */
6164             if (!palette_missing)
6165                 hr = IWineD3DDevice_UpdateSurface(device->wineD3DDevice, src_level->WineD3DSurface, &rect, dest_level->WineD3DSurface,
6166                                 &point);
6167
6168             if (palette_missing || FAILED(hr))
6169             {
6170                 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
6171                 IWineD3DSurface_BltFast(dest_level->WineD3DSurface,
6172                                         point.x, point.y,
6173                                         src_level->WineD3DSurface, &rect, 0);
6174             }
6175
6176             ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6177             ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6178             IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
6179
6180             if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6181
6182             dest_level = (IDirectDrawSurfaceImpl *)temp;
6183         }
6184
6185         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6186         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6187         IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
6188
6189         if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6190
6191         src_level = (IDirectDrawSurfaceImpl *)temp;
6192
6193         point.x /= 2;
6194         point.y /= 2;
6195
6196         rect.top /= 2;
6197         rect.left /= 2;
6198         rect.right = (rect.right + 1) / 2;
6199         rect.bottom = (rect.bottom + 1) / 2;
6200     }
6201
6202     if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6203     if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6204 }
6205
6206 /*****************************************************************************
6207  * IDirect3DDevice7::Load
6208  *
6209  * Loads a rectangular area from the source into the destination texture.
6210  * It can also copy the source to the faces of a cubic environment map
6211  *
6212  * Version 7
6213  *
6214  * Params:
6215  *  DestTex: Destination texture
6216  *  DestPoint: Point in the destination where the source image should be
6217  *             written to
6218  *  SrcTex: Source texture
6219  *  SrcRect: Source rectangle
6220  *  Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6221  *          DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6222  *          DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6223  *
6224  * Returns:
6225  *  D3D_OK on success
6226  *  DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6227  *
6228  *
6229  *****************************************************************************/
6230
6231 static HRESULT
6232 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6233                            IDirectDrawSurface7 *DestTex,
6234                            POINT *DestPoint,
6235                            IDirectDrawSurface7 *SrcTex,
6236                            RECT *SrcRect,
6237                            DWORD Flags)
6238 {
6239     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6240     IDirectDrawSurfaceImpl *dest = (IDirectDrawSurfaceImpl *)DestTex;
6241     IDirectDrawSurfaceImpl *src = (IDirectDrawSurfaceImpl *)SrcTex;
6242     POINT destpoint;
6243     RECT srcrect;
6244
6245     TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6246             iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6247
6248     if( (!src) || (!dest) )
6249         return DDERR_INVALIDPARAMS;
6250
6251     EnterCriticalSection(&ddraw_cs);
6252
6253     if (SrcRect) srcrect = *SrcRect;
6254     else
6255     {
6256         srcrect.left = srcrect.top = 0;
6257         srcrect.right = src->surface_desc.dwWidth;
6258         srcrect.bottom = src->surface_desc.dwHeight;
6259     }
6260
6261     if (DestPoint) destpoint = *DestPoint;
6262     else
6263     {
6264         destpoint.x = destpoint.y = 0;
6265     }
6266     /* Check bad dimensions. DestPoint is validated against src, not dest, because
6267      * destination can be a subset of mip levels, in which case actual coordinates used
6268      * for it may be divided. If any dimension of dest is larger than source, it can't be
6269      * mip level subset, so an error can be returned early.
6270      */
6271     if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6272         srcrect.right > src->surface_desc.dwWidth ||
6273         srcrect.bottom > src->surface_desc.dwHeight ||
6274         destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6275         destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6276         dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6277         dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6278     {
6279         LeaveCriticalSection(&ddraw_cs);
6280         return DDERR_INVALIDPARAMS;
6281     }
6282
6283     /* Must be top level surfaces. */
6284     if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6285         dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6286     {
6287         LeaveCriticalSection(&ddraw_cs);
6288         return DDERR_INVALIDPARAMS;
6289     }
6290
6291     if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6292     {
6293         DWORD src_face_flag, dest_face_flag;
6294         IDirectDrawSurfaceImpl *src_face, *dest_face;
6295         IDirectDrawSurface7 *temp;
6296         DDSURFACEDESC2 ddsd;
6297         int i;
6298
6299         if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6300         {
6301             LeaveCriticalSection(&ddraw_cs);
6302             return DDERR_INVALIDPARAMS;
6303         }
6304
6305         /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6306          * time it's actual surface loading. */
6307         for (i = 0; i < 2; i++)
6308         {
6309             dest_face = dest;
6310             src_face = src;
6311
6312             for (;dest_face && src_face;)
6313             {
6314                 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6315                 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6316
6317                 if (src_face_flag == dest_face_flag)
6318                 {
6319                     if (i == 0)
6320                     {
6321                         /* Destination mip levels must be subset of source mip levels. */
6322                         if (!is_mip_level_subset(dest_face, src_face))
6323                         {
6324                             LeaveCriticalSection(&ddraw_cs);
6325                             return DDERR_INVALIDPARAMS;
6326                         }
6327                     }
6328                     else if (Flags & dest_face_flag)
6329                     {
6330                         copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6331                     }
6332
6333                     if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6334                     {
6335                         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6336                         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6337                         IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src, &ddsd.ddsCaps, &temp);
6338
6339                         if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6340
6341                         src_face = (IDirectDrawSurfaceImpl *)temp;
6342                     }
6343                     else
6344                     {
6345                         if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6346
6347                         src_face = NULL;
6348                     }
6349                 }
6350
6351                 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6352                 {
6353                     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6354                     ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6355                     IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest, &ddsd.ddsCaps, &temp);
6356
6357                     if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6358
6359                     dest_face = (IDirectDrawSurfaceImpl *)temp;
6360                 }
6361                 else
6362                 {
6363                     if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6364
6365                     dest_face = NULL;
6366                 }
6367             }
6368
6369             if (i == 0)
6370             {
6371                 /* Native returns error if src faces are not subset of dest faces. */
6372                 if (src_face)
6373                 {
6374                     LeaveCriticalSection(&ddraw_cs);
6375                     return DDERR_INVALIDPARAMS;
6376                 }
6377             }
6378         }
6379
6380         LeaveCriticalSection(&ddraw_cs);
6381         return D3D_OK;
6382     }
6383     else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6384     {
6385         LeaveCriticalSection(&ddraw_cs);
6386         return DDERR_INVALIDPARAMS;
6387     }
6388
6389     /* Handle non cube map textures. */
6390
6391     /* Destination mip levels must be subset of source mip levels. */
6392     if (!is_mip_level_subset(dest, src))
6393     {
6394         LeaveCriticalSection(&ddraw_cs);
6395         return DDERR_INVALIDPARAMS;
6396     }
6397
6398     copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6399
6400     LeaveCriticalSection(&ddraw_cs);
6401     return D3D_OK;
6402 }
6403
6404 static HRESULT WINAPI
6405 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6406                            IDirectDrawSurface7 *DestTex,
6407                            POINT *DestPoint,
6408                            IDirectDrawSurface7 *SrcTex,
6409                            RECT *SrcRect,
6410                            DWORD Flags)
6411 {
6412     return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6413 }
6414
6415 static HRESULT WINAPI
6416 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6417                            IDirectDrawSurface7 *DestTex,
6418                            POINT *DestPoint,
6419                            IDirectDrawSurface7 *SrcTex,
6420                            RECT *SrcRect,
6421                            DWORD Flags)
6422 {
6423     HRESULT hr;
6424     WORD old_fpucw;
6425
6426     old_fpucw = d3d_fpu_setup();
6427     hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6428     set_fpu_control_word(old_fpucw);
6429
6430     return hr;
6431 }
6432
6433 /*****************************************************************************
6434  * IDirect3DDevice7::LightEnable
6435  *
6436  * Enables or disables a light
6437  *
6438  * Version 7, IDirect3DLight uses this method too.
6439  *
6440  * Params:
6441  *  LightIndex: The index of the light to enable / disable
6442  *  Enable: Enable or disable the light
6443  *
6444  * Returns:
6445  *  D3D_OK on success
6446  *  For more details, see IWineD3DDevice::SetLightEnable
6447  *
6448  *****************************************************************************/
6449 static HRESULT
6450 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6451                                   DWORD LightIndex,
6452                                   BOOL Enable)
6453 {
6454     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6455     HRESULT hr;
6456
6457     TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6458
6459     EnterCriticalSection(&ddraw_cs);
6460     hr = IWineD3DDevice_SetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6461     LeaveCriticalSection(&ddraw_cs);
6462     return hr_ddraw_from_wined3d(hr);
6463 }
6464
6465 static HRESULT WINAPI
6466 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6467                                   DWORD LightIndex,
6468                                   BOOL Enable)
6469 {
6470     return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6471 }
6472
6473 static HRESULT WINAPI
6474 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6475                                   DWORD LightIndex,
6476                                   BOOL Enable)
6477 {
6478     HRESULT hr;
6479     WORD old_fpucw;
6480
6481     old_fpucw = d3d_fpu_setup();
6482     hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6483     set_fpu_control_word(old_fpucw);
6484
6485     return hr;
6486 }
6487
6488 /*****************************************************************************
6489  * IDirect3DDevice7::GetLightEnable
6490  *
6491  * Retrieves if the light with the given index is enabled or not
6492  *
6493  * Version 7
6494  *
6495  * Params:
6496  *  LightIndex: Index of desired light
6497  *  Enable: Pointer to a BOOL which contains the result
6498  *
6499  * Returns:
6500  *  D3D_OK on success
6501  *  DDERR_INVALIDPARAMS if Enable is NULL
6502  *  See IWineD3DDevice::GetLightEnable for more details
6503  *
6504  *****************************************************************************/
6505 static HRESULT
6506 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6507                                      DWORD LightIndex,
6508                                      BOOL* Enable)
6509 {
6510     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6511     HRESULT hr;
6512
6513     TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6514
6515     if(!Enable)
6516         return DDERR_INVALIDPARAMS;
6517
6518     EnterCriticalSection(&ddraw_cs);
6519     hr = IWineD3DDevice_GetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6520     LeaveCriticalSection(&ddraw_cs);
6521     return hr_ddraw_from_wined3d(hr);
6522 }
6523
6524 static HRESULT WINAPI
6525 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6526                                      DWORD LightIndex,
6527                                      BOOL* Enable)
6528 {
6529     return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6530 }
6531
6532 static HRESULT WINAPI
6533 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6534                                      DWORD LightIndex,
6535                                      BOOL* Enable)
6536 {
6537     HRESULT hr;
6538     WORD old_fpucw;
6539
6540     old_fpucw = d3d_fpu_setup();
6541     hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6542     set_fpu_control_word(old_fpucw);
6543
6544     return hr;
6545 }
6546
6547 /*****************************************************************************
6548  * IDirect3DDevice7::SetClipPlane
6549  *
6550  * Sets custom clipping plane
6551  *
6552  * Version 7
6553  *
6554  * Params:
6555  *  Index: The index of the clipping plane
6556  *  PlaneEquation: An equation defining the clipping plane
6557  *
6558  * Returns:
6559  *  D3D_OK on success
6560  *  DDERR_INVALIDPARAMS if PlaneEquation is NULL
6561  *  See IWineD3DDevice::SetClipPlane for more details
6562  *
6563  *****************************************************************************/
6564 static HRESULT
6565 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6566                                    DWORD Index,
6567                                    D3DVALUE* PlaneEquation)
6568 {
6569     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6570     HRESULT hr;
6571
6572     TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6573
6574     if(!PlaneEquation)
6575         return DDERR_INVALIDPARAMS;
6576
6577     EnterCriticalSection(&ddraw_cs);
6578     hr = IWineD3DDevice_SetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6579     LeaveCriticalSection(&ddraw_cs);
6580     return hr;
6581 }
6582
6583 static HRESULT WINAPI
6584 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6585                                    DWORD Index,
6586                                    D3DVALUE* PlaneEquation)
6587 {
6588     return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6589 }
6590
6591 static HRESULT WINAPI
6592 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6593                                    DWORD Index,
6594                                    D3DVALUE* PlaneEquation)
6595 {
6596     HRESULT hr;
6597     WORD old_fpucw;
6598
6599     old_fpucw = d3d_fpu_setup();
6600     hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6601     set_fpu_control_word(old_fpucw);
6602
6603     return hr;
6604 }
6605
6606 /*****************************************************************************
6607  * IDirect3DDevice7::GetClipPlane
6608  *
6609  * Returns the clipping plane with a specific index
6610  *
6611  * Params:
6612  *  Index: The index of the desired plane
6613  *  PlaneEquation: Address to store the plane equation to
6614  *
6615  * Returns:
6616  *  D3D_OK on success
6617  *  DDERR_INVALIDPARAMS if PlaneEquation is NULL
6618  *  See IWineD3DDevice::GetClipPlane for more details
6619  *
6620  *****************************************************************************/
6621 static HRESULT
6622 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6623                                    DWORD Index,
6624                                    D3DVALUE* PlaneEquation)
6625 {
6626     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6627     HRESULT hr;
6628
6629     TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6630
6631     if(!PlaneEquation)
6632         return DDERR_INVALIDPARAMS;
6633
6634     EnterCriticalSection(&ddraw_cs);
6635     hr = IWineD3DDevice_GetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6636     LeaveCriticalSection(&ddraw_cs);
6637     return hr;
6638 }
6639
6640 static HRESULT WINAPI
6641 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6642                                    DWORD Index,
6643                                    D3DVALUE* PlaneEquation)
6644 {
6645     return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6646 }
6647
6648 static HRESULT WINAPI
6649 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6650                                    DWORD Index,
6651                                    D3DVALUE* PlaneEquation)
6652 {
6653     HRESULT hr;
6654     WORD old_fpucw;
6655
6656     old_fpucw = d3d_fpu_setup();
6657     hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6658     set_fpu_control_word(old_fpucw);
6659
6660     return hr;
6661 }
6662
6663 /*****************************************************************************
6664  * IDirect3DDevice7::GetInfo
6665  *
6666  * Retrieves some information about the device. The DirectX sdk says that
6667  * this version returns S_FALSE for all retail builds of DirectX, that's what
6668  * this implementation does.
6669  *
6670  * Params:
6671  *  DevInfoID: Information type requested
6672  *  DevInfoStruct: Pointer to a structure to store the info to
6673  *  Size: Size of the structure
6674  *
6675  * Returns:
6676  *  S_FALSE, because it's a non-debug driver
6677  *
6678  *****************************************************************************/
6679 static HRESULT WINAPI
6680 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6681                               DWORD DevInfoID,
6682                               void *DevInfoStruct,
6683                               DWORD Size)
6684 {
6685     TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6686             iface, DevInfoID, DevInfoStruct, Size);
6687
6688     if (TRACE_ON(ddraw))
6689     {
6690         TRACE(" info requested : ");
6691         switch (DevInfoID)
6692         {
6693             case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6694             case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6695             case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6696             default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6697         }
6698     }
6699
6700     return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6701 }
6702
6703 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6704  * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6705  * are not duplicated.
6706
6707  * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6708  * has already been setup for optimal d3d operation.
6709
6710  * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6711  * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6712  * by Sacrifice (game). */
6713 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6714 {
6715     /*** IUnknown Methods ***/
6716     IDirect3DDeviceImpl_7_QueryInterface,
6717     IDirect3DDeviceImpl_7_AddRef,
6718     IDirect3DDeviceImpl_7_Release,
6719     /*** IDirect3DDevice7 ***/
6720     IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6721     IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6722     IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6723     IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6724     IDirect3DDeviceImpl_7_GetDirect3D,
6725     IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6726     IDirect3DDeviceImpl_7_GetRenderTarget,
6727     IDirect3DDeviceImpl_7_Clear_FPUSetup,
6728     IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6729     IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6730     IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6731     IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6732     IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6733     IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6734     IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6735     IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6736     IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6737     IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6738     IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6739     IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6740     IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6741     IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6742     IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6743     IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6744     IDirect3DDeviceImpl_7_SetClipStatus,
6745     IDirect3DDeviceImpl_7_GetClipStatus,
6746     IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6747     IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6748     IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6749     IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6750     IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6751     IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6752     IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6753     IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6754     IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6755     IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6756     IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6757     IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6758     IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6759     IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6760     IDirect3DDeviceImpl_7_Load_FPUSetup,
6761     IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6762     IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6763     IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6764     IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6765     IDirect3DDeviceImpl_7_GetInfo
6766 };
6767
6768 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6769 {
6770     /*** IUnknown Methods ***/
6771     IDirect3DDeviceImpl_7_QueryInterface,
6772     IDirect3DDeviceImpl_7_AddRef,
6773     IDirect3DDeviceImpl_7_Release,
6774     /*** IDirect3DDevice7 ***/
6775     IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6776     IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6777     IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6778     IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6779     IDirect3DDeviceImpl_7_GetDirect3D,
6780     IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6781     IDirect3DDeviceImpl_7_GetRenderTarget,
6782     IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6783     IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6784     IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6785     IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6786     IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6787     IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6788     IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6789     IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6790     IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6791     IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6792     IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6793     IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6794     IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6795     IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6796     IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6797     IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6798     IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6799     IDirect3DDeviceImpl_7_SetClipStatus,
6800     IDirect3DDeviceImpl_7_GetClipStatus,
6801     IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6802     IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6803     IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6804     IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6805     IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6806     IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6807     IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6808     IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6809     IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6810     IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6811     IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6812     IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6813     IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6814     IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6815     IDirect3DDeviceImpl_7_Load_FPUPreserve,
6816     IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6817     IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6818     IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6819     IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6820     IDirect3DDeviceImpl_7_GetInfo
6821 };
6822
6823 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6824 {
6825     /*** IUnknown Methods ***/
6826     Thunk_IDirect3DDeviceImpl_3_QueryInterface,
6827     Thunk_IDirect3DDeviceImpl_3_AddRef,
6828     Thunk_IDirect3DDeviceImpl_3_Release,
6829     /*** IDirect3DDevice3 ***/
6830     IDirect3DDeviceImpl_3_GetCaps,
6831     IDirect3DDeviceImpl_3_GetStats,
6832     IDirect3DDeviceImpl_3_AddViewport,
6833     IDirect3DDeviceImpl_3_DeleteViewport,
6834     IDirect3DDeviceImpl_3_NextViewport,
6835     Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
6836     Thunk_IDirect3DDeviceImpl_3_BeginScene,
6837     Thunk_IDirect3DDeviceImpl_3_EndScene,
6838     Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
6839     IDirect3DDeviceImpl_3_SetCurrentViewport,
6840     IDirect3DDeviceImpl_3_GetCurrentViewport,
6841     Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
6842     Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
6843     IDirect3DDeviceImpl_3_Begin,
6844     IDirect3DDeviceImpl_3_BeginIndexed,
6845     IDirect3DDeviceImpl_3_Vertex,
6846     IDirect3DDeviceImpl_3_Index,
6847     IDirect3DDeviceImpl_3_End,
6848     IDirect3DDeviceImpl_3_GetRenderState,
6849     IDirect3DDeviceImpl_3_SetRenderState,
6850     IDirect3DDeviceImpl_3_GetLightState,
6851     IDirect3DDeviceImpl_3_SetLightState,
6852     Thunk_IDirect3DDeviceImpl_3_SetTransform,
6853     Thunk_IDirect3DDeviceImpl_3_GetTransform,
6854     Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
6855     Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
6856     Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6857     Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
6858     Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
6859     Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6860     Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6861     Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6862     Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6863     Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6864     Thunk_IDirect3DDeviceImpl_3_GetTexture,
6865     IDirect3DDeviceImpl_3_SetTexture,
6866     Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
6867     Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
6868     Thunk_IDirect3DDeviceImpl_3_ValidateDevice
6869 };
6870
6871 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6872 {
6873     /*** IUnknown Methods ***/
6874     Thunk_IDirect3DDeviceImpl_2_QueryInterface,
6875     Thunk_IDirect3DDeviceImpl_2_AddRef,
6876     Thunk_IDirect3DDeviceImpl_2_Release,
6877     /*** IDirect3DDevice2 ***/
6878     Thunk_IDirect3DDeviceImpl_2_GetCaps,
6879     IDirect3DDeviceImpl_2_SwapTextureHandles,
6880     Thunk_IDirect3DDeviceImpl_2_GetStats,
6881     Thunk_IDirect3DDeviceImpl_2_AddViewport,
6882     Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
6883     Thunk_IDirect3DDeviceImpl_2_NextViewport,
6884     IDirect3DDeviceImpl_2_EnumTextureFormats,
6885     Thunk_IDirect3DDeviceImpl_2_BeginScene,
6886     Thunk_IDirect3DDeviceImpl_2_EndScene,
6887     Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
6888     Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
6889     Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
6890     Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
6891     Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
6892     Thunk_IDirect3DDeviceImpl_2_Begin,
6893     Thunk_IDirect3DDeviceImpl_2_BeginIndexed,
6894     Thunk_IDirect3DDeviceImpl_2_Vertex,
6895     Thunk_IDirect3DDeviceImpl_2_Index,
6896     Thunk_IDirect3DDeviceImpl_2_End,
6897     Thunk_IDirect3DDeviceImpl_2_GetRenderState,
6898     Thunk_IDirect3DDeviceImpl_2_SetRenderState,
6899     Thunk_IDirect3DDeviceImpl_2_GetLightState,
6900     Thunk_IDirect3DDeviceImpl_2_SetLightState,
6901     Thunk_IDirect3DDeviceImpl_2_SetTransform,
6902     Thunk_IDirect3DDeviceImpl_2_GetTransform,
6903     Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
6904     Thunk_IDirect3DDeviceImpl_2_DrawPrimitive,
6905     Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6906     Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
6907     Thunk_IDirect3DDeviceImpl_2_GetClipStatus
6908 };
6909
6910 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6911 {
6912     /*** IUnknown Methods ***/
6913     Thunk_IDirect3DDeviceImpl_1_QueryInterface,
6914     Thunk_IDirect3DDeviceImpl_1_AddRef,
6915     Thunk_IDirect3DDeviceImpl_1_Release,
6916     /*** IDirect3DDevice1 ***/
6917     IDirect3DDeviceImpl_1_Initialize,
6918     Thunk_IDirect3DDeviceImpl_1_GetCaps,
6919     Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
6920     IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6921     Thunk_IDirect3DDeviceImpl_1_GetStats,
6922     IDirect3DDeviceImpl_1_Execute,
6923     Thunk_IDirect3DDeviceImpl_1_AddViewport,
6924     Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
6925     Thunk_IDirect3DDeviceImpl_1_NextViewport,
6926     IDirect3DDeviceImpl_1_Pick,
6927     IDirect3DDeviceImpl_1_GetPickRecords,
6928     Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
6929     IDirect3DDeviceImpl_1_CreateMatrix,
6930     IDirect3DDeviceImpl_1_SetMatrix,
6931     IDirect3DDeviceImpl_1_GetMatrix,
6932     IDirect3DDeviceImpl_1_DeleteMatrix,
6933     Thunk_IDirect3DDeviceImpl_1_BeginScene,
6934     Thunk_IDirect3DDeviceImpl_1_EndScene,
6935     Thunk_IDirect3DDeviceImpl_1_GetDirect3D
6936 };
6937
6938 /*****************************************************************************
6939  * IDirect3DDeviceImpl_UpdateDepthStencil
6940  *
6941  * Checks the current render target for attached depth stencils and sets the
6942  * WineD3D depth stencil accordingly.
6943  *
6944  * Returns:
6945  *  The depth stencil state to set if creating the device
6946  *
6947  *****************************************************************************/
6948 WINED3DZBUFFERTYPE
6949 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6950 {
6951     IDirectDrawSurface7 *depthStencil = NULL;
6952     IDirectDrawSurfaceImpl *dsi;
6953     static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6954
6955     IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)This->target, &depthcaps, &depthStencil);
6956     if(!depthStencil)
6957     {
6958         TRACE("Setting wined3d depth stencil to NULL\n");
6959         IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6960                                               NULL);
6961         return WINED3DZB_FALSE;
6962     }
6963
6964     dsi = (IDirectDrawSurfaceImpl *)depthStencil;
6965     TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->WineD3DSurface);
6966     IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6967                                           dsi->WineD3DSurface);
6968
6969     IDirectDrawSurface7_Release(depthStencil);
6970     return WINED3DZB_TRUE;
6971 }
6972
6973 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
6974 {
6975     IParentImpl *index_buffer_parent;
6976     HRESULT hr;
6977
6978     if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6979         device->lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6980     else
6981         device->lpVtbl = &d3d_device7_fpu_setup_vtbl;
6982
6983     device->IDirect3DDevice3_vtbl = &d3d_device3_vtbl;
6984     device->IDirect3DDevice2_vtbl = &d3d_device2_vtbl;
6985     device->IDirect3DDevice_vtbl = &d3d_device1_vtbl;
6986     device->ref = 1;
6987     device->ddraw = ddraw;
6988     device->target = target;
6989
6990     if (!ddraw_handle_table_init(&device->handle_table, 64))
6991     {
6992         ERR("Failed to initialize handle table.\n");
6993         return DDERR_OUTOFMEMORY;
6994     }
6995
6996     device->legacyTextureBlending = FALSE;
6997
6998     /* Create an index buffer, it's needed for indexed drawing */
6999     index_buffer_parent = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*index_buffer_parent));
7000     if (!index_buffer_parent)
7001     {
7002         ERR("Failed to allocate index buffer parent memory.\n");
7003         ddraw_handle_table_destroy(&device->handle_table);
7004         return DDERR_OUTOFMEMORY;
7005     }
7006
7007     ddraw_parent_init(index_buffer_parent);
7008
7009     hr = IWineD3DDevice_CreateIndexBuffer(ddraw->wineD3DDevice, 0x40000 /* Length. Don't know how long it should be */,
7010             WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, index_buffer_parent,
7011             &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
7012     if (FAILED(hr))
7013     {
7014         ERR("Failed to create an index buffer, hr %#x.\n", hr);
7015         HeapFree(GetProcessHeap(), 0, index_buffer_parent);
7016         ddraw_handle_table_destroy(&device->handle_table);
7017         return hr;
7018     }
7019     index_buffer_parent->child = (IUnknown *)device->indexbuffer;
7020
7021     /* This is for convenience. */
7022     device->wineD3DDevice = ddraw->wineD3DDevice;
7023     IWineD3DDevice_AddRef(ddraw->wineD3DDevice);
7024
7025     /* This is for apps which create a non-flip, non-d3d primary surface
7026      * and an offscreen D3DDEVICE surface, then render to the offscreen surface
7027      * and do a Blt from the offscreen to the primary surface.
7028      *
7029      * Set the offscreen D3DDDEVICE surface(=target) as the back buffer,
7030      * and the primary surface(=This->d3d_target) as the front buffer.
7031      *
7032      * This way the app will render to the D3DDEVICE surface and WineD3D
7033      * will catch the Blt was Back Buffer -> Front buffer blt and perform
7034      * a flip instead. This way we don't have to deal with a mixed GL / GDI
7035      * environment.
7036      *
7037      * This should be checked against windowed apps. The only app tested with
7038      * this is moto racer 2 during the loading screen.
7039      */
7040     TRACE("Is rendertarget: %s, d3d_target %p.\n",
7041             target->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ? "true" : "false", ddraw->d3d_target);
7042
7043     if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
7044             && ddraw->d3d_target != target)
7045     {
7046         TRACE("Using %p as front buffer, %p as back buffer.\n", ddraw->d3d_target, target);
7047
7048         hr = IWineD3DDevice_SetFrontBackBuffers(ddraw->wineD3DDevice,
7049                 ddraw->d3d_target->WineD3DSurface, target->WineD3DSurface);
7050         if (FAILED(hr))
7051         {
7052             ERR("Failed to set front and back buffer, hr %#x.\n", hr);
7053             IParent_Release((IParent *)index_buffer_parent);
7054             ddraw_handle_table_destroy(&device->handle_table);
7055             return hr;
7056         }
7057
7058         /* Render to the back buffer */
7059         IWineD3DDevice_SetRenderTarget(ddraw->wineD3DDevice, 0, target->WineD3DSurface, TRUE);
7060         device->OffScreenTarget = TRUE;
7061     }
7062     else
7063     {
7064         device->OffScreenTarget = FALSE;
7065     }
7066
7067     /* FIXME: This is broken. The target AddRef() makes some sense, because
7068      * we store a pointer during initialization, but then that's also where
7069      * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
7070     /* AddRef the render target. Also AddRef the render target from ddraw,
7071      * because if it is released before the app releases the D3D device, the
7072      * D3D capabilities of wined3d will be uninitialized, which has bad effects.
7073      *
7074      * In most cases, those surfaces are the same anyway, but this will simply
7075      * add another ref which is released when the device is destroyed. */
7076     IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)target);
7077     IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)ddraw->d3d_target);
7078
7079     ddraw->d3ddevice = device;
7080
7081     IWineD3DDevice_SetRenderState(ddraw->wineD3DDevice, WINED3DRS_ZENABLE,
7082             IDirect3DDeviceImpl_UpdateDepthStencil(device));
7083
7084     return D3D_OK;
7085 }