mscoree/tests: Remove spaces before '\n's in traces.
[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     EnterCriticalSection(&ddraw_cs);
5224     hr = IWineD3DDevice_Clear(This->wineD3DDevice, Count, (RECT *)Rects, Flags, Color, Z, Stencil);
5225     LeaveCriticalSection(&ddraw_cs);
5226     return hr;
5227 }
5228
5229 static HRESULT WINAPI
5230 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5231                             DWORD Count,
5232                             D3DRECT *Rects,
5233                             DWORD Flags,
5234                             D3DCOLOR Color,
5235                             D3DVALUE Z,
5236                             DWORD Stencil)
5237 {
5238     return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5239 }
5240
5241 static HRESULT WINAPI
5242 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5243                             DWORD Count,
5244                             D3DRECT *Rects,
5245                             DWORD Flags,
5246                             D3DCOLOR Color,
5247                             D3DVALUE Z,
5248                             DWORD Stencil)
5249 {
5250     HRESULT hr;
5251     WORD old_fpucw;
5252
5253     old_fpucw = d3d_fpu_setup();
5254     hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5255     set_fpu_control_word(old_fpucw);
5256
5257     return hr;
5258 }
5259
5260 /*****************************************************************************
5261  * IDirect3DDevice7::SetViewport
5262  *
5263  * Sets the current viewport.
5264  *
5265  * Version 7 only, but IDirect3DViewport uses this call for older
5266  * versions
5267  *
5268  * Params:
5269  *  Data: The new viewport to set
5270  *
5271  * Returns:
5272  *  D3D_OK on success
5273  *  DDERR_INVALIDPARAMS if Data is NULL
5274  *  For more details, see IWineDDDevice::SetViewport
5275  *
5276  *****************************************************************************/
5277 static HRESULT
5278 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5279                                   D3DVIEWPORT7 *Data)
5280 {
5281     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5282     HRESULT hr;
5283
5284     TRACE("iface %p, viewport %p.\n", iface, Data);
5285
5286     if(!Data)
5287         return DDERR_INVALIDPARAMS;
5288
5289     /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5290     EnterCriticalSection(&ddraw_cs);
5291     hr = IWineD3DDevice_SetViewport(This->wineD3DDevice,
5292                                     (WINED3DVIEWPORT*) Data);
5293     LeaveCriticalSection(&ddraw_cs);
5294     return hr;
5295 }
5296
5297 static HRESULT WINAPI
5298 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5299                                   D3DVIEWPORT7 *Data)
5300 {
5301     return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5302 }
5303
5304 static HRESULT WINAPI
5305 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5306                                   D3DVIEWPORT7 *Data)
5307 {
5308     HRESULT hr;
5309     WORD old_fpucw;
5310
5311     old_fpucw = d3d_fpu_setup();
5312     hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5313     set_fpu_control_word(old_fpucw);
5314
5315     return hr;
5316 }
5317
5318 /*****************************************************************************
5319  * IDirect3DDevice::GetViewport
5320  *
5321  * Returns the current viewport
5322  *
5323  * Version 7
5324  *
5325  * Params:
5326  *  Data: D3D7Viewport structure to write the viewport information to
5327  *
5328  * Returns:
5329  *  D3D_OK on success
5330  *  DDERR_INVALIDPARAMS if Data is NULL
5331  *  For more details, see IWineD3DDevice::GetViewport
5332  *
5333  *****************************************************************************/
5334 static HRESULT
5335 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5336                                   D3DVIEWPORT7 *Data)
5337 {
5338     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5339     HRESULT hr;
5340
5341     TRACE("iface %p, viewport %p.\n", iface, Data);
5342
5343     if(!Data)
5344         return DDERR_INVALIDPARAMS;
5345
5346     /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5347     EnterCriticalSection(&ddraw_cs);
5348     hr = IWineD3DDevice_GetViewport(This->wineD3DDevice,
5349                                     (WINED3DVIEWPORT*) Data);
5350
5351     LeaveCriticalSection(&ddraw_cs);
5352     return hr_ddraw_from_wined3d(hr);
5353 }
5354
5355 static HRESULT WINAPI
5356 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5357                                   D3DVIEWPORT7 *Data)
5358 {
5359     return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5360 }
5361
5362 static HRESULT WINAPI
5363 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5364                                   D3DVIEWPORT7 *Data)
5365 {
5366     HRESULT hr;
5367     WORD old_fpucw;
5368
5369     old_fpucw = d3d_fpu_setup();
5370     hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5371     set_fpu_control_word(old_fpucw);
5372
5373     return hr;
5374 }
5375
5376 /*****************************************************************************
5377  * IDirect3DDevice7::SetMaterial
5378  *
5379  * Sets the Material
5380  *
5381  * Version 7
5382  *
5383  * Params:
5384  *  Mat: The material to set
5385  *
5386  * Returns:
5387  *  D3D_OK on success
5388  *  DDERR_INVALIDPARAMS if Mat is NULL.
5389  *  For more details, see IWineD3DDevice::SetMaterial
5390  *
5391  *****************************************************************************/
5392 static HRESULT
5393 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5394                                   D3DMATERIAL7 *Mat)
5395 {
5396     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5397     HRESULT hr;
5398
5399     TRACE("iface %p, material %p.\n", iface, Mat);
5400
5401     if (!Mat) return DDERR_INVALIDPARAMS;
5402     /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5403     EnterCriticalSection(&ddraw_cs);
5404     hr = IWineD3DDevice_SetMaterial(This->wineD3DDevice,
5405                                     (WINED3DMATERIAL*) Mat);
5406     LeaveCriticalSection(&ddraw_cs);
5407     return hr_ddraw_from_wined3d(hr);
5408 }
5409
5410 static HRESULT WINAPI
5411 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5412                                   D3DMATERIAL7 *Mat)
5413 {
5414     return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5415 }
5416
5417 static HRESULT WINAPI
5418 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5419                                   D3DMATERIAL7 *Mat)
5420 {
5421     HRESULT hr;
5422     WORD old_fpucw;
5423
5424     old_fpucw = d3d_fpu_setup();
5425     hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5426     set_fpu_control_word(old_fpucw);
5427
5428     return hr;
5429 }
5430
5431 /*****************************************************************************
5432  * IDirect3DDevice7::GetMaterial
5433  *
5434  * Returns the current material
5435  *
5436  * Version 7
5437  *
5438  * Params:
5439  *  Mat: D3DMATERIAL7 structure to write the material parameters to
5440  *
5441  * Returns:
5442  *  D3D_OK on success
5443  *  DDERR_INVALIDPARAMS if Mat is NULL
5444  *  For more details, see IWineD3DDevice::GetMaterial
5445  *
5446  *****************************************************************************/
5447 static HRESULT
5448 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5449                                   D3DMATERIAL7 *Mat)
5450 {
5451     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5452     HRESULT hr;
5453
5454     TRACE("iface %p, material %p.\n", iface, Mat);
5455
5456     EnterCriticalSection(&ddraw_cs);
5457     /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5458     hr = IWineD3DDevice_GetMaterial(This->wineD3DDevice,
5459                                     (WINED3DMATERIAL*) Mat);
5460     LeaveCriticalSection(&ddraw_cs);
5461     return hr_ddraw_from_wined3d(hr);
5462 }
5463
5464 static HRESULT WINAPI
5465 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5466                                   D3DMATERIAL7 *Mat)
5467 {
5468     return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5469 }
5470
5471 static HRESULT WINAPI
5472 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5473                                   D3DMATERIAL7 *Mat)
5474 {
5475     HRESULT hr;
5476     WORD old_fpucw;
5477
5478     old_fpucw = d3d_fpu_setup();
5479     hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5480     set_fpu_control_word(old_fpucw);
5481
5482     return hr;
5483 }
5484
5485 /*****************************************************************************
5486  * IDirect3DDevice7::SetLight
5487  *
5488  * Assigns a light to a light index, but doesn't activate it yet.
5489  *
5490  * Version 7, IDirect3DLight uses this method for older versions
5491  *
5492  * Params:
5493  *  LightIndex: The index of the new light
5494  *  Light: A D3DLIGHT7 structure describing the light
5495  *
5496  * Returns:
5497  *  D3D_OK on success
5498  *  For more details, see IWineD3DDevice::SetLight
5499  *
5500  *****************************************************************************/
5501 static HRESULT
5502 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5503                                DWORD LightIndex,
5504                                D3DLIGHT7 *Light)
5505 {
5506     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5507     HRESULT hr;
5508
5509     TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5510
5511     EnterCriticalSection(&ddraw_cs);
5512     /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5513     hr = IWineD3DDevice_SetLight(This->wineD3DDevice,
5514                                  LightIndex,
5515                                  (WINED3DLIGHT*) Light);
5516     LeaveCriticalSection(&ddraw_cs);
5517     return hr_ddraw_from_wined3d(hr);
5518 }
5519
5520 static HRESULT WINAPI
5521 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5522                                DWORD LightIndex,
5523                                D3DLIGHT7 *Light)
5524 {
5525     return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5526 }
5527
5528 static HRESULT WINAPI
5529 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5530                                DWORD LightIndex,
5531                                D3DLIGHT7 *Light)
5532 {
5533     HRESULT hr;
5534     WORD old_fpucw;
5535
5536     old_fpucw = d3d_fpu_setup();
5537     hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5538     set_fpu_control_word(old_fpucw);
5539
5540     return hr;
5541 }
5542
5543 /*****************************************************************************
5544  * IDirect3DDevice7::GetLight
5545  *
5546  * Returns the light assigned to a light index
5547  *
5548  * Params:
5549  *  Light: Structure to write the light information to
5550  *
5551  * Returns:
5552  *  D3D_OK on success
5553  *  DDERR_INVALIDPARAMS if Light is NULL
5554  *  For details, see IWineD3DDevice::GetLight
5555  *
5556  *****************************************************************************/
5557 static HRESULT
5558 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5559                                DWORD LightIndex,
5560                                D3DLIGHT7 *Light)
5561 {
5562     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5563     HRESULT rc;
5564
5565     TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5566
5567     EnterCriticalSection(&ddraw_cs);
5568     /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5569     rc =  IWineD3DDevice_GetLight(This->wineD3DDevice,
5570                                   LightIndex,
5571                                   (WINED3DLIGHT*) Light);
5572
5573     /* Translate the result. WineD3D returns other values than D3D7 */
5574     LeaveCriticalSection(&ddraw_cs);
5575     return hr_ddraw_from_wined3d(rc);
5576 }
5577
5578 static HRESULT WINAPI
5579 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5580                                DWORD LightIndex,
5581                                D3DLIGHT7 *Light)
5582 {
5583     return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5584 }
5585
5586 static HRESULT WINAPI
5587 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5588                                DWORD LightIndex,
5589                                D3DLIGHT7 *Light)
5590 {
5591     HRESULT hr;
5592     WORD old_fpucw;
5593
5594     old_fpucw = d3d_fpu_setup();
5595     hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5596     set_fpu_control_word(old_fpucw);
5597
5598     return hr;
5599 }
5600
5601 /*****************************************************************************
5602  * IDirect3DDevice7::BeginStateBlock
5603  *
5604  * Begins recording to a stateblock
5605  *
5606  * Version 7
5607  *
5608  * Returns:
5609  *  D3D_OK on success
5610  *  For details see IWineD3DDevice::BeginStateBlock
5611  *
5612  *****************************************************************************/
5613 static HRESULT
5614 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5615 {
5616     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5617     HRESULT hr;
5618
5619     TRACE("iface %p.\n", iface);
5620
5621     EnterCriticalSection(&ddraw_cs);
5622     hr = IWineD3DDevice_BeginStateBlock(This->wineD3DDevice);
5623     LeaveCriticalSection(&ddraw_cs);
5624     return hr_ddraw_from_wined3d(hr);
5625 }
5626
5627 static HRESULT WINAPI
5628 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5629 {
5630     return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5631 }
5632
5633 static HRESULT WINAPI
5634 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5635 {
5636     HRESULT hr;
5637     WORD old_fpucw;
5638
5639     old_fpucw = d3d_fpu_setup();
5640     hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5641     set_fpu_control_word(old_fpucw);
5642
5643     return hr;
5644 }
5645
5646 /*****************************************************************************
5647  * IDirect3DDevice7::EndStateBlock
5648  *
5649  * Stops recording to a state block and returns the created stateblock
5650  * handle.
5651  *
5652  * Version 7
5653  *
5654  * Params:
5655  *  BlockHandle: Address to store the stateblock's handle to
5656  *
5657  * Returns:
5658  *  D3D_OK on success
5659  *  DDERR_INVALIDPARAMS if BlockHandle is NULL
5660  *  See IWineD3DDevice::EndStateBlock for more details
5661  *
5662  *****************************************************************************/
5663 static HRESULT
5664 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5665                                     DWORD *BlockHandle)
5666 {
5667     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5668     IWineD3DStateBlock *wined3d_sb;
5669     HRESULT hr;
5670     DWORD h;
5671
5672     TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5673
5674     if(!BlockHandle)
5675     {
5676         WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5677         return DDERR_INVALIDPARAMS;
5678     }
5679
5680     EnterCriticalSection(&ddraw_cs);
5681
5682     hr = IWineD3DDevice_EndStateBlock(This->wineD3DDevice, &wined3d_sb);
5683     if (FAILED(hr))
5684     {
5685         WARN("Failed to end stateblock, hr %#x.\n", hr);
5686         LeaveCriticalSection(&ddraw_cs);
5687         *BlockHandle = 0;
5688         return hr_ddraw_from_wined3d(hr);
5689     }
5690
5691     h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5692     if (h == DDRAW_INVALID_HANDLE)
5693     {
5694         ERR("Failed to allocate a stateblock handle.\n");
5695         IWineD3DStateBlock_Release(wined3d_sb);
5696         LeaveCriticalSection(&ddraw_cs);
5697         *BlockHandle = 0;
5698         return DDERR_OUTOFMEMORY;
5699     }
5700
5701     LeaveCriticalSection(&ddraw_cs);
5702     *BlockHandle = h + 1;
5703
5704     return hr_ddraw_from_wined3d(hr);
5705 }
5706
5707 static HRESULT WINAPI
5708 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5709                                     DWORD *BlockHandle)
5710 {
5711     return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5712 }
5713
5714 static HRESULT WINAPI
5715 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5716                                     DWORD *BlockHandle)
5717 {
5718     HRESULT hr;
5719     WORD old_fpucw;
5720
5721     old_fpucw = d3d_fpu_setup();
5722     hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5723     set_fpu_control_word(old_fpucw);
5724
5725     return hr;
5726 }
5727
5728 /*****************************************************************************
5729  * IDirect3DDevice7::PreLoad
5730  *
5731  * Allows the app to signal that a texture will be used soon, to allow
5732  * the Direct3DDevice to load it to the video card in the meantime.
5733  *
5734  * Version 7
5735  *
5736  * Params:
5737  *  Texture: The texture to preload
5738  *
5739  * Returns:
5740  *  D3D_OK on success
5741  *  DDERR_INVALIDPARAMS if Texture is NULL
5742  *  See IWineD3DSurface::PreLoad for details
5743  *
5744  *****************************************************************************/
5745 static HRESULT
5746 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5747                               IDirectDrawSurface7 *Texture)
5748 {
5749     IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
5750
5751     TRACE("iface %p, texture %p.\n", iface, Texture);
5752
5753     if(!Texture)
5754         return DDERR_INVALIDPARAMS;
5755
5756     EnterCriticalSection(&ddraw_cs);
5757     IWineD3DSurface_PreLoad(surf->WineD3DSurface);
5758     LeaveCriticalSection(&ddraw_cs);
5759     return D3D_OK;
5760 }
5761
5762 static HRESULT WINAPI
5763 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5764                               IDirectDrawSurface7 *Texture)
5765 {
5766     return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5767 }
5768
5769 static HRESULT WINAPI
5770 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5771                               IDirectDrawSurface7 *Texture)
5772 {
5773     HRESULT hr;
5774     WORD old_fpucw;
5775
5776     old_fpucw = d3d_fpu_setup();
5777     hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5778     set_fpu_control_word(old_fpucw);
5779
5780     return hr;
5781 }
5782
5783 /*****************************************************************************
5784  * IDirect3DDevice7::ApplyStateBlock
5785  *
5786  * Activates the state stored in a state block handle.
5787  *
5788  * Params:
5789  *  BlockHandle: The stateblock handle to activate
5790  *
5791  * Returns:
5792  *  D3D_OK on success
5793  *  D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5794  *
5795  *****************************************************************************/
5796 static HRESULT
5797 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5798                                       DWORD BlockHandle)
5799 {
5800     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5801     IWineD3DStateBlock *wined3d_sb;
5802     HRESULT hr;
5803
5804     TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5805
5806     EnterCriticalSection(&ddraw_cs);
5807
5808     wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5809     if (!wined3d_sb)
5810     {
5811         WARN("Invalid stateblock handle.\n");
5812         LeaveCriticalSection(&ddraw_cs);
5813         return D3DERR_INVALIDSTATEBLOCK;
5814     }
5815
5816     hr = IWineD3DStateBlock_Apply(wined3d_sb);
5817     LeaveCriticalSection(&ddraw_cs);
5818
5819     return hr_ddraw_from_wined3d(hr);
5820 }
5821
5822 static HRESULT WINAPI
5823 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5824                                       DWORD BlockHandle)
5825 {
5826     return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5827 }
5828
5829 static HRESULT WINAPI
5830 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5831                                       DWORD BlockHandle)
5832 {
5833     HRESULT hr;
5834     WORD old_fpucw;
5835
5836     old_fpucw = d3d_fpu_setup();
5837     hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5838     set_fpu_control_word(old_fpucw);
5839
5840     return hr;
5841 }
5842
5843 /*****************************************************************************
5844  * IDirect3DDevice7::CaptureStateBlock
5845  *
5846  * Updates a stateblock's values to the values currently set for the device
5847  *
5848  * Version 7
5849  *
5850  * Params:
5851  *  BlockHandle: Stateblock to update
5852  *
5853  * Returns:
5854  *  D3D_OK on success
5855  *  D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5856  *  See IWineD3DDevice::CaptureStateBlock for more details
5857  *
5858  *****************************************************************************/
5859 static HRESULT
5860 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5861                                         DWORD BlockHandle)
5862 {
5863     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5864     IWineD3DStateBlock *wined3d_sb;
5865     HRESULT hr;
5866
5867     TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5868
5869     EnterCriticalSection(&ddraw_cs);
5870
5871     wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5872     if (!wined3d_sb)
5873     {
5874         WARN("Invalid stateblock handle.\n");
5875         LeaveCriticalSection(&ddraw_cs);
5876         return D3DERR_INVALIDSTATEBLOCK;
5877     }
5878
5879     hr = IWineD3DStateBlock_Capture(wined3d_sb);
5880     LeaveCriticalSection(&ddraw_cs);
5881     return hr_ddraw_from_wined3d(hr);
5882 }
5883
5884 static HRESULT WINAPI
5885 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5886                                         DWORD BlockHandle)
5887 {
5888     return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5889 }
5890
5891 static HRESULT WINAPI
5892 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5893                                         DWORD BlockHandle)
5894 {
5895     HRESULT hr;
5896     WORD old_fpucw;
5897
5898     old_fpucw = d3d_fpu_setup();
5899     hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5900     set_fpu_control_word(old_fpucw);
5901
5902     return hr;
5903 }
5904
5905 /*****************************************************************************
5906  * IDirect3DDevice7::DeleteStateBlock
5907  *
5908  * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5909  *
5910  * Version 7
5911  *
5912  * Params:
5913  *  BlockHandle: Stateblock handle to delete
5914  *
5915  * Returns:
5916  *  D3D_OK on success
5917  *  D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5918  *
5919  *****************************************************************************/
5920 static HRESULT
5921 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5922                                        DWORD BlockHandle)
5923 {
5924     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5925     IWineD3DStateBlock *wined3d_sb;
5926     ULONG ref;
5927
5928     TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5929
5930     EnterCriticalSection(&ddraw_cs);
5931
5932     wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5933     if (!wined3d_sb)
5934     {
5935         WARN("Invalid stateblock handle.\n");
5936         LeaveCriticalSection(&ddraw_cs);
5937         return D3DERR_INVALIDSTATEBLOCK;
5938     }
5939
5940     if ((ref = IWineD3DStateBlock_Release(wined3d_sb)))
5941     {
5942         ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5943     }
5944
5945     LeaveCriticalSection(&ddraw_cs);
5946     return D3D_OK;
5947 }
5948
5949 static HRESULT WINAPI
5950 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5951                                        DWORD BlockHandle)
5952 {
5953     return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5954 }
5955
5956 static HRESULT WINAPI
5957 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5958                                        DWORD BlockHandle)
5959 {
5960     HRESULT hr;
5961     WORD old_fpucw;
5962
5963     old_fpucw = d3d_fpu_setup();
5964     hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5965     set_fpu_control_word(old_fpucw);
5966
5967     return hr;
5968 }
5969
5970 /*****************************************************************************
5971  * IDirect3DDevice7::CreateStateBlock
5972  *
5973  * Creates a new state block handle.
5974  *
5975  * Version 7
5976  *
5977  * Params:
5978  *  Type: The state block type
5979  *  BlockHandle: Address to write the created handle to
5980  *
5981  * Returns:
5982  *   D3D_OK on success
5983  *   DDERR_INVALIDPARAMS if BlockHandle is NULL
5984  *
5985  *****************************************************************************/
5986 static HRESULT
5987 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5988                                        D3DSTATEBLOCKTYPE Type,
5989                                        DWORD *BlockHandle)
5990 {
5991     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5992     IWineD3DStateBlock *wined3d_sb;
5993     HRESULT hr;
5994     DWORD h;
5995
5996     TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5997
5998     if(!BlockHandle)
5999     {
6000         WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
6001         return DDERR_INVALIDPARAMS;
6002     }
6003     if(Type != D3DSBT_ALL         && Type != D3DSBT_PIXELSTATE &&
6004        Type != D3DSBT_VERTEXSTATE                              ) {
6005         WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
6006         return DDERR_INVALIDPARAMS;
6007     }
6008
6009     EnterCriticalSection(&ddraw_cs);
6010
6011     /* The D3DSTATEBLOCKTYPE enum is fine here. */
6012     hr = IWineD3DDevice_CreateStateBlock(This->wineD3DDevice, Type, &wined3d_sb);
6013     if (FAILED(hr))
6014     {
6015         WARN("Failed to create stateblock, hr %#x.\n", hr);
6016         LeaveCriticalSection(&ddraw_cs);
6017         return hr_ddraw_from_wined3d(hr);
6018     }
6019
6020     h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
6021     if (h == DDRAW_INVALID_HANDLE)
6022     {
6023         ERR("Failed to allocate stateblock handle.\n");
6024         IWineD3DStateBlock_Release(wined3d_sb);
6025         LeaveCriticalSection(&ddraw_cs);
6026         return DDERR_OUTOFMEMORY;
6027     }
6028
6029     *BlockHandle = h + 1;
6030     LeaveCriticalSection(&ddraw_cs);
6031
6032     return hr_ddraw_from_wined3d(hr);
6033 }
6034
6035 static HRESULT WINAPI
6036 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
6037                                        D3DSTATEBLOCKTYPE Type,
6038                                        DWORD *BlockHandle)
6039 {
6040     return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6041 }
6042
6043 static HRESULT WINAPI
6044 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
6045                                        D3DSTATEBLOCKTYPE Type,
6046                                        DWORD *BlockHandle)
6047 {
6048     HRESULT hr;
6049     WORD old_fpucw;
6050
6051     old_fpucw = d3d_fpu_setup();
6052     hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6053     set_fpu_control_word(old_fpucw);
6054
6055     return hr;
6056 }
6057
6058 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6059 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
6060                                 IDirectDrawSurfaceImpl *src)
6061 {
6062     IDirectDrawSurfaceImpl *src_level, *dest_level;
6063     IDirectDrawSurface7 *temp;
6064     DDSURFACEDESC2 ddsd;
6065     BOOL levelFound; /* at least one suitable sublevel in dest found */
6066
6067     /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
6068      * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
6069      * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
6070      */
6071     levelFound = FALSE;
6072
6073     src_level = src;
6074     dest_level = dest;
6075
6076     for (;src_level && dest_level;)
6077     {
6078         if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6079             src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6080         {
6081             levelFound = TRUE;
6082
6083             ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6084             ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6085             IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
6086
6087             if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6088
6089             dest_level = (IDirectDrawSurfaceImpl *)temp;
6090         }
6091
6092         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6093         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6094         IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
6095
6096         if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6097
6098         src_level = (IDirectDrawSurfaceImpl *)temp;
6099     }
6100
6101     if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6102     if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6103
6104     return !dest_level && levelFound;
6105 }
6106
6107 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6108 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
6109                               IDirectDrawSurfaceImpl *dest,
6110                               IDirectDrawSurfaceImpl *src,
6111                               const POINT *DestPoint,
6112                               const RECT *SrcRect)
6113 {
6114     IDirectDrawSurfaceImpl *src_level, *dest_level;
6115     IDirectDrawSurface7 *temp;
6116     DDSURFACEDESC2 ddsd;
6117     POINT point;
6118     RECT rect;
6119     HRESULT hr;
6120     IDirectDrawPalette *pal = NULL, *pal_src = NULL;
6121     DWORD ckeyflag;
6122     DDCOLORKEY ddckey;
6123     BOOL palette_missing = FALSE;
6124
6125     /* Copy palette, if possible. */
6126     IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)src, &pal_src);
6127     IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)dest, &pal);
6128
6129     if (pal_src != NULL && pal != NULL)
6130     {
6131         PALETTEENTRY palent[256];
6132
6133         IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
6134         IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
6135     }
6136
6137     if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
6138             DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
6139     {
6140         palette_missing = TRUE;
6141     }
6142
6143     if (pal) IDirectDrawPalette_Release(pal);
6144     if (pal_src) IDirectDrawPalette_Release(pal_src);
6145
6146     /* Copy colorkeys, if present. */
6147     for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6148     {
6149         hr = IDirectDrawSurface7_GetColorKey((IDirectDrawSurface7 *)src, ckeyflag, &ddckey);
6150
6151         if (SUCCEEDED(hr))
6152         {
6153             IDirectDrawSurface7_SetColorKey((IDirectDrawSurface7 *)dest, ckeyflag, &ddckey);
6154         }
6155     }
6156
6157     src_level = src;
6158     dest_level = dest;
6159
6160     point = *DestPoint;
6161     rect = *SrcRect;
6162
6163     for (;src_level && dest_level;)
6164     {
6165         if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6166             src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6167         {
6168             /* Try UpdateSurface that may perform a more direct opengl loading. But skip this if destination is paletted texture and has no palette.
6169              * Some games like Sacrifice set palette after Load, and it is a waste of effort to try to load texture without palette and generates
6170              * warnings in wined3d. */
6171             if (!palette_missing)
6172                 hr = IWineD3DDevice_UpdateSurface(device->wineD3DDevice, src_level->WineD3DSurface, &rect, dest_level->WineD3DSurface,
6173                                 &point);
6174
6175             if (palette_missing || FAILED(hr))
6176             {
6177                 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
6178                 IWineD3DSurface_BltFast(dest_level->WineD3DSurface,
6179                                         point.x, point.y,
6180                                         src_level->WineD3DSurface, &rect, 0);
6181             }
6182
6183             ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6184             ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6185             IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
6186
6187             if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6188
6189             dest_level = (IDirectDrawSurfaceImpl *)temp;
6190         }
6191
6192         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6193         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6194         IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
6195
6196         if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6197
6198         src_level = (IDirectDrawSurfaceImpl *)temp;
6199
6200         point.x /= 2;
6201         point.y /= 2;
6202
6203         rect.top /= 2;
6204         rect.left /= 2;
6205         rect.right = (rect.right + 1) / 2;
6206         rect.bottom = (rect.bottom + 1) / 2;
6207     }
6208
6209     if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6210     if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6211 }
6212
6213 /*****************************************************************************
6214  * IDirect3DDevice7::Load
6215  *
6216  * Loads a rectangular area from the source into the destination texture.
6217  * It can also copy the source to the faces of a cubic environment map
6218  *
6219  * Version 7
6220  *
6221  * Params:
6222  *  DestTex: Destination texture
6223  *  DestPoint: Point in the destination where the source image should be
6224  *             written to
6225  *  SrcTex: Source texture
6226  *  SrcRect: Source rectangle
6227  *  Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6228  *          DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6229  *          DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6230  *
6231  * Returns:
6232  *  D3D_OK on success
6233  *  DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6234  *
6235  *
6236  *****************************************************************************/
6237
6238 static HRESULT
6239 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6240                            IDirectDrawSurface7 *DestTex,
6241                            POINT *DestPoint,
6242                            IDirectDrawSurface7 *SrcTex,
6243                            RECT *SrcRect,
6244                            DWORD Flags)
6245 {
6246     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6247     IDirectDrawSurfaceImpl *dest = (IDirectDrawSurfaceImpl *)DestTex;
6248     IDirectDrawSurfaceImpl *src = (IDirectDrawSurfaceImpl *)SrcTex;
6249     POINT destpoint;
6250     RECT srcrect;
6251
6252     TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6253             iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6254
6255     if( (!src) || (!dest) )
6256         return DDERR_INVALIDPARAMS;
6257
6258     EnterCriticalSection(&ddraw_cs);
6259
6260     if (SrcRect) srcrect = *SrcRect;
6261     else
6262     {
6263         srcrect.left = srcrect.top = 0;
6264         srcrect.right = src->surface_desc.dwWidth;
6265         srcrect.bottom = src->surface_desc.dwHeight;
6266     }
6267
6268     if (DestPoint) destpoint = *DestPoint;
6269     else
6270     {
6271         destpoint.x = destpoint.y = 0;
6272     }
6273     /* Check bad dimensions. DestPoint is validated against src, not dest, because
6274      * destination can be a subset of mip levels, in which case actual coordinates used
6275      * for it may be divided. If any dimension of dest is larger than source, it can't be
6276      * mip level subset, so an error can be returned early.
6277      */
6278     if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6279         srcrect.right > src->surface_desc.dwWidth ||
6280         srcrect.bottom > src->surface_desc.dwHeight ||
6281         destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6282         destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6283         dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6284         dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6285     {
6286         LeaveCriticalSection(&ddraw_cs);
6287         return DDERR_INVALIDPARAMS;
6288     }
6289
6290     /* Must be top level surfaces. */
6291     if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6292         dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6293     {
6294         LeaveCriticalSection(&ddraw_cs);
6295         return DDERR_INVALIDPARAMS;
6296     }
6297
6298     if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6299     {
6300         DWORD src_face_flag, dest_face_flag;
6301         IDirectDrawSurfaceImpl *src_face, *dest_face;
6302         IDirectDrawSurface7 *temp;
6303         DDSURFACEDESC2 ddsd;
6304         int i;
6305
6306         if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6307         {
6308             LeaveCriticalSection(&ddraw_cs);
6309             return DDERR_INVALIDPARAMS;
6310         }
6311
6312         /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6313          * time it's actual surface loading. */
6314         for (i = 0; i < 2; i++)
6315         {
6316             dest_face = dest;
6317             src_face = src;
6318
6319             for (;dest_face && src_face;)
6320             {
6321                 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6322                 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6323
6324                 if (src_face_flag == dest_face_flag)
6325                 {
6326                     if (i == 0)
6327                     {
6328                         /* Destination mip levels must be subset of source mip levels. */
6329                         if (!is_mip_level_subset(dest_face, src_face))
6330                         {
6331                             LeaveCriticalSection(&ddraw_cs);
6332                             return DDERR_INVALIDPARAMS;
6333                         }
6334                     }
6335                     else if (Flags & dest_face_flag)
6336                     {
6337                         copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6338                     }
6339
6340                     if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6341                     {
6342                         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6343                         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6344                         IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src, &ddsd.ddsCaps, &temp);
6345
6346                         if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6347
6348                         src_face = (IDirectDrawSurfaceImpl *)temp;
6349                     }
6350                     else
6351                     {
6352                         if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6353
6354                         src_face = NULL;
6355                     }
6356                 }
6357
6358                 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6359                 {
6360                     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6361                     ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6362                     IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest, &ddsd.ddsCaps, &temp);
6363
6364                     if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6365
6366                     dest_face = (IDirectDrawSurfaceImpl *)temp;
6367                 }
6368                 else
6369                 {
6370                     if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6371
6372                     dest_face = NULL;
6373                 }
6374             }
6375
6376             if (i == 0)
6377             {
6378                 /* Native returns error if src faces are not subset of dest faces. */
6379                 if (src_face)
6380                 {
6381                     LeaveCriticalSection(&ddraw_cs);
6382                     return DDERR_INVALIDPARAMS;
6383                 }
6384             }
6385         }
6386
6387         LeaveCriticalSection(&ddraw_cs);
6388         return D3D_OK;
6389     }
6390     else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6391     {
6392         LeaveCriticalSection(&ddraw_cs);
6393         return DDERR_INVALIDPARAMS;
6394     }
6395
6396     /* Handle non cube map textures. */
6397
6398     /* Destination mip levels must be subset of source mip levels. */
6399     if (!is_mip_level_subset(dest, src))
6400     {
6401         LeaveCriticalSection(&ddraw_cs);
6402         return DDERR_INVALIDPARAMS;
6403     }
6404
6405     copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6406
6407     LeaveCriticalSection(&ddraw_cs);
6408     return D3D_OK;
6409 }
6410
6411 static HRESULT WINAPI
6412 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6413                            IDirectDrawSurface7 *DestTex,
6414                            POINT *DestPoint,
6415                            IDirectDrawSurface7 *SrcTex,
6416                            RECT *SrcRect,
6417                            DWORD Flags)
6418 {
6419     return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6420 }
6421
6422 static HRESULT WINAPI
6423 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6424                            IDirectDrawSurface7 *DestTex,
6425                            POINT *DestPoint,
6426                            IDirectDrawSurface7 *SrcTex,
6427                            RECT *SrcRect,
6428                            DWORD Flags)
6429 {
6430     HRESULT hr;
6431     WORD old_fpucw;
6432
6433     old_fpucw = d3d_fpu_setup();
6434     hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6435     set_fpu_control_word(old_fpucw);
6436
6437     return hr;
6438 }
6439
6440 /*****************************************************************************
6441  * IDirect3DDevice7::LightEnable
6442  *
6443  * Enables or disables a light
6444  *
6445  * Version 7, IDirect3DLight uses this method too.
6446  *
6447  * Params:
6448  *  LightIndex: The index of the light to enable / disable
6449  *  Enable: Enable or disable the light
6450  *
6451  * Returns:
6452  *  D3D_OK on success
6453  *  For more details, see IWineD3DDevice::SetLightEnable
6454  *
6455  *****************************************************************************/
6456 static HRESULT
6457 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6458                                   DWORD LightIndex,
6459                                   BOOL Enable)
6460 {
6461     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6462     HRESULT hr;
6463
6464     TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6465
6466     EnterCriticalSection(&ddraw_cs);
6467     hr = IWineD3DDevice_SetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6468     LeaveCriticalSection(&ddraw_cs);
6469     return hr_ddraw_from_wined3d(hr);
6470 }
6471
6472 static HRESULT WINAPI
6473 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6474                                   DWORD LightIndex,
6475                                   BOOL Enable)
6476 {
6477     return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6478 }
6479
6480 static HRESULT WINAPI
6481 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6482                                   DWORD LightIndex,
6483                                   BOOL Enable)
6484 {
6485     HRESULT hr;
6486     WORD old_fpucw;
6487
6488     old_fpucw = d3d_fpu_setup();
6489     hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6490     set_fpu_control_word(old_fpucw);
6491
6492     return hr;
6493 }
6494
6495 /*****************************************************************************
6496  * IDirect3DDevice7::GetLightEnable
6497  *
6498  * Retrieves if the light with the given index is enabled or not
6499  *
6500  * Version 7
6501  *
6502  * Params:
6503  *  LightIndex: Index of desired light
6504  *  Enable: Pointer to a BOOL which contains the result
6505  *
6506  * Returns:
6507  *  D3D_OK on success
6508  *  DDERR_INVALIDPARAMS if Enable is NULL
6509  *  See IWineD3DDevice::GetLightEnable for more details
6510  *
6511  *****************************************************************************/
6512 static HRESULT
6513 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6514                                      DWORD LightIndex,
6515                                      BOOL* Enable)
6516 {
6517     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6518     HRESULT hr;
6519
6520     TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6521
6522     if(!Enable)
6523         return DDERR_INVALIDPARAMS;
6524
6525     EnterCriticalSection(&ddraw_cs);
6526     hr = IWineD3DDevice_GetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6527     LeaveCriticalSection(&ddraw_cs);
6528     return hr_ddraw_from_wined3d(hr);
6529 }
6530
6531 static HRESULT WINAPI
6532 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6533                                      DWORD LightIndex,
6534                                      BOOL* Enable)
6535 {
6536     return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6537 }
6538
6539 static HRESULT WINAPI
6540 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6541                                      DWORD LightIndex,
6542                                      BOOL* Enable)
6543 {
6544     HRESULT hr;
6545     WORD old_fpucw;
6546
6547     old_fpucw = d3d_fpu_setup();
6548     hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6549     set_fpu_control_word(old_fpucw);
6550
6551     return hr;
6552 }
6553
6554 /*****************************************************************************
6555  * IDirect3DDevice7::SetClipPlane
6556  *
6557  * Sets custom clipping plane
6558  *
6559  * Version 7
6560  *
6561  * Params:
6562  *  Index: The index of the clipping plane
6563  *  PlaneEquation: An equation defining the clipping plane
6564  *
6565  * Returns:
6566  *  D3D_OK on success
6567  *  DDERR_INVALIDPARAMS if PlaneEquation is NULL
6568  *  See IWineD3DDevice::SetClipPlane for more details
6569  *
6570  *****************************************************************************/
6571 static HRESULT
6572 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6573                                    DWORD Index,
6574                                    D3DVALUE* PlaneEquation)
6575 {
6576     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6577     HRESULT hr;
6578
6579     TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6580
6581     if(!PlaneEquation)
6582         return DDERR_INVALIDPARAMS;
6583
6584     EnterCriticalSection(&ddraw_cs);
6585     hr = IWineD3DDevice_SetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6586     LeaveCriticalSection(&ddraw_cs);
6587     return hr;
6588 }
6589
6590 static HRESULT WINAPI
6591 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6592                                    DWORD Index,
6593                                    D3DVALUE* PlaneEquation)
6594 {
6595     return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6596 }
6597
6598 static HRESULT WINAPI
6599 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6600                                    DWORD Index,
6601                                    D3DVALUE* PlaneEquation)
6602 {
6603     HRESULT hr;
6604     WORD old_fpucw;
6605
6606     old_fpucw = d3d_fpu_setup();
6607     hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6608     set_fpu_control_word(old_fpucw);
6609
6610     return hr;
6611 }
6612
6613 /*****************************************************************************
6614  * IDirect3DDevice7::GetClipPlane
6615  *
6616  * Returns the clipping plane with a specific index
6617  *
6618  * Params:
6619  *  Index: The index of the desired plane
6620  *  PlaneEquation: Address to store the plane equation to
6621  *
6622  * Returns:
6623  *  D3D_OK on success
6624  *  DDERR_INVALIDPARAMS if PlaneEquation is NULL
6625  *  See IWineD3DDevice::GetClipPlane for more details
6626  *
6627  *****************************************************************************/
6628 static HRESULT
6629 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6630                                    DWORD Index,
6631                                    D3DVALUE* PlaneEquation)
6632 {
6633     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6634     HRESULT hr;
6635
6636     TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6637
6638     if(!PlaneEquation)
6639         return DDERR_INVALIDPARAMS;
6640
6641     EnterCriticalSection(&ddraw_cs);
6642     hr = IWineD3DDevice_GetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6643     LeaveCriticalSection(&ddraw_cs);
6644     return hr;
6645 }
6646
6647 static HRESULT WINAPI
6648 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6649                                    DWORD Index,
6650                                    D3DVALUE* PlaneEquation)
6651 {
6652     return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6653 }
6654
6655 static HRESULT WINAPI
6656 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6657                                    DWORD Index,
6658                                    D3DVALUE* PlaneEquation)
6659 {
6660     HRESULT hr;
6661     WORD old_fpucw;
6662
6663     old_fpucw = d3d_fpu_setup();
6664     hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6665     set_fpu_control_word(old_fpucw);
6666
6667     return hr;
6668 }
6669
6670 /*****************************************************************************
6671  * IDirect3DDevice7::GetInfo
6672  *
6673  * Retrieves some information about the device. The DirectX sdk says that
6674  * this version returns S_FALSE for all retail builds of DirectX, that's what
6675  * this implementation does.
6676  *
6677  * Params:
6678  *  DevInfoID: Information type requested
6679  *  DevInfoStruct: Pointer to a structure to store the info to
6680  *  Size: Size of the structure
6681  *
6682  * Returns:
6683  *  S_FALSE, because it's a non-debug driver
6684  *
6685  *****************************************************************************/
6686 static HRESULT WINAPI
6687 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6688                               DWORD DevInfoID,
6689                               void *DevInfoStruct,
6690                               DWORD Size)
6691 {
6692     TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6693             iface, DevInfoID, DevInfoStruct, Size);
6694
6695     if (TRACE_ON(ddraw))
6696     {
6697         TRACE(" info requested : ");
6698         switch (DevInfoID)
6699         {
6700             case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6701             case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6702             case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6703             default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6704         }
6705     }
6706
6707     return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6708 }
6709
6710 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6711  * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6712  * are not duplicated.
6713
6714  * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6715  * has already been setup for optimal d3d operation.
6716
6717  * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6718  * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6719  * by Sacrifice (game). */
6720 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6721 {
6722     /*** IUnknown Methods ***/
6723     IDirect3DDeviceImpl_7_QueryInterface,
6724     IDirect3DDeviceImpl_7_AddRef,
6725     IDirect3DDeviceImpl_7_Release,
6726     /*** IDirect3DDevice7 ***/
6727     IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6728     IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6729     IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6730     IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6731     IDirect3DDeviceImpl_7_GetDirect3D,
6732     IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6733     IDirect3DDeviceImpl_7_GetRenderTarget,
6734     IDirect3DDeviceImpl_7_Clear_FPUSetup,
6735     IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6736     IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6737     IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6738     IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6739     IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6740     IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6741     IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6742     IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6743     IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6744     IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6745     IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6746     IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6747     IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6748     IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6749     IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6750     IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6751     IDirect3DDeviceImpl_7_SetClipStatus,
6752     IDirect3DDeviceImpl_7_GetClipStatus,
6753     IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6754     IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6755     IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6756     IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6757     IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6758     IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6759     IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6760     IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6761     IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6762     IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6763     IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6764     IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6765     IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6766     IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6767     IDirect3DDeviceImpl_7_Load_FPUSetup,
6768     IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6769     IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6770     IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6771     IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6772     IDirect3DDeviceImpl_7_GetInfo
6773 };
6774
6775 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6776 {
6777     /*** IUnknown Methods ***/
6778     IDirect3DDeviceImpl_7_QueryInterface,
6779     IDirect3DDeviceImpl_7_AddRef,
6780     IDirect3DDeviceImpl_7_Release,
6781     /*** IDirect3DDevice7 ***/
6782     IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6783     IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6784     IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6785     IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6786     IDirect3DDeviceImpl_7_GetDirect3D,
6787     IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6788     IDirect3DDeviceImpl_7_GetRenderTarget,
6789     IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6790     IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6791     IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6792     IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6793     IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6794     IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6795     IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6796     IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6797     IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6798     IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6799     IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6800     IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6801     IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6802     IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6803     IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6804     IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6805     IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6806     IDirect3DDeviceImpl_7_SetClipStatus,
6807     IDirect3DDeviceImpl_7_GetClipStatus,
6808     IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6809     IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6810     IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6811     IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6812     IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6813     IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6814     IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6815     IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6816     IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6817     IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6818     IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6819     IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6820     IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6821     IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6822     IDirect3DDeviceImpl_7_Load_FPUPreserve,
6823     IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6824     IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6825     IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6826     IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6827     IDirect3DDeviceImpl_7_GetInfo
6828 };
6829
6830 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6831 {
6832     /*** IUnknown Methods ***/
6833     Thunk_IDirect3DDeviceImpl_3_QueryInterface,
6834     Thunk_IDirect3DDeviceImpl_3_AddRef,
6835     Thunk_IDirect3DDeviceImpl_3_Release,
6836     /*** IDirect3DDevice3 ***/
6837     IDirect3DDeviceImpl_3_GetCaps,
6838     IDirect3DDeviceImpl_3_GetStats,
6839     IDirect3DDeviceImpl_3_AddViewport,
6840     IDirect3DDeviceImpl_3_DeleteViewport,
6841     IDirect3DDeviceImpl_3_NextViewport,
6842     Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
6843     Thunk_IDirect3DDeviceImpl_3_BeginScene,
6844     Thunk_IDirect3DDeviceImpl_3_EndScene,
6845     Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
6846     IDirect3DDeviceImpl_3_SetCurrentViewport,
6847     IDirect3DDeviceImpl_3_GetCurrentViewport,
6848     Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
6849     Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
6850     IDirect3DDeviceImpl_3_Begin,
6851     IDirect3DDeviceImpl_3_BeginIndexed,
6852     IDirect3DDeviceImpl_3_Vertex,
6853     IDirect3DDeviceImpl_3_Index,
6854     IDirect3DDeviceImpl_3_End,
6855     IDirect3DDeviceImpl_3_GetRenderState,
6856     IDirect3DDeviceImpl_3_SetRenderState,
6857     IDirect3DDeviceImpl_3_GetLightState,
6858     IDirect3DDeviceImpl_3_SetLightState,
6859     Thunk_IDirect3DDeviceImpl_3_SetTransform,
6860     Thunk_IDirect3DDeviceImpl_3_GetTransform,
6861     Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
6862     Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
6863     Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6864     Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
6865     Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
6866     Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6867     Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6868     Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6869     Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6870     Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6871     Thunk_IDirect3DDeviceImpl_3_GetTexture,
6872     IDirect3DDeviceImpl_3_SetTexture,
6873     Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
6874     Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
6875     Thunk_IDirect3DDeviceImpl_3_ValidateDevice
6876 };
6877
6878 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6879 {
6880     /*** IUnknown Methods ***/
6881     Thunk_IDirect3DDeviceImpl_2_QueryInterface,
6882     Thunk_IDirect3DDeviceImpl_2_AddRef,
6883     Thunk_IDirect3DDeviceImpl_2_Release,
6884     /*** IDirect3DDevice2 ***/
6885     Thunk_IDirect3DDeviceImpl_2_GetCaps,
6886     IDirect3DDeviceImpl_2_SwapTextureHandles,
6887     Thunk_IDirect3DDeviceImpl_2_GetStats,
6888     Thunk_IDirect3DDeviceImpl_2_AddViewport,
6889     Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
6890     Thunk_IDirect3DDeviceImpl_2_NextViewport,
6891     IDirect3DDeviceImpl_2_EnumTextureFormats,
6892     Thunk_IDirect3DDeviceImpl_2_BeginScene,
6893     Thunk_IDirect3DDeviceImpl_2_EndScene,
6894     Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
6895     Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
6896     Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
6897     Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
6898     Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
6899     Thunk_IDirect3DDeviceImpl_2_Begin,
6900     Thunk_IDirect3DDeviceImpl_2_BeginIndexed,
6901     Thunk_IDirect3DDeviceImpl_2_Vertex,
6902     Thunk_IDirect3DDeviceImpl_2_Index,
6903     Thunk_IDirect3DDeviceImpl_2_End,
6904     Thunk_IDirect3DDeviceImpl_2_GetRenderState,
6905     Thunk_IDirect3DDeviceImpl_2_SetRenderState,
6906     Thunk_IDirect3DDeviceImpl_2_GetLightState,
6907     Thunk_IDirect3DDeviceImpl_2_SetLightState,
6908     Thunk_IDirect3DDeviceImpl_2_SetTransform,
6909     Thunk_IDirect3DDeviceImpl_2_GetTransform,
6910     Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
6911     Thunk_IDirect3DDeviceImpl_2_DrawPrimitive,
6912     Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6913     Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
6914     Thunk_IDirect3DDeviceImpl_2_GetClipStatus
6915 };
6916
6917 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6918 {
6919     /*** IUnknown Methods ***/
6920     Thunk_IDirect3DDeviceImpl_1_QueryInterface,
6921     Thunk_IDirect3DDeviceImpl_1_AddRef,
6922     Thunk_IDirect3DDeviceImpl_1_Release,
6923     /*** IDirect3DDevice1 ***/
6924     IDirect3DDeviceImpl_1_Initialize,
6925     Thunk_IDirect3DDeviceImpl_1_GetCaps,
6926     Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
6927     IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6928     Thunk_IDirect3DDeviceImpl_1_GetStats,
6929     IDirect3DDeviceImpl_1_Execute,
6930     Thunk_IDirect3DDeviceImpl_1_AddViewport,
6931     Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
6932     Thunk_IDirect3DDeviceImpl_1_NextViewport,
6933     IDirect3DDeviceImpl_1_Pick,
6934     IDirect3DDeviceImpl_1_GetPickRecords,
6935     Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
6936     IDirect3DDeviceImpl_1_CreateMatrix,
6937     IDirect3DDeviceImpl_1_SetMatrix,
6938     IDirect3DDeviceImpl_1_GetMatrix,
6939     IDirect3DDeviceImpl_1_DeleteMatrix,
6940     Thunk_IDirect3DDeviceImpl_1_BeginScene,
6941     Thunk_IDirect3DDeviceImpl_1_EndScene,
6942     Thunk_IDirect3DDeviceImpl_1_GetDirect3D
6943 };
6944
6945 /*****************************************************************************
6946  * IDirect3DDeviceImpl_UpdateDepthStencil
6947  *
6948  * Checks the current render target for attached depth stencils and sets the
6949  * WineD3D depth stencil accordingly.
6950  *
6951  * Returns:
6952  *  The depth stencil state to set if creating the device
6953  *
6954  *****************************************************************************/
6955 WINED3DZBUFFERTYPE
6956 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6957 {
6958     IDirectDrawSurface7 *depthStencil = NULL;
6959     IDirectDrawSurfaceImpl *dsi;
6960     static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6961
6962     IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)This->target, &depthcaps, &depthStencil);
6963     if(!depthStencil)
6964     {
6965         TRACE("Setting wined3d depth stencil to NULL\n");
6966         IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6967                                               NULL);
6968         return WINED3DZB_FALSE;
6969     }
6970
6971     dsi = (IDirectDrawSurfaceImpl *)depthStencil;
6972     TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->WineD3DSurface);
6973     IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6974                                           dsi->WineD3DSurface);
6975
6976     IDirectDrawSurface7_Release(depthStencil);
6977     return WINED3DZB_TRUE;
6978 }
6979
6980 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
6981 {
6982     IParentImpl *index_buffer_parent;
6983     HRESULT hr;
6984
6985     if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6986         device->lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6987     else
6988         device->lpVtbl = &d3d_device7_fpu_setup_vtbl;
6989
6990     device->IDirect3DDevice3_vtbl = &d3d_device3_vtbl;
6991     device->IDirect3DDevice2_vtbl = &d3d_device2_vtbl;
6992     device->IDirect3DDevice_vtbl = &d3d_device1_vtbl;
6993     device->ref = 1;
6994     device->ddraw = ddraw;
6995     device->target = target;
6996
6997     if (!ddraw_handle_table_init(&device->handle_table, 64))
6998     {
6999         ERR("Failed to initialize handle table.\n");
7000         return DDERR_OUTOFMEMORY;
7001     }
7002
7003     device->legacyTextureBlending = FALSE;
7004
7005     /* Create an index buffer, it's needed for indexed drawing */
7006     index_buffer_parent = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*index_buffer_parent));
7007     if (!index_buffer_parent)
7008     {
7009         ERR("Failed to allocate index buffer parent memory.\n");
7010         ddraw_handle_table_destroy(&device->handle_table);
7011         return DDERR_OUTOFMEMORY;
7012     }
7013
7014     ddraw_parent_init(index_buffer_parent);
7015
7016     hr = IWineD3DDevice_CreateIndexBuffer(ddraw->wineD3DDevice, 0x40000 /* Length. Don't know how long it should be */,
7017             WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, &device->indexbuffer,
7018             (IUnknown *)index_buffer_parent, &ddraw_null_wined3d_parent_ops);
7019     if (FAILED(hr))
7020     {
7021         ERR("Failed to create an index buffer, hr %#x.\n", hr);
7022         HeapFree(GetProcessHeap(), 0, index_buffer_parent);
7023         ddraw_handle_table_destroy(&device->handle_table);
7024         return hr;
7025     }
7026     index_buffer_parent->child = (IUnknown *)device->indexbuffer;
7027
7028     /* This is for convenience. */
7029     device->wineD3DDevice = ddraw->wineD3DDevice;
7030     IWineD3DDevice_AddRef(ddraw->wineD3DDevice);
7031
7032     /* This is for apps which create a non-flip, non-d3d primary surface
7033      * and an offscreen D3DDEVICE surface, then render to the offscreen surface
7034      * and do a Blt from the offscreen to the primary surface.
7035      *
7036      * Set the offscreen D3DDDEVICE surface(=target) as the back buffer,
7037      * and the primary surface(=This->d3d_target) as the front buffer.
7038      *
7039      * This way the app will render to the D3DDEVICE surface and WineD3D
7040      * will catch the Blt was Back Buffer -> Front buffer blt and perform
7041      * a flip instead. This way we don't have to deal with a mixed GL / GDI
7042      * environment.
7043      *
7044      * This should be checked against windowed apps. The only app tested with
7045      * this is moto racer 2 during the loading screen.
7046      */
7047     TRACE("Is rendertarget: %s, d3d_target %p.\n",
7048             target->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ? "true" : "false", ddraw->d3d_target);
7049
7050     if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
7051             && ddraw->d3d_target != target)
7052     {
7053         TRACE("Using %p as front buffer, %p as back buffer.\n", ddraw->d3d_target, target);
7054
7055         hr = IWineD3DDevice_SetFrontBackBuffers(ddraw->wineD3DDevice,
7056                 ddraw->d3d_target->WineD3DSurface, target->WineD3DSurface);
7057         if (FAILED(hr))
7058         {
7059             ERR("Failed to set front and back buffer, hr %#x.\n", hr);
7060             IParent_Release((IParent *)index_buffer_parent);
7061             ddraw_handle_table_destroy(&device->handle_table);
7062             return hr;
7063         }
7064
7065         /* Render to the back buffer */
7066         IWineD3DDevice_SetRenderTarget(ddraw->wineD3DDevice, 0, target->WineD3DSurface, TRUE);
7067         device->OffScreenTarget = TRUE;
7068     }
7069     else
7070     {
7071         device->OffScreenTarget = FALSE;
7072     }
7073
7074     /* FIXME: This is broken. The target AddRef() makes some sense, because
7075      * we store a pointer during initialization, but then that's also where
7076      * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
7077     /* AddRef the render target. Also AddRef the render target from ddraw,
7078      * because if it is released before the app releases the D3D device, the
7079      * D3D capabilities of wined3d will be uninitialized, which has bad effects.
7080      *
7081      * In most cases, those surfaces are the same anyway, but this will simply
7082      * add another ref which is released when the device is destroyed. */
7083     IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)target);
7084     IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)ddraw->d3d_target);
7085
7086     ddraw->d3ddevice = device;
7087
7088     IWineD3DDevice_SetRenderState(ddraw->wineD3DDevice, WINED3DRS_ZENABLE,
7089             IDirect3DDeviceImpl_UpdateDepthStencil(device));
7090
7091     return D3D_OK;
7092 }