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