winex11: add owned windows to taskbar if owner is not mapped
[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  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * IDirect3DDevice implementation, version 1, 2, 3 and 7. Rendering is relayed
21  * to WineD3D, some minimal DirectDraw specific management is handled here.
22  * The Direct3DDevice is NOT the parent of the WineD3DDevice, because d3d
23  * is initialized when DirectDraw creates the primary surface.
24  * Some type management is necessary, because some D3D types changed between
25  * D3D7 and D3D9.
26  *
27  */
28
29 #include "config.h"
30 #include "wine/port.h"
31
32 #include <assert.h>
33 #include <stdarg.h>
34 #include <string.h>
35 #include <stdlib.h>
36
37 #define COBJMACROS
38 #define NONAMELESSUNION
39
40 #include "windef.h"
41 #include "winbase.h"
42 #include "winerror.h"
43 #include "wingdi.h"
44 #include "wine/exception.h"
45
46 #include "ddraw.h"
47 #include "d3d.h"
48
49 #include "ddraw_private.h"
50 #include "wine/debug.h"
51
52 WINE_DEFAULT_DEBUG_CHANNEL(d3d7);
53 WINE_DECLARE_DEBUG_CHANNEL(ddraw_thunk);
54
55 /* The device ID */
56 const GUID IID_D3DDEVICE_WineD3D = {
57   0xaef72d43,
58   0xb09a,
59   0x4b7b,
60   { 0xb7,0x98,0xc6,0x8a,0x77,0x2d,0x72,0x2a }
61 };
62
63 /*****************************************************************************
64  * IUnknown Methods. Common for Version 1, 2, 3 and 7 
65  *****************************************************************************/
66
67 /*****************************************************************************
68  * IDirect3DDevice7::QueryInterface
69  *
70  * Used to query other interfaces from a Direct3DDevice interface.
71  * It can return interface pointers to all Direct3DDevice versions as well
72  * as IDirectDraw and IDirect3D. For a link to QueryInterface
73  * rules see ddraw.c, IDirectDraw7::QueryInterface
74  *
75  * Exists in Version 1, 2, 3 and 7
76  *
77  * Params:
78  *  refiid: Interface ID queried for
79  *  obj: Used to return the interface pointer
80  *
81  * Returns:
82  *  D3D_OK or E_NOINTERFACE
83  *
84  *****************************************************************************/
85 static HRESULT WINAPI
86 IDirect3DDeviceImpl_7_QueryInterface(IDirect3DDevice7 *iface,
87                                      REFIID refiid,
88                                      void **obj)
89 {
90     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
91     TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(refiid), obj);
92
93     /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
94     *obj = NULL;
95
96     if(!refiid)
97         return DDERR_INVALIDPARAMS;
98
99     if ( IsEqualGUID( &IID_IUnknown, refiid ) )
100     {
101         *obj = ICOM_INTERFACE(This, IDirect3DDevice7);
102     }
103
104     /* Check DirectDraw Interfac\ 1s */
105     else if( IsEqualGUID( &IID_IDirectDraw7, refiid ) )
106     {
107         *obj = ICOM_INTERFACE(This->ddraw, IDirectDraw7);
108         TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
109     }
110     else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
111     {
112         *obj = ICOM_INTERFACE(This->ddraw, IDirectDraw4);
113         TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
114     }
115     else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
116     {
117         *obj = ICOM_INTERFACE(This->ddraw, IDirectDraw2);
118         TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
119     }
120     else if( IsEqualGUID( &IID_IDirectDraw, refiid ) )
121     {
122         *obj = ICOM_INTERFACE(This->ddraw, IDirectDraw);
123         TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
124     }
125
126     /* Direct3D */
127     else if ( IsEqualGUID( &IID_IDirect3D  , refiid ) )
128     {
129         *obj = ICOM_INTERFACE(This->ddraw, IDirect3D);
130         TRACE("(%p) Returning IDirect3D interface at %p\n", This, *obj);
131     }
132     else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) )
133     {
134         *obj = ICOM_INTERFACE(This->ddraw, IDirect3D2);
135         TRACE("(%p) Returning IDirect3D2 interface at %p\n", This, *obj);
136     }
137     else if ( IsEqualGUID( &IID_IDirect3D3 , refiid ) )
138     {
139         *obj = ICOM_INTERFACE(This->ddraw, IDirect3D3);
140         TRACE("(%p) Returning IDirect3D3 interface at %p\n", This, *obj);
141     }
142     else if ( IsEqualGUID( &IID_IDirect3D7 , refiid ) )
143     {
144         *obj = ICOM_INTERFACE(This->ddraw, IDirect3D7);
145         TRACE("(%p) Returning IDirect3D7 interface at %p\n", This, *obj);
146     }
147
148     /* Direct3DDevice */
149     else if ( IsEqualGUID( &IID_IDirect3DDevice  , refiid ) )
150     {
151         *obj = ICOM_INTERFACE(This, IDirect3DDevice);
152         TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
153     }
154     else if ( IsEqualGUID( &IID_IDirect3DDevice2  , refiid ) ) {
155         *obj = ICOM_INTERFACE(This, IDirect3DDevice2);
156         TRACE("(%p) Returning IDirect3DDevice2 interface at %p\n", This, *obj);
157     }
158     else if ( IsEqualGUID( &IID_IDirect3DDevice3  , refiid ) ) {
159         *obj = ICOM_INTERFACE(This, IDirect3DDevice3);
160         TRACE("(%p) Returning IDirect3DDevice3 interface at %p\n", This, *obj);
161     }
162     else if ( IsEqualGUID( &IID_IDirect3DDevice7  , refiid ) ) {
163         *obj = ICOM_INTERFACE(This, IDirect3DDevice7);
164         TRACE("(%p) Returning IDirect3DDevice7 interface at %p\n", This, *obj);
165     }
166
167     /* Unknown interface */
168     else
169     {
170         ERR("(%p)->(%s, %p): No interface found\n", This, debugstr_guid(refiid), obj);
171         return E_NOINTERFACE;
172     }
173
174     /* AddRef the returned interface */
175     IUnknown_AddRef( (IUnknown *) *obj);
176     return D3D_OK;
177 }
178
179 static HRESULT WINAPI
180 Thunk_IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface,
181                                            REFIID riid,
182                                            void **obj)
183 {
184     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
185     TRACE_(ddraw_thunk)("(%p)->(%s,%p) thunking to IDirect3DDevice7 interface.\n", This, debugstr_guid(riid), obj);
186     return IDirect3DDevice7_QueryInterface(ICOM_INTERFACE(This, IDirect3DDevice7),
187                                            riid,
188                                            obj);
189 }
190
191 static HRESULT WINAPI
192 Thunk_IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface,
193                                            REFIID riid,
194                                            void **obj)
195 {
196     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
197     TRACE_(ddraw_thunk)("(%p)->(%s,%p) thunking to IDirect3DDevice7 interface.\n", This, debugstr_guid(riid), obj);
198     return IDirect3DDevice7_QueryInterface(ICOM_INTERFACE(This, IDirect3DDevice7),
199                                            riid,
200                                            obj);
201 }
202
203 static HRESULT WINAPI
204 Thunk_IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface,
205                                            REFIID riid,
206                                            void **obp)
207 {
208     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
209     TRACE_(ddraw_thunk)("(%p)->(%s,%p) thunking to IDirect3DDevice7 interface.\n", This, debugstr_guid(riid), obp);
210     return IDirect3DDevice7_QueryInterface(ICOM_INTERFACE(This, IDirect3DDevice7),
211                                            riid,
212                                            obp);
213 }
214
215 /*****************************************************************************
216  * IDirect3DDevice7::AddRef
217  *
218  * Increases the refcount....
219  * The most exciting Method, definitely
220  *
221  * Exists in Version 1, 2, 3 and 7
222  *
223  * Returns:
224  *  The new refcount
225  *
226  *****************************************************************************/
227 static ULONG WINAPI
228 IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
229 {
230     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
231     ULONG ref = InterlockedIncrement(&This->ref);
232
233     TRACE("(%p) : incrementing from %u.\n", This, ref -1);
234
235     return ref;
236 }
237
238 static ULONG WINAPI
239 Thunk_IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
240 {
241     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
242     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
243     return IDirect3DDevice7_AddRef(ICOM_INTERFACE(This, IDirect3DDevice7));
244 }
245
246 static ULONG WINAPI
247 Thunk_IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
248 {
249     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
250     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
251     return IDirect3DDevice7_AddRef(ICOM_INTERFACE(This, IDirect3DDevice7));
252 }
253
254 static ULONG WINAPI
255 Thunk_IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
256 {
257     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", iface);
258     return IDirect3DDevice7_AddRef(COM_INTERFACE_CAST(IDirect3DDeviceImpl, IDirect3DDevice, IDirect3DDevice7, iface));
259 }
260
261 /*****************************************************************************
262  * IDirect3DDevice7::Release
263  *
264  * Decreases the refcount of the interface
265  * When the refcount is reduced to 0, the object is destroyed.
266  *
267  * Exists in Version 1, 2, 3 and 7
268  *
269  * Returns:d
270  *  The new refcount
271  *
272  *****************************************************************************/
273 static ULONG WINAPI
274 IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
275 {
276     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
277     ULONG ref = InterlockedDecrement(&This->ref);
278
279     TRACE("(%p)->() decrementing from %u.\n", This, ref +1);
280
281     /* This method doesn't destroy the WineD3DDevice, because it's still in use for
282      * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
283      * when the render target is released
284      */
285     if (ref == 0)
286     {
287         IParent *IndexBufferParent;
288         DWORD i;
289
290         EnterCriticalSection(&ddraw_cs);
291         /* Free the index buffer. */
292         IWineD3DDevice_SetIndices(This->wineD3DDevice, NULL);
293         IWineD3DIndexBuffer_GetParent(This->indexbuffer,
294                                       (IUnknown **) &IndexBufferParent);
295         IParent_Release(IndexBufferParent); /* Once for the getParent */
296         if( IParent_Release(IndexBufferParent) != 0)  /* And now to destroy it */
297         {
298             ERR(" (%p) Something is still holding the index buffer parent %p\n", This, IndexBufferParent);
299         }
300
301         /* There is no need to unset the vertex buffer here, IWineD3DDevice_Uninit3D will do that when
302          * destroying the primary stateblock. If a vertex buffer is destroyed while it is bound
303          * IDirect3DVertexBuffer::Release will unset it.
304          */
305
306         /* Restore the render targets */
307         if(This->OffScreenTarget)
308         {
309             WINED3DVIEWPORT vp;
310
311             vp.X = 0;
312             vp.Y = 0;
313             vp.Width = This->ddraw->d3d_target->surface_desc.dwWidth;
314             vp.Height = This->ddraw->d3d_target->surface_desc.dwHeight;
315             vp.MinZ = 0.0;
316             vp.MaxZ = 1.0;
317             IWineD3DDevice_SetViewport(This->wineD3DDevice,
318                                        &vp);
319
320             /* Set the device up to render to the front buffer since the back buffer will
321              * vanish soon.
322              */
323             IWineD3DDevice_SetRenderTarget(This->wineD3DDevice, 0,
324                                            This->ddraw->d3d_target->WineD3DSurface);
325             /* This->target is the offscreen target.
326              * This->ddraw->d3d_target is the target used by DDraw
327              */
328             TRACE("(%p) Release: Using %p as front buffer, %p as back buffer\n", This, This->ddraw->d3d_target, NULL);
329             IWineD3DDevice_SetFrontBackBuffers(This->wineD3DDevice,
330                                                This->ddraw->d3d_target->WineD3DSurface,
331                                                NULL);
332         }
333
334         /* Release the WineD3DDevice. This won't destroy it */
335         if(IWineD3DDevice_Release(This->wineD3DDevice) <= 0)
336         {
337             ERR(" (%p) The wineD3D device %p was destroyed unexpectadely. Prepare for trouble\n", This, This->wineD3DDevice);
338         }
339
340         /* The texture handles should be unset by now, but there might be some bits
341          * missing in our reference counting(needs test). Do a sanity check
342          */
343         for(i = 0; i < This->numHandles; i++)
344         {
345             if(This->Handles[i].ptr)
346             {
347                 switch(This->Handles[i].type)
348                 {
349                     case DDrawHandle_Texture:
350                     {
351                         IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *) This->Handles[i].ptr;
352                         FIXME("Texture Handle %d not unset properly\n", i + 1);
353                         surf->Handle = 0;
354                     }
355                     break;
356
357                     case DDrawHandle_Material:
358                     {
359                         IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) This->Handles[i].ptr;
360                         FIXME("Material handle %d not unset properly\n", i + 1);
361                         mat->Handle = 0;
362                     }
363                     break;
364
365                     case DDrawHandle_Matrix:
366                     {
367                         /* No fixme here because this might happen because of sloppy apps */
368                         WARN("Leftover matrix handle %d, deleting\n", i + 1);
369                         IDirect3DDevice_DeleteMatrix(ICOM_INTERFACE(This, IDirect3DDevice),
370                                                      i + 1);
371                     }
372                     break;
373
374                     case DDrawHandle_StateBlock:
375                     {
376                         /* No fixme here because this might happen because of sloppy apps */
377                         WARN("Leftover stateblock handle %d, deleting\n", i + 1);
378                         IDirect3DDevice7_DeleteStateBlock(ICOM_INTERFACE(This, IDirect3DDevice7),
379                                                           i + 1);
380                     }
381                     break;
382
383                     default:
384                         FIXME("Unknown handle %d not unset properly\n", i + 1);
385                 }
386             }
387         }
388
389         HeapFree(GetProcessHeap(), 0, This->Handles);
390
391         TRACE("Releasing target %p %p\n", This->target, This->ddraw->d3d_target);
392         /* Release the render target and the WineD3D render target
393          * (See IDirect3D7::CreateDevice for more comments on this)
394          */
395         IDirectDrawSurface7_Release(ICOM_INTERFACE(This->target, IDirectDrawSurface7));
396         IDirectDrawSurface7_Release(ICOM_INTERFACE(This->ddraw->d3d_target,IDirectDrawSurface7));
397         TRACE("Target release done\n");
398
399         This->ddraw->d3ddevice = NULL;
400
401         /* Now free the structure */
402         HeapFree(GetProcessHeap(), 0, This);
403         LeaveCriticalSection(&ddraw_cs);
404     }
405
406     TRACE("Done\n");
407     return ref;
408 }
409
410 static ULONG WINAPI
411 Thunk_IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
412 {
413     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
414     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
415     return IDirect3DDevice7_Release(ICOM_INTERFACE(This, IDirect3DDevice7));
416 }
417
418 static ULONG WINAPI
419 Thunk_IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
420 {
421     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
422     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
423     return IDirect3DDevice7_Release(ICOM_INTERFACE(This, IDirect3DDevice7));
424 }
425
426 static ULONG WINAPI
427 Thunk_IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
428 {
429     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
430     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
431     return IDirect3DDevice7_Release(ICOM_INTERFACE(This, IDirect3DDevice7));
432 }
433
434 /*****************************************************************************
435  * IDirect3DDevice Methods
436  *****************************************************************************/
437
438 /*****************************************************************************
439  * IDirect3DDevice::Initialize
440  *
441  * Initializes a Direct3DDevice. This implementation is a no-op, as all
442  * initialization is done at create time.
443  *
444  * Exists in Version 1
445  *
446  * Parameters:
447  *  No idea what they mean, as the MSDN page is gone
448  *
449  * Returns: DD_OK
450  *
451  *****************************************************************************/
452 static HRESULT WINAPI
453 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
454                                  IDirect3D *Direct3D, GUID *guid,
455                                  D3DDEVICEDESC *Desc)
456 {
457     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
458
459     /* It shouldn't be crucial, but print a FIXME, I'm interested if
460      * any game calls it and when
461      */
462     FIXME("(%p)->(%p,%p,%p): No-op!\n", This, Direct3D, guid, Desc);
463
464     return D3D_OK;
465 }
466
467 /*****************************************************************************
468  * IDirect3DDevice7::GetCaps
469  *
470  * Retrieves the device's capabilities
471  *
472  * This implementation is used for Version 7 only, the older versions have
473  * their own implementation.
474  *
475  * Parameters:
476  *  Desc: Pointer to a D3DDEVICEDESC7 structure to fill
477  *
478  * Returns:
479  *  D3D_OK on success
480  *  D3DERR_* if a problem occurs. See WineD3D
481  *
482  *****************************************************************************/
483 static HRESULT WINAPI
484 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
485                               D3DDEVICEDESC7 *Desc)
486 {
487     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
488     D3DDEVICEDESC OldDesc;
489     TRACE("(%p)->(%p)\n", This, Desc);
490
491     /* Call the same function used by IDirect3D, this saves code */
492     return IDirect3DImpl_GetCaps(This->ddraw->wineD3D, &OldDesc, Desc);
493 }
494
495 /*****************************************************************************
496  * IDirect3DDevice3::GetCaps
497  *
498  * Retrieves the capabilities of the hardware device and the emulation
499  * device. For Wine, hardware and emulation are the same (it's all HW).
500  *
501  * This implementation is used for Version 1, 2, and 3. Version 7 has its own
502  *
503  * Parameters:
504  *  HWDesc: Structure to fill with the HW caps
505  *  HelDesc: Structure to fill with the hardware emulation caps
506  *
507  * Returns:
508  *  D3D_OK on success
509  *  D3DERR_* if a problem occurs. See WineD3D
510  *
511  *****************************************************************************/
512 static HRESULT WINAPI
513 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
514                               D3DDEVICEDESC *HWDesc,
515                               D3DDEVICEDESC *HelDesc)
516 {
517     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
518     D3DDEVICEDESC7 newDesc;
519     HRESULT hr;
520     TRACE("(%p)->(%p,%p)\n", iface, HWDesc, HelDesc);
521
522     hr = IDirect3DImpl_GetCaps(This->ddraw->wineD3D, HWDesc, &newDesc);
523     if(hr != D3D_OK) return hr;
524
525     *HelDesc = *HWDesc;
526     return D3D_OK;
527 }
528
529 static HRESULT WINAPI
530 Thunk_IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
531                                     D3DDEVICEDESC *D3DHWDevDesc,
532                                     D3DDEVICEDESC *D3DHELDevDesc)
533 {
534     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
535     TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice3 interface.\n", This, D3DHWDevDesc, D3DHELDevDesc);
536     return IDirect3DDevice3_GetCaps(ICOM_INTERFACE(This, IDirect3DDevice3),
537                                     D3DHWDevDesc,
538                                     D3DHELDevDesc);
539 }
540
541 static HRESULT WINAPI
542 Thunk_IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
543                                     D3DDEVICEDESC *D3DHWDevDesc,
544                                     D3DDEVICEDESC *D3DHELDevDesc)
545 {
546     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
547     TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice3 interface.\n", This, D3DHWDevDesc, D3DHELDevDesc);
548     return IDirect3DDevice3_GetCaps(ICOM_INTERFACE(This, IDirect3DDevice3),
549                                     D3DHWDevDesc,
550                                     D3DHELDevDesc);
551 }
552
553 /*****************************************************************************
554  * IDirect3DDevice2::SwapTextureHandles
555  *
556  * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
557  *
558  * Parameters:
559  *  Tex1, Tex2: The 2 Textures to swap
560  *
561  * Returns:
562  *  D3D_OK
563  *
564  *****************************************************************************/
565 static HRESULT WINAPI
566 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
567                                          IDirect3DTexture2 *Tex1,
568                                          IDirect3DTexture2 *Tex2)
569 {
570     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
571     DWORD swap;
572     IDirectDrawSurfaceImpl *surf1 = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture2, Tex1);
573     IDirectDrawSurfaceImpl *surf2 = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture2, Tex2);
574     TRACE("(%p)->(%p,%p)\n", This, surf1, surf2);
575
576     EnterCriticalSection(&ddraw_cs);
577     This->Handles[surf1->Handle - 1].ptr = surf2;
578     This->Handles[surf2->Handle - 1].ptr = surf1;
579
580     swap = surf2->Handle;
581     surf2->Handle = surf1->Handle;
582     surf1->Handle = swap;
583     LeaveCriticalSection(&ddraw_cs);
584
585     return D3D_OK;
586 }
587
588 static HRESULT WINAPI
589 Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
590                                                IDirect3DTexture *D3DTex1,
591                                                IDirect3DTexture *D3DTex2)
592 {
593     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
594     IDirectDrawSurfaceImpl *surf1 = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture, D3DTex1);
595     IDirectDrawSurfaceImpl *surf2 = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture, D3DTex2);
596     TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice2 interface.\n", This, surf1, surf2);
597     return IDirect3DDevice2_SwapTextureHandles(ICOM_INTERFACE(This, IDirect3DDevice2),
598                                                ICOM_INTERFACE(surf1, IDirect3DTexture2),
599                                                ICOM_INTERFACE(surf2, IDirect3DTexture2));
600 }
601
602 /*****************************************************************************
603  * IDirect3DDevice3::GetStats
604  *
605  * This method seems to retrieve some stats from the device.
606  * The MSDN documentation doesn't exist any more, but the D3DSTATS
607  * structure suggests that the amount of drawn primitives and processed
608  * vertices is returned.
609  *
610  * Exists in Version 1, 2 and 3
611  *
612  * Parameters:
613  *  Stats: Pointer to a D3DSTATS structure to be filled
614  *
615  * Returns:
616  *  D3D_OK on success
617  *  DDERR_INVALIDPARAMS if Stats == NULL
618  *
619  *****************************************************************************/
620 static HRESULT WINAPI
621 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
622                                D3DSTATS *Stats)
623 {
624     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
625     FIXME("(%p)->(%p): Stub!\n", This, Stats);
626
627     if(!Stats)
628         return DDERR_INVALIDPARAMS;
629
630     /* Fill the Stats with 0 */
631     Stats->dwTrianglesDrawn = 0;
632     Stats->dwLinesDrawn = 0;
633     Stats->dwPointsDrawn = 0;
634     Stats->dwSpansDrawn = 0;
635     Stats->dwVerticesProcessed = 0;
636
637     return D3D_OK;
638 }
639
640 static HRESULT WINAPI
641 Thunk_IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface,
642                                      D3DSTATS *Stats)
643 {
644     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
645     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, Stats);
646     return IDirect3DDevice3_GetStats(ICOM_INTERFACE(This, IDirect3DDevice3),
647                                      Stats);
648 }
649
650 static HRESULT WINAPI
651 Thunk_IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface,
652                                      D3DSTATS *Stats)
653 {
654     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
655     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, Stats);
656     return IDirect3DDevice3_GetStats(ICOM_INTERFACE(This, IDirect3DDevice3),
657                                      Stats);
658 }
659
660 /*****************************************************************************
661  * IDirect3DDevice::CreateExecuteBuffer
662  *
663  * Creates an IDirect3DExecuteBuffer, used for rendering with a
664  * Direct3DDevice.
665  *
666  * Version 1 only.
667  *
668  * Params:
669  *  Desc: Buffer description
670  *  ExecuteBuffer: Address to return the Interface pointer at
671  *  UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
672  *            support
673  *
674  * Returns:
675  *  CLASS_E_NOAGGREGATION if UnkOuter != NULL
676  *  DDERR_OUTOFMEMORY if we ran out of memory
677  *  D3D_OK on success
678  *
679  *****************************************************************************/
680 static HRESULT WINAPI
681 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
682                                           D3DEXECUTEBUFFERDESC *Desc,
683                                           IDirect3DExecuteBuffer **ExecuteBuffer,
684                                           IUnknown *UnkOuter)
685 {
686     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
687     IDirect3DExecuteBufferImpl* object;
688     TRACE("(%p)->(%p,%p,%p)!\n", This, Desc, ExecuteBuffer, UnkOuter);
689
690     if(UnkOuter)
691         return CLASS_E_NOAGGREGATION;
692
693     /* Allocate the new Execute Buffer */
694     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
695     if(!object)
696     {
697         ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
698         return DDERR_OUTOFMEMORY;
699     }
700
701     ICOM_INIT_INTERFACE(object, IDirect3DExecuteBuffer, IDirect3DExecuteBuffer_Vtbl);
702
703     object->ref = 1;
704     object->d3ddev = This;
705
706     /* Initializes memory */
707     memcpy(&object->desc, Desc, Desc->dwSize);
708
709     /* No buffer given */
710     if ((object->desc.dwFlags & D3DDEB_LPDATA) == 0)
711         object->desc.lpData = NULL;
712
713     /* No buffer size given */
714     if ((object->desc.dwFlags & D3DDEB_BUFSIZE) == 0)
715         object->desc.dwBufferSize = 0;
716
717     /* Create buffer if asked */
718     if ((object->desc.lpData == NULL) && (object->desc.dwBufferSize > 0))
719     {
720         object->need_free = TRUE;
721         object->desc.lpData = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,object->desc.dwBufferSize);
722         if(!object->desc.lpData)
723         {
724             ERR("Out of memory when allocating the execute buffer data\n");
725             HeapFree(GetProcessHeap(), 0, object);
726             return DDERR_OUTOFMEMORY;
727         }
728     }
729     else
730     {
731         object->need_free = FALSE;
732     }
733
734     /* No vertices for the moment */
735     object->vertex_data = NULL;
736
737     object->desc.dwFlags |= D3DDEB_LPDATA;
738
739     object->indices = NULL;
740     object->nb_indices = 0;
741
742     *ExecuteBuffer = ICOM_INTERFACE(object, IDirect3DExecuteBuffer);
743
744     TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
745
746     return D3D_OK;
747 }
748
749 /*****************************************************************************
750  * IDirect3DDevice::Execute
751  *
752  * Executes all the stuff in an execute buffer.
753  *
754  * Params:
755  *  ExecuteBuffer: The buffer to execute
756  *  Viewport: The viewport used for rendering
757  *  Flags: Some flags
758  *
759  * Returns:
760  *  DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
761  *  D3D_OK on success
762  *
763  *****************************************************************************/
764 static HRESULT WINAPI
765 IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
766                               IDirect3DExecuteBuffer *ExecuteBuffer,
767                               IDirect3DViewport *Viewport,
768                               DWORD Flags)
769 {
770     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
771     IDirect3DExecuteBufferImpl *Direct3DExecuteBufferImpl = ICOM_OBJECT(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, ExecuteBuffer);
772     IDirect3DViewportImpl *Direct3DViewportImpl = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Viewport);
773
774     TRACE("(%p)->(%p,%p,%08x)\n", This, Direct3DExecuteBufferImpl, Direct3DViewportImpl, Flags);
775
776     if(!Direct3DExecuteBufferImpl)
777         return DDERR_INVALIDPARAMS;
778
779     /* Execute... */
780     EnterCriticalSection(&ddraw_cs);
781     IDirect3DExecuteBufferImpl_Execute(Direct3DExecuteBufferImpl, This, Direct3DViewportImpl);
782     LeaveCriticalSection(&ddraw_cs);
783
784     return D3D_OK;
785 }
786
787 /*****************************************************************************
788  * IDirect3DDevice3::AddViewport
789  *
790  * Add a Direct3DViewport to the device's viewport list. These viewports
791  * are wrapped to IDirect3DDevice7 viewports in viewport.c
792  *
793  * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
794  * are the same interfaces.
795  *
796  * Params:
797  *  Viewport: The viewport to add
798  *
799  * Returns:
800  *  DDERR_INVALIDPARAMS if Viewport == NULL
801  *  D3D_OK on success
802  *
803  *****************************************************************************/
804 static HRESULT WINAPI
805 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
806                                   IDirect3DViewport3 *Viewport)
807 {
808     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
809     IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Viewport);
810
811     TRACE("(%p)->(%p)\n", This, vp);
812
813     /* Sanity check */
814     if(!vp)
815         return DDERR_INVALIDPARAMS;
816
817     EnterCriticalSection(&ddraw_cs);
818     vp->next = This->viewport_list;
819     This->viewport_list = vp;
820     vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
821                                     so set active_device here. */
822     LeaveCriticalSection(&ddraw_cs);
823
824     return D3D_OK;
825 }
826
827 static HRESULT WINAPI
828 Thunk_IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
829                                         IDirect3DViewport2 *Direct3DViewport2)
830 {
831     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
832     IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Direct3DViewport2);
833     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
834     return IDirect3DDevice3_AddViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
835                                         ICOM_INTERFACE(vp, IDirect3DViewport3));
836 }
837
838 static HRESULT WINAPI
839 Thunk_IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
840                                         IDirect3DViewport *Direct3DViewport)
841 {
842     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
843     IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Direct3DViewport);
844     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
845     return IDirect3DDevice3_AddViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
846                                         ICOM_INTERFACE(vp, IDirect3DViewport3));
847 }
848
849 /*****************************************************************************
850  * IDirect3DDevice3::DeleteViewport
851  *
852  * Deletes a Direct3DViewport from the device's viewport list.
853  *
854  * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
855  * are equal.
856  *
857  * Params:
858  *  Viewport: The viewport to delete
859  *
860  * Returns:
861  *  D3D_OK on success
862  *  DDERR_INVALIDPARAMS if the viewport wasn't found in the list
863  *
864  *****************************************************************************/
865 static HRESULT WINAPI
866 IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface,
867                                      IDirect3DViewport3 *Viewport)
868 {
869     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
870     IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *) Viewport;
871     IDirect3DViewportImpl *cur_viewport, *prev_viewport = NULL;
872
873     TRACE("(%p)->(%p)\n", This, vp);
874
875     EnterCriticalSection(&ddraw_cs);
876     cur_viewport = This->viewport_list;
877     while (cur_viewport != NULL)
878     {
879         if (cur_viewport == vp)
880         {
881             if (prev_viewport == NULL) This->viewport_list = cur_viewport->next;
882             else prev_viewport->next = cur_viewport->next;
883             /* TODO : add desactivate of the viewport and all associated lights... */
884             LeaveCriticalSection(&ddraw_cs);
885             return D3D_OK;
886         }
887         prev_viewport = cur_viewport;
888         cur_viewport = cur_viewport->next;
889     }
890
891     LeaveCriticalSection(&ddraw_cs);
892     return DDERR_INVALIDPARAMS;
893 }
894
895 static HRESULT WINAPI
896 Thunk_IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
897                                            IDirect3DViewport2 *Direct3DViewport2)
898 {
899     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
900     IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Direct3DViewport2);
901     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
902     return IDirect3DDevice3_DeleteViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
903                                            ICOM_INTERFACE(vp, IDirect3DViewport3));
904 }
905
906 static HRESULT WINAPI
907 Thunk_IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
908                                            IDirect3DViewport *Direct3DViewport)
909 {
910     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
911     IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Direct3DViewport);
912     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
913     return IDirect3DDevice3_DeleteViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
914                                            ICOM_INTERFACE(vp, IDirect3DViewport3));
915 }
916
917 /*****************************************************************************
918  * IDirect3DDevice3::NextViewport
919  *
920  * Returns a viewport from the viewport list, depending on the
921  * passed viewport and the flags.
922  *
923  * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
924  * are equal.
925  *
926  * Params:
927  *  Viewport: Viewport to use for beginning the search
928  *  Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
929  *
930  * Returns:
931  *  D3D_OK on success
932  *  DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
933  *
934  *****************************************************************************/
935 static HRESULT WINAPI
936 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
937                                    IDirect3DViewport3 *Viewport3,
938                                    IDirect3DViewport3 **lplpDirect3DViewport3,
939                                    DWORD Flags)
940 {
941     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
942     IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Viewport3);
943     IDirect3DViewportImpl *res = NULL;
944
945     TRACE("(%p)->(%p,%p,%08x)\n", This, vp, lplpDirect3DViewport3, Flags);
946
947     if(!vp)
948     {
949         *lplpDirect3DViewport3 = NULL;
950         return DDERR_INVALIDPARAMS;
951     }
952
953
954     EnterCriticalSection(&ddraw_cs);
955     switch (Flags)
956     {
957         case D3DNEXT_NEXT:
958         {
959             res = vp->next;
960         }
961         break;
962         case D3DNEXT_HEAD:
963         {
964             res = This->viewport_list;
965         }
966         break;
967         case D3DNEXT_TAIL:
968         {
969             IDirect3DViewportImpl *cur_viewport = This->viewport_list;
970             if (cur_viewport != NULL)
971             {
972                 while (cur_viewport->next != NULL) cur_viewport = cur_viewport->next;
973             }
974             res = cur_viewport;
975         }
976         break;
977         default:
978             *lplpDirect3DViewport3 = NULL;
979             LeaveCriticalSection(&ddraw_cs);
980             return DDERR_INVALIDPARAMS;
981     }
982
983     *lplpDirect3DViewport3 = ICOM_INTERFACE(res, IDirect3DViewport3);
984     LeaveCriticalSection(&ddraw_cs);
985     return D3D_OK;
986 }
987
988 static HRESULT WINAPI
989 Thunk_IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
990                                          IDirect3DViewport2 *Viewport2,
991                                          IDirect3DViewport2 **lplpDirect3DViewport2,
992                                          DWORD Flags)
993 {
994     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
995     IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Viewport2);
996     IDirect3DViewport3 *res;
997     HRESULT hr;
998     TRACE_(ddraw_thunk)("(%p)->(%p,%p,%08x) thunking to IDirect3DDevice3 interface.\n", This, vp, lplpDirect3DViewport2, Flags);
999     hr = IDirect3DDevice3_NextViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
1000                                        ICOM_INTERFACE(vp, IDirect3DViewport3),
1001                                        &res,
1002                                        Flags);
1003     *lplpDirect3DViewport2 = (IDirect3DViewport2 *) COM_INTERFACE_CAST(IDirect3DViewportImpl, IDirect3DViewport3, IDirect3DViewport3, res);
1004     return hr;
1005 }
1006
1007 static HRESULT WINAPI
1008 Thunk_IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
1009                                          IDirect3DViewport *Viewport,
1010                                          IDirect3DViewport **lplpDirect3DViewport,
1011                                          DWORD Flags)
1012 {
1013     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1014     IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Viewport);
1015     IDirect3DViewport3 *res;
1016     HRESULT hr;
1017     TRACE_(ddraw_thunk)("(%p)->(%p,%p,%08x) thunking to IDirect3DDevice3 interface.\n", This, vp, lplpDirect3DViewport, Flags);
1018     hr = IDirect3DDevice3_NextViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
1019                                        ICOM_INTERFACE(vp, IDirect3DViewport3),
1020                                        &res,
1021                                        Flags);
1022     *lplpDirect3DViewport = (IDirect3DViewport *) COM_INTERFACE_CAST(IDirect3DViewportImpl, IDirect3DViewport3, IDirect3DViewport3, res);
1023     return hr;
1024 }
1025
1026 /*****************************************************************************
1027  * IDirect3DDevice::Pick
1028  *
1029  * Executes an execute buffer without performing rendering. Instead, a
1030  * list of primitives that intersect with (x1,y1) of the passed rectangle
1031  * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
1032  * this list.
1033  *
1034  * Version 1 only
1035  *
1036  * Params:
1037  *  ExecuteBuffer: Buffer to execute
1038  *  Viewport: Viewport to use for execution
1039  *  Flags: None are defined, according to the SDK
1040  *  Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
1041  *        x2 and y2 are ignored.
1042  *
1043  * Returns:
1044  *  D3D_OK because it's a stub
1045  *
1046  *****************************************************************************/
1047 static HRESULT WINAPI
1048 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
1049                            IDirect3DExecuteBuffer *ExecuteBuffer,
1050                            IDirect3DViewport *Viewport,
1051                            DWORD Flags,
1052                            D3DRECT *Rect)
1053 {
1054     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1055     IDirect3DExecuteBufferImpl *execbuf = ICOM_OBJECT(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, ExecuteBuffer);
1056     IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Viewport);
1057     FIXME("(%p)->(%p,%p,%08x,%p): stub!\n", This, execbuf, vp, Flags, Rect);
1058
1059     return D3D_OK;
1060 }
1061
1062 /*****************************************************************************
1063  * IDirect3DDevice::GetPickRecords
1064  *
1065  * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1066  *
1067  * Version 1 only
1068  *
1069  * Params:
1070  *  Count: Pointer to a DWORD containing the numbers of pick records to
1071  *         retrieve
1072  *  D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1073  *
1074  * Returns:
1075  *  D3D_OK, because it's a stub
1076  *
1077  *****************************************************************************/
1078 static HRESULT WINAPI
1079 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1080                                      DWORD *Count,
1081                                      D3DPICKRECORD *D3DPickRec)
1082 {
1083     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1084     FIXME("(%p)->(%p,%p): stub!\n", This, Count, D3DPickRec);
1085
1086     return D3D_OK;
1087 }
1088
1089 /*****************************************************************************
1090  * IDirect3DDevice7::EnumTextureformats
1091  *
1092  * Enumerates the supported texture formats. It has a list of all possible
1093  * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1094  * WineD3D supports it. If so, then it is passed to the app.
1095  *
1096  * This is for Version 7 and 3, older versions have a different
1097  * callback function and their own implementation
1098  *
1099  * Params:
1100  *  Callback: Callback to call for each enumerated format
1101  *  Arg: Argument to pass to the callback
1102  *
1103  * Returns:
1104  *  D3D_OK on success
1105  *  DDERR_INVALIDPARAMS if Callback == NULL
1106  *
1107  *****************************************************************************/
1108 static HRESULT WINAPI
1109 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1110                                          LPD3DENUMPIXELFORMATSCALLBACK Callback,
1111                                          void *Arg)
1112 {
1113     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1114     HRESULT hr;
1115     int i;
1116
1117     WINED3DFORMAT FormatList[] = {
1118         /* 32 bit */
1119         WINED3DFMT_A8R8G8B8,
1120         WINED3DFMT_X8R8G8B8,
1121         /* 24 bit */
1122         WINED3DFMT_R8G8B8,
1123         /* 16 Bit */
1124         WINED3DFMT_A1R5G5B5,
1125         WINED3DFMT_A4R4G4B4,
1126         WINED3DFMT_R5G6B5,
1127         WINED3DFMT_X1R5G5B5,
1128         /* 8 Bit */
1129         WINED3DFMT_R3G3B2,
1130         WINED3DFMT_P8,
1131         /* FOURCC codes */
1132         WINED3DFMT_DXT1,
1133         WINED3DFMT_DXT3,
1134         WINED3DFMT_DXT5,
1135     };
1136
1137     WINED3DFORMAT BumpFormatList[] = {
1138         WINED3DFMT_V8U8,
1139         WINED3DFMT_L6V5U5,
1140         WINED3DFMT_X8L8V8U8,
1141         WINED3DFMT_Q8W8V8U8,
1142         WINED3DFMT_V16U16,
1143         WINED3DFMT_W11V11U10,
1144         WINED3DFMT_A2W10V10U10
1145     };
1146
1147     TRACE("(%p)->(%p,%p): Relay\n", This, Callback, Arg);
1148
1149     if(!Callback)
1150         return DDERR_INVALIDPARAMS;
1151
1152     EnterCriticalSection(&ddraw_cs);
1153     for(i = 0; i < sizeof(FormatList) / sizeof(WINED3DFORMAT); i++)
1154     {
1155         hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1156                                         0 /* Adapter */,
1157                                         0 /* DeviceType */,
1158                                         0 /* AdapterFormat */,
1159                                         0 /* Usage */,
1160                                         0 /* ResourceType */,
1161                                         FormatList[i]);
1162         if(hr == D3D_OK)
1163         {
1164             DDPIXELFORMAT pformat;
1165
1166             memset(&pformat, 0, sizeof(pformat));
1167             pformat.dwSize = sizeof(pformat);
1168             PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1169
1170             TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1171             hr = Callback(&pformat, Arg);
1172             if(hr != DDENUMRET_OK)
1173             {
1174                 TRACE("Format enumeration cancelled by application\n");
1175                 LeaveCriticalSection(&ddraw_cs);
1176                 return D3D_OK;
1177             }
1178         }
1179     }
1180
1181     for(i = 0; i < sizeof(BumpFormatList) / sizeof(WINED3DFORMAT); i++)
1182     {
1183         hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1184                                         0 /* Adapter */,
1185                                         0 /* DeviceType */,
1186                                         0 /* AdapterFormat */,
1187                                         WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1188                                         0 /* ResourceType */,
1189                                         BumpFormatList[i]);
1190         if(hr == D3D_OK)
1191         {
1192             DDPIXELFORMAT pformat;
1193
1194             memset(&pformat, 0, sizeof(pformat));
1195             pformat.dwSize = sizeof(pformat);
1196             PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1197
1198             TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1199             hr = Callback(&pformat, Arg);
1200             if(hr != DDENUMRET_OK)
1201             {
1202                 TRACE("Format enumeration cancelled by application\n");
1203                 LeaveCriticalSection(&ddraw_cs);
1204                 return D3D_OK;
1205             }
1206         }
1207     }
1208     TRACE("End of enumeration\n");
1209     LeaveCriticalSection(&ddraw_cs);
1210     return D3D_OK;
1211 }
1212
1213 static HRESULT WINAPI
1214 Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1215                                                LPD3DENUMPIXELFORMATSCALLBACK Callback,
1216                                                void *Arg)
1217 {
1218     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1219     TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice7 interface.\n", This, Callback, Arg);
1220     return IDirect3DDevice7_EnumTextureFormats(ICOM_INTERFACE(This, IDirect3DDevice7),
1221                                                Callback,
1222                                                Arg);
1223 }
1224
1225 /*****************************************************************************
1226  * IDirect3DDevice2::EnumTextureformats
1227  *
1228  * EnumTextureFormats for Version 1 and 2, see
1229  * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1230  *
1231  * This version has a different callback and does not enumerate FourCC
1232  * formats
1233  *
1234  *****************************************************************************/
1235 static HRESULT WINAPI
1236 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1237                                          LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1238                                          void *Arg)
1239 {
1240     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1241     HRESULT hr;
1242     int i;
1243
1244     WINED3DFORMAT FormatList[] = {
1245         /* 32 bit */
1246         WINED3DFMT_A8R8G8B8,
1247         WINED3DFMT_X8R8G8B8,
1248         /* 24 bit */
1249         WINED3DFMT_R8G8B8,
1250         /* 16 Bit */
1251         WINED3DFMT_A1R5G5B5,
1252         WINED3DFMT_A4R4G4B4,
1253         WINED3DFMT_R5G6B5,
1254         WINED3DFMT_X1R5G5B5,
1255         /* 8 Bit */
1256         WINED3DFMT_R3G3B2,
1257         WINED3DFMT_P8,
1258         /* FOURCC codes - Not in this version*/
1259     };
1260
1261     TRACE("(%p)->(%p,%p): Relay\n", This, Callback, Arg);
1262
1263     if(!Callback)
1264         return DDERR_INVALIDPARAMS;
1265
1266     EnterCriticalSection(&ddraw_cs);
1267     for(i = 0; i < sizeof(FormatList) / sizeof(WINED3DFORMAT); i++)
1268     {
1269         hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1270                                         0 /* Adapter */,
1271                                         0 /* DeviceType */,
1272                                         0 /* AdapterFormat */,
1273                                         0 /* Usage */,
1274                                         0 /* ResourceType */,
1275                                         FormatList[i]);
1276         if(hr == D3D_OK)
1277         {
1278             DDSURFACEDESC sdesc;
1279
1280             memset(&sdesc, 0, sizeof(sdesc));
1281             sdesc.dwSize = sizeof(sdesc);
1282             sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1283             sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1284             sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1285             PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1286
1287             TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1288             hr = Callback(&sdesc, Arg);
1289             if(hr != DDENUMRET_OK)
1290             {
1291                 TRACE("Format enumeration cancelled by application\n");
1292                 LeaveCriticalSection(&ddraw_cs);
1293                 return D3D_OK;
1294             }
1295         }
1296     }
1297     TRACE("End of enumeration\n");
1298     LeaveCriticalSection(&ddraw_cs);
1299     return D3D_OK;
1300 }
1301
1302 static HRESULT WINAPI
1303 Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1304                                                LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1305                                                void *Arg)
1306 {
1307     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1308     TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice2 interface.\n", This, Callback, Arg);
1309     return IDirect3DDevice2_EnumTextureFormats(ICOM_INTERFACE(This, IDirect3DDevice2),
1310                                                Callback,
1311                                                Arg);
1312 }
1313
1314 /*****************************************************************************
1315  * IDirect3DDevice::CreateMatrix
1316  *
1317  * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1318  * allocated for the handle.
1319  *
1320  * Version 1 only
1321  *
1322  * Params
1323  *  D3DMatHandle: Address to return the handle at
1324  *
1325  * Returns:
1326  *  D3D_OK on success
1327  *  DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1328  *
1329  *****************************************************************************/
1330 static HRESULT WINAPI
1331 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1332 {
1333     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1334     D3DMATRIX *Matrix;
1335     TRACE("(%p)->(%p)\n", This, D3DMatHandle);
1336
1337     if(!D3DMatHandle)
1338         return DDERR_INVALIDPARAMS;
1339
1340     Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1341     if(!Matrix)
1342     {
1343         ERR("Out of memory when allocating a D3DMATRIX\n");
1344         return DDERR_OUTOFMEMORY;
1345     }
1346
1347     EnterCriticalSection(&ddraw_cs);
1348     *D3DMatHandle = IDirect3DDeviceImpl_CreateHandle(This);
1349     if(!(*D3DMatHandle))
1350     {
1351         ERR("Failed to create a matrix handle\n");
1352         HeapFree(GetProcessHeap(), 0, Matrix);
1353         LeaveCriticalSection(&ddraw_cs);
1354         return DDERR_OUTOFMEMORY;
1355     }
1356     This->Handles[*D3DMatHandle - 1].ptr = Matrix;
1357     This->Handles[*D3DMatHandle - 1].type = DDrawHandle_Matrix;
1358     TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1359
1360     LeaveCriticalSection(&ddraw_cs);
1361     return D3D_OK;
1362 }
1363
1364 /*****************************************************************************
1365  * IDirect3DDevice::SetMatrix
1366  *
1367  * Sets a matrix for a matrix handle. The matrix is copied into the memory
1368  * allocated for the handle
1369  *
1370  * Version 1 only
1371  *
1372  * Params:
1373  *  D3DMatHandle: Handle to set the matrix to
1374  *  D3DMatrix: Matrix to set
1375  *
1376  * Returns:
1377  *  D3D_OK on success
1378  *  DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1379  *   to set is NULL
1380  *
1381  *****************************************************************************/
1382 static HRESULT WINAPI
1383 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1384                                 D3DMATRIXHANDLE D3DMatHandle,
1385                                 D3DMATRIX *D3DMatrix)
1386 {
1387     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1388     TRACE("(%p)->(%08x,%p)\n", This, D3DMatHandle, D3DMatrix);
1389
1390     if( (!D3DMatHandle) || (!D3DMatrix) )
1391         return DDERR_INVALIDPARAMS;
1392
1393     EnterCriticalSection(&ddraw_cs);
1394     if(D3DMatHandle > This->numHandles)
1395     {
1396         ERR("Handle %d out of range\n", D3DMatHandle);
1397         LeaveCriticalSection(&ddraw_cs);
1398         return DDERR_INVALIDPARAMS;
1399     }
1400     else if(This->Handles[D3DMatHandle - 1].type != DDrawHandle_Matrix)
1401     {
1402         ERR("Handle %d is not a matrix handle\n", D3DMatHandle);
1403         LeaveCriticalSection(&ddraw_cs);
1404         return DDERR_INVALIDPARAMS;
1405     }
1406
1407     if (TRACE_ON(d3d7))
1408         dump_D3DMATRIX(D3DMatrix);
1409
1410     *((D3DMATRIX *) This->Handles[D3DMatHandle - 1].ptr) = *D3DMatrix;
1411
1412     if(This->world == D3DMatHandle)
1413     {
1414         IWineD3DDevice_SetTransform(This->wineD3DDevice,
1415                                     WINED3DTS_WORLDMATRIX(0),
1416                                     (WINED3DMATRIX *) D3DMatrix);
1417     }
1418     if(This->view == D3DMatHandle)
1419     {
1420         IWineD3DDevice_SetTransform(This->wineD3DDevice,
1421                                     WINED3DTS_VIEW,
1422                                     (WINED3DMATRIX *) D3DMatrix);
1423     }
1424     if(This->proj == D3DMatHandle)
1425     {
1426         IWineD3DDevice_SetTransform(This->wineD3DDevice,
1427                                     WINED3DTS_PROJECTION,
1428                                     (WINED3DMATRIX *) D3DMatrix);
1429     }
1430
1431     LeaveCriticalSection(&ddraw_cs);
1432     return D3D_OK;
1433 }
1434
1435 /*****************************************************************************
1436  * IDirect3DDevice::SetMatrix
1437  *
1438  * Returns the content of a D3DMATRIX handle
1439  *
1440  * Version 1 only
1441  *
1442  * Params:
1443  *  D3DMatHandle: Matrix handle to read the content from
1444  *  D3DMatrix: Address to store the content at
1445  *
1446  * Returns:
1447  *  D3D_OK on success
1448  *  DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1449  *
1450  *****************************************************************************/
1451 static HRESULT WINAPI
1452 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1453                                 D3DMATRIXHANDLE D3DMatHandle,
1454                                 D3DMATRIX *D3DMatrix)
1455 {
1456     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1457     TRACE("(%p)->(%08x,%p)\n", This, D3DMatHandle, D3DMatrix);
1458
1459     if(!D3DMatrix)
1460         return DDERR_INVALIDPARAMS;
1461     if(!D3DMatHandle)
1462         return DDERR_INVALIDPARAMS;
1463
1464     EnterCriticalSection(&ddraw_cs);
1465     if(D3DMatHandle > This->numHandles)
1466     {
1467         ERR("Handle %d out of range\n", D3DMatHandle);
1468         LeaveCriticalSection(&ddraw_cs);
1469         return DDERR_INVALIDPARAMS;
1470     }
1471     else if(This->Handles[D3DMatHandle - 1].type != DDrawHandle_Matrix)
1472     {
1473         ERR("Handle %d is not a matrix handle\n", D3DMatHandle);
1474         LeaveCriticalSection(&ddraw_cs);
1475         return DDERR_INVALIDPARAMS;
1476     }
1477
1478     /* The handle is simply a pointer to a D3DMATRIX structure */
1479     *D3DMatrix = *((D3DMATRIX *) This->Handles[D3DMatHandle - 1].ptr);
1480
1481     LeaveCriticalSection(&ddraw_cs);
1482     return D3D_OK;
1483 }
1484
1485 /*****************************************************************************
1486  * IDirect3DDevice::DeleteMatrix
1487  *
1488  * Destroys a Matrix handle. Frees the memory and unsets the handle data
1489  *
1490  * Version 1 only
1491  *
1492  * Params:
1493  *  D3DMatHandle: Handle to destroy
1494  *
1495  * Returns:
1496  *  D3D_OK on success
1497  *  DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1498  *
1499  *****************************************************************************/
1500 static HRESULT WINAPI
1501 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1502                                    D3DMATRIXHANDLE D3DMatHandle)
1503 {
1504     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1505     TRACE("(%p)->(%08x)\n", This, D3DMatHandle);
1506
1507     if(!D3DMatHandle)
1508         return DDERR_INVALIDPARAMS;
1509
1510     EnterCriticalSection(&ddraw_cs);
1511     if(D3DMatHandle > This->numHandles)
1512     {
1513         ERR("Handle %d out of range\n", D3DMatHandle);
1514         LeaveCriticalSection(&ddraw_cs);
1515         return DDERR_INVALIDPARAMS;
1516     }
1517     else if(This->Handles[D3DMatHandle - 1].type != DDrawHandle_Matrix)
1518     {
1519         ERR("Handle %d is not a matrix handle\n", D3DMatHandle);
1520         LeaveCriticalSection(&ddraw_cs);
1521         return DDERR_INVALIDPARAMS;
1522     }
1523
1524     HeapFree(GetProcessHeap(), 0, This->Handles[D3DMatHandle - 1].ptr);
1525     This->Handles[D3DMatHandle - 1].ptr = NULL;
1526     This->Handles[D3DMatHandle - 1].type = DDrawHandle_Unknown;
1527
1528     LeaveCriticalSection(&ddraw_cs);
1529     return D3D_OK;
1530 }
1531
1532 /*****************************************************************************
1533  * IDirect3DDevice7::BeginScene
1534  *
1535  * This method must be called before any rendering is performed.
1536  * IDirect3DDevice::EndScene has to be called after the scene is complete
1537  *
1538  * Version 1, 2, 3 and 7
1539  *
1540  * Returns:
1541  *  D3D_OK on success, for details see IWineD3DDevice::BeginScene
1542  *  D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1543  *  started scene).
1544  *
1545  *****************************************************************************/
1546 static HRESULT WINAPI
1547 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1548 {
1549     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1550     HRESULT hr;
1551     TRACE("(%p): Relay\n", This);
1552
1553     EnterCriticalSection(&ddraw_cs);
1554     hr = IWineD3DDevice_BeginScene(This->wineD3DDevice);
1555     LeaveCriticalSection(&ddraw_cs);
1556     if(hr == WINED3D_OK) return D3D_OK;
1557     else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1558 }
1559
1560 static HRESULT WINAPI
1561 Thunk_IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1562 {
1563     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1564     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1565     return IDirect3DDevice7_BeginScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1566 }
1567
1568 static HRESULT WINAPI
1569 Thunk_IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1570 {
1571     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1572     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1573     return IDirect3DDevice7_BeginScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1574 }
1575
1576 static HRESULT WINAPI
1577 Thunk_IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1578 {
1579     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1580     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1581     return IDirect3DDevice7_BeginScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1582 }
1583
1584 /*****************************************************************************
1585  * IDirect3DDevice7::EndScene
1586  *
1587  * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1588  * This method must be called after rendering is finished.
1589  *
1590  * Version 1, 2, 3 and 7
1591  *
1592  * Returns:
1593  *  D3D_OK on success, for details see IWineD3DDevice::EndScene
1594  *  D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1595  *  that only if the scene was already ended.
1596  *
1597  *****************************************************************************/
1598 static HRESULT WINAPI
1599 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1600 {
1601     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1602     HRESULT hr;
1603     TRACE("(%p): Relay\n", This);
1604
1605     EnterCriticalSection(&ddraw_cs);
1606     hr = IWineD3DDevice_EndScene(This->wineD3DDevice);
1607     LeaveCriticalSection(&ddraw_cs);
1608     if(hr == WINED3D_OK) return D3D_OK;
1609     else return D3DERR_SCENE_NOT_IN_SCENE;
1610 }
1611
1612 static HRESULT WINAPI
1613 Thunk_IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1614 {
1615     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1616     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1617     return IDirect3DDevice7_EndScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1618 }
1619
1620 static HRESULT WINAPI
1621 Thunk_IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1622 {
1623     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1624     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1625     return IDirect3DDevice7_EndScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1626 }
1627
1628 static HRESULT WINAPI
1629 Thunk_IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1630 {
1631     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1632     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1633     return IDirect3DDevice7_EndScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1634 }
1635
1636 /*****************************************************************************
1637  * IDirect3DDevice7::GetDirect3D
1638  *
1639  * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1640  * this device.
1641  *
1642  * Params:
1643  *  Direct3D7: Address to store the interface pointer at
1644  *
1645  * Returns:
1646  *  D3D_OK on success
1647  *  DDERR_INVALIDPARAMS if Direct3D7 == NULL
1648  *
1649  *****************************************************************************/
1650 static HRESULT WINAPI
1651 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1652                                   IDirect3D7 **Direct3D7)
1653 {
1654     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1655     TRACE("(%p)->(%p)\n", This, Direct3D7);
1656
1657     if(!Direct3D7)
1658         return DDERR_INVALIDPARAMS;
1659
1660     *Direct3D7 = ICOM_INTERFACE(This->ddraw, IDirect3D7);
1661     IDirect3D7_AddRef(*Direct3D7);
1662
1663     TRACE(" returning interface %p\n", *Direct3D7);
1664     return D3D_OK;
1665 }
1666
1667 static HRESULT WINAPI
1668 Thunk_IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1669                                         IDirect3D3 **Direct3D3)
1670 {
1671     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1672     HRESULT ret;
1673     IDirect3D7 *ret_ptr;
1674
1675     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Direct3D3);
1676     ret = IDirect3DDevice7_GetDirect3D(ICOM_INTERFACE(This, IDirect3DDevice7),
1677                                        &ret_ptr);
1678     if(ret != D3D_OK)
1679         return ret;
1680     *Direct3D3 = COM_INTERFACE_CAST(IDirectDrawImpl, IDirect3D7, IDirect3D3, ret_ptr);
1681     TRACE(" returning interface %p\n", *Direct3D3);
1682     return D3D_OK;
1683 }
1684
1685 static HRESULT WINAPI
1686 Thunk_IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1687                                         IDirect3D2 **Direct3D2)
1688 {
1689     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1690     HRESULT ret;
1691     IDirect3D7 *ret_ptr;
1692
1693     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Direct3D2);
1694     ret = IDirect3DDevice7_GetDirect3D(ICOM_INTERFACE(This, IDirect3DDevice7),
1695                                        &ret_ptr);
1696     if(ret != D3D_OK)
1697         return ret;
1698     *Direct3D2 = COM_INTERFACE_CAST(IDirectDrawImpl, IDirect3D7, IDirect3D2, ret_ptr);
1699     TRACE(" returning interface %p\n", *Direct3D2);
1700     return D3D_OK;
1701 }
1702
1703 static HRESULT WINAPI
1704 Thunk_IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1705                                         IDirect3D **Direct3D)
1706 {
1707     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1708     HRESULT ret;
1709     IDirect3D7 *ret_ptr;
1710
1711     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Direct3D);
1712     ret = IDirect3DDevice7_GetDirect3D(ICOM_INTERFACE(This, IDirect3DDevice7),
1713                                        &ret_ptr);
1714     if(ret != D3D_OK)
1715         return ret;
1716     *Direct3D = COM_INTERFACE_CAST(IDirectDrawImpl, IDirect3D7, IDirect3D, ret_ptr);
1717     TRACE(" returning interface %p\n", *Direct3D);
1718     return D3D_OK;
1719 }
1720
1721 /*****************************************************************************
1722  * IDirect3DDevice3::SetCurrentViewport
1723  *
1724  * Sets a Direct3DViewport as the current viewport.
1725  * For the thunks note that all viewport interface versions are equal
1726  *
1727  * Params:
1728  *  Direct3DViewport3: The viewport to set
1729  *
1730  * Version 2 and 3
1731  *
1732  * Returns:
1733  *  D3D_OK on success
1734  *  (Is a NULL viewport valid?)
1735  *
1736  *****************************************************************************/
1737 static HRESULT WINAPI
1738 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1739                                          IDirect3DViewport3 *Direct3DViewport3)
1740 {
1741     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1742     IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Direct3DViewport3);
1743     TRACE("(%p)->(%p)\n", This, Direct3DViewport3);
1744
1745     EnterCriticalSection(&ddraw_cs);
1746     /* Do nothing if the specified viewport is the same as the current one */
1747     if (This->current_viewport == vp )
1748     {
1749         LeaveCriticalSection(&ddraw_cs);
1750         return D3D_OK;
1751     }
1752
1753     /* Should check if the viewport was added or not */
1754
1755     /* Release previous viewport and AddRef the new one */
1756     if (This->current_viewport)
1757     {
1758         TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport, ICOM_INTERFACE(This->current_viewport, IDirect3DViewport3));
1759         IDirect3DViewport3_Release( ICOM_INTERFACE(This->current_viewport, IDirect3DViewport3) );
1760     }
1761     IDirect3DViewport3_AddRef(Direct3DViewport3);
1762
1763     /* Set this viewport as the current viewport */
1764     This->current_viewport = vp;
1765
1766     /* Activate this viewport */
1767     This->current_viewport->active_device = This;
1768     This->current_viewport->activate(This->current_viewport, FALSE);
1769
1770     LeaveCriticalSection(&ddraw_cs);
1771     return D3D_OK;
1772 }
1773
1774 static HRESULT WINAPI
1775 Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1776                                                IDirect3DViewport2 *Direct3DViewport2)
1777 {
1778     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1779     IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Direct3DViewport2);
1780     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
1781     return IDirect3DDevice3_SetCurrentViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
1782                                                ICOM_INTERFACE(vp, IDirect3DViewport3));
1783 }
1784
1785 /*****************************************************************************
1786  * IDirect3DDevice3::GetCurrentViewport
1787  *
1788  * Returns the currently active viewport.
1789  *
1790  * Version 2 and 3
1791  *
1792  * Params:
1793  *  Direct3DViewport3: Address to return the interface pointer at
1794  *
1795  * Returns:
1796  *  D3D_OK on success
1797  *  DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1798  *
1799  *****************************************************************************/
1800 static HRESULT WINAPI
1801 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1802                                          IDirect3DViewport3 **Direct3DViewport3)
1803 {
1804     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1805     TRACE("(%p)->(%p)\n", This, Direct3DViewport3);
1806
1807     if(!Direct3DViewport3)
1808         return DDERR_INVALIDPARAMS;
1809
1810     EnterCriticalSection(&ddraw_cs);
1811     *Direct3DViewport3 = ICOM_INTERFACE(This->current_viewport, IDirect3DViewport3);
1812
1813     /* AddRef the returned viewport */
1814     if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1815
1816     TRACE(" returning interface %p\n", *Direct3DViewport3);
1817
1818     LeaveCriticalSection(&ddraw_cs);
1819     return D3D_OK;
1820 }
1821
1822 static HRESULT WINAPI
1823 Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1824                                                IDirect3DViewport2 **Direct3DViewport2)
1825 {
1826     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1827     HRESULT hr;
1828     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, Direct3DViewport2);
1829     hr = IDirect3DDevice3_GetCurrentViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
1830                                             (IDirect3DViewport3 **) Direct3DViewport2);
1831     if(hr != D3D_OK) return hr;
1832     *Direct3DViewport2 = (IDirect3DViewport2 *) COM_INTERFACE_CAST(IDirect3DViewportImpl, IDirect3DViewport3, IDirect3DViewport3, *Direct3DViewport2);
1833     return D3D_OK;
1834 }
1835
1836 /*****************************************************************************
1837  * IDirect3DDevice7::SetRenderTarget
1838  *
1839  * Sets the render target for the Direct3DDevice.
1840  * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1841  * IDirectDrawSurface3 == IDirectDrawSurface
1842  *
1843  * Version 2, 3 and 7
1844  *
1845  * Params:
1846  *  NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1847  *             render target
1848  *  Flags: Some flags
1849  *
1850  * Returns:
1851  *  D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1852  *
1853  *****************************************************************************/
1854 static HRESULT WINAPI
1855 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1856                                       IDirectDrawSurface7 *NewTarget,
1857                                       DWORD Flags)
1858 {
1859     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1860     IDirectDrawSurfaceImpl *Target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, NewTarget);
1861     HRESULT hr;
1862     TRACE("(%p)->(%p,%08x): Relay\n", This, NewTarget, Flags);
1863
1864     EnterCriticalSection(&ddraw_cs);
1865     /* Flags: Not used */
1866
1867     if(This->target == Target)
1868     {
1869         TRACE("No-op SetRenderTarget operation, not doing anything\n");
1870         LeaveCriticalSection(&ddraw_cs);
1871         return D3D_OK;
1872     }
1873
1874     hr = IWineD3DDevice_SetRenderTarget(This->wineD3DDevice,
1875                                         0,
1876                                         Target ? Target->WineD3DSurface : NULL);
1877     if(hr != D3D_OK)
1878     {
1879         LeaveCriticalSection(&ddraw_cs);
1880         return hr;
1881     }
1882     IDirectDrawSurface7_AddRef(NewTarget);
1883     IDirectDrawSurface7_Release(ICOM_INTERFACE(This->target, IDirectDrawSurface7));
1884     This->target = Target;
1885     IDirect3DDeviceImpl_UpdateDepthStencil(This);
1886     LeaveCriticalSection(&ddraw_cs);
1887     return D3D_OK;
1888 }
1889
1890 static HRESULT WINAPI
1891 Thunk_IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
1892                                             IDirectDrawSurface4 *NewRenderTarget,
1893                                             DWORD Flags)
1894 {
1895     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1896     IDirectDrawSurfaceImpl *Target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, NewRenderTarget);
1897     TRACE_(ddraw_thunk)("(%p)->(%p,%08x) thunking to IDirect3DDevice7 interface.\n", This, Target, Flags);
1898     return IDirect3DDevice7_SetRenderTarget(ICOM_INTERFACE(This, IDirect3DDevice7),
1899                                             ICOM_INTERFACE(Target, IDirectDrawSurface7),
1900                                             Flags);
1901 }
1902
1903 static HRESULT WINAPI
1904 Thunk_IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
1905                                             IDirectDrawSurface *NewRenderTarget,
1906                                             DWORD Flags)
1907 {
1908     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1909     IDirectDrawSurfaceImpl *Target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface3, NewRenderTarget);
1910     TRACE_(ddraw_thunk)("(%p)->(%p,%08x) thunking to IDirect3DDevice7 interface.\n", This, Target, Flags);
1911     return IDirect3DDevice7_SetRenderTarget(ICOM_INTERFACE(This, IDirect3DDevice7),
1912                                             ICOM_INTERFACE(Target, IDirectDrawSurface7),
1913                                             Flags);
1914 }
1915
1916 /*****************************************************************************
1917  * IDirect3DDevice7::GetRenderTarget
1918  *
1919  * Returns the current render target.
1920  * This is handled locally, because the WineD3D render target's parent
1921  * is an IParent
1922  *
1923  * Version 2, 3 and 7
1924  *
1925  * Params:
1926  *  RenderTarget: Address to store the surface interface pointer
1927  *
1928  * Returns:
1929  *  D3D_OK on success
1930  *  DDERR_INVALIDPARAMS if RenderTarget == NULL
1931  *
1932  *****************************************************************************/
1933 static HRESULT WINAPI
1934 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
1935                                       IDirectDrawSurface7 **RenderTarget)
1936 {
1937     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1938     TRACE("(%p)->(%p): Relay\n", This, RenderTarget);
1939
1940     if(!RenderTarget)
1941         return DDERR_INVALIDPARAMS;
1942
1943     EnterCriticalSection(&ddraw_cs);
1944     *RenderTarget = ICOM_INTERFACE(This->target, IDirectDrawSurface7);
1945     IDirectDrawSurface7_AddRef(*RenderTarget);
1946
1947     LeaveCriticalSection(&ddraw_cs);
1948     return D3D_OK;
1949 }
1950
1951 static HRESULT WINAPI
1952 Thunk_IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
1953                                             IDirectDrawSurface4 **RenderTarget)
1954 {
1955     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1956     HRESULT hr;
1957     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, RenderTarget);
1958     hr = IDirect3DDevice7_GetRenderTarget(ICOM_INTERFACE(This, IDirect3DDevice7),
1959                                           (IDirectDrawSurface7 **) RenderTarget);
1960     if(hr != D3D_OK) return hr;
1961     *RenderTarget = (IDirectDrawSurface4 *) COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirectDrawSurface7, IDirectDrawSurface7, *RenderTarget);
1962     return D3D_OK;
1963 }
1964
1965 static HRESULT WINAPI
1966 Thunk_IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
1967                                             IDirectDrawSurface **RenderTarget)
1968 {
1969     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1970     HRESULT hr;
1971     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, RenderTarget);
1972     hr = IDirect3DDevice7_GetRenderTarget(ICOM_INTERFACE(This, IDirect3DDevice7),
1973                                           (IDirectDrawSurface7 **) RenderTarget);
1974     if(hr != D3D_OK) return hr;
1975     *RenderTarget = (IDirectDrawSurface *) COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirectDrawSurface7, IDirectDrawSurface3, *RenderTarget);
1976     return D3D_OK;
1977 }
1978
1979 /*****************************************************************************
1980  * IDirect3DDevice3::Begin
1981  *
1982  * Begins a description block of vertices. This is similar to glBegin()
1983  * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
1984  * described with IDirect3DDevice::Vertex are drawn.
1985  *
1986  * Version 2 and 3
1987  *
1988  * Params:
1989  *  PrimitiveType: The type of primitives to draw
1990  *  VertexTypeDesc: A flexible vertex format description of the vertices
1991  *  Flags: Some flags..
1992  *
1993  * Returns:
1994  *  D3D_OK on success
1995  *
1996  *****************************************************************************/
1997 static HRESULT WINAPI
1998 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
1999                             D3DPRIMITIVETYPE PrimitiveType,
2000                             DWORD VertexTypeDesc,
2001                             DWORD Flags)
2002 {
2003     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2004     TRACE("(%p)->(%d,%d,%08x)\n", This, PrimitiveType, VertexTypeDesc, Flags);
2005
2006     EnterCriticalSection(&ddraw_cs);
2007     This->primitive_type = PrimitiveType;
2008     This->vertex_type = VertexTypeDesc;
2009     This->render_flags = Flags;
2010     This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2011     This->nb_vertices = 0;
2012     LeaveCriticalSection(&ddraw_cs);
2013
2014     return D3D_OK;
2015 }
2016
2017 static HRESULT WINAPI
2018 Thunk_IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface,
2019                                   D3DPRIMITIVETYPE d3dpt,
2020                                   D3DVERTEXTYPE dwVertexTypeDesc,
2021                                   DWORD dwFlags)
2022 {
2023     DWORD FVF;
2024     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2025     TRACE_(ddraw_thunk)("(%p/%p)->(%08x,%08x,%08x): Thunking to IDirect3DDevice3\n", This, iface, d3dpt, dwVertexTypeDesc, dwFlags);
2026
2027     switch(dwVertexTypeDesc)
2028     {
2029         case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2030         case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2031         case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2032         default:
2033             ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2034             return DDERR_INVALIDPARAMS;  /* Should never happen */
2035     };
2036
2037     return IDirect3DDevice3_Begin(ICOM_INTERFACE(This, IDirect3DDevice3),
2038                                   d3dpt,
2039                                   FVF,
2040                                   dwFlags);
2041 }
2042
2043 /*****************************************************************************
2044  * IDirect3DDevice3::BeginIndexed
2045  *
2046  * Draws primitives based on vertices in a vertex array which are specified
2047  * by indices.
2048  *
2049  * Version 2 and 3
2050  *
2051  * Params:
2052  *  PrimitiveType: Primitive type to draw
2053  *  VertexType: A FVF description of the vertex format
2054  *  Vertices: pointer to an array containing the vertices
2055  *  NumVertices: The number of vertices in the vertex array
2056  *  Flags: Some flags ...
2057  *
2058  * Returns:
2059  *  D3D_OK, because it's a stub
2060  *
2061  *****************************************************************************/
2062 static HRESULT WINAPI
2063 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2064                                    D3DPRIMITIVETYPE PrimitiveType,
2065                                    DWORD VertexType,
2066                                    void *Vertices,
2067                                    DWORD NumVertices,
2068                                    DWORD Flags)
2069 {
2070     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2071     FIXME("(%p)->(%08x,%08x,%p,%08x,%08x): stub!\n", This, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2072     return D3D_OK;
2073 }
2074
2075
2076 static HRESULT WINAPI
2077 Thunk_IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2078                                          D3DPRIMITIVETYPE d3dptPrimitiveType,
2079                                          D3DVERTEXTYPE d3dvtVertexType,
2080                                          void *lpvVertices,
2081                                          DWORD dwNumVertices,
2082                                          DWORD dwFlags)
2083 {
2084     DWORD FVF;
2085     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2086     TRACE_(ddraw_thunk)("(%p/%p)->(%08x,%08x,%p,%08x,%08x): Thunking to IDirect3DDevice3\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2087
2088     switch(d3dvtVertexType)
2089     {
2090         case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2091         case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2092         case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2093         default:
2094             ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2095             return DDERR_INVALIDPARAMS;  /* Should never happen */
2096     };
2097
2098     return IDirect3DDevice3_BeginIndexed(ICOM_INTERFACE(This,IDirect3DDevice3),
2099                                          d3dptPrimitiveType,
2100                                          FVF,
2101                                          lpvVertices,
2102                                          dwNumVertices,
2103                                          dwFlags);
2104 }
2105
2106 /*****************************************************************************
2107  * IDirect3DDevice3::Vertex
2108  *
2109  * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2110  * drawn vertices in a vertex buffer. If the buffer is too small, its
2111  * size is increased.
2112  *
2113  * Version 2 and 3
2114  *
2115  * Params:
2116  *  Vertex: Pointer to the vertex
2117  *
2118  * Returns:
2119  *  D3D_OK, on success
2120  *  DDERR_INVALIDPARAMS if Vertex is NULL
2121  *
2122  *****************************************************************************/
2123 static HRESULT WINAPI
2124 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2125                              void *Vertex)
2126 {
2127     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2128     TRACE("(%p)->(%p)\n", This, Vertex);
2129
2130     if(!Vertex)
2131         return DDERR_INVALIDPARAMS;
2132
2133     EnterCriticalSection(&ddraw_cs);
2134     if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2135     {
2136         BYTE *old_buffer;
2137         This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2138         old_buffer = This->vertex_buffer;
2139         This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2140         if (old_buffer)
2141         {
2142             CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2143             HeapFree(GetProcessHeap(), 0, old_buffer);
2144         }
2145     }
2146
2147     CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2148
2149     LeaveCriticalSection(&ddraw_cs);
2150     return D3D_OK;
2151 }
2152
2153 static HRESULT WINAPI
2154 Thunk_IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface,
2155                                    void *lpVertexType)
2156 {
2157     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2158     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, lpVertexType);
2159     return IDirect3DDevice3_Vertex(ICOM_INTERFACE(This, IDirect3DDevice3),
2160                                                   lpVertexType);
2161 }
2162
2163 /*****************************************************************************
2164  * IDirect3DDevice3::Index
2165  *
2166  * Specifies an index to a vertex to be drawn. The vertex array has to
2167  * be specified with BeginIndexed first.
2168  *
2169  * Parameters:
2170  *  VertexIndex: The index of the vertex to draw
2171  *
2172  * Returns:
2173  *  D3D_OK because it's a stub
2174  *
2175  *****************************************************************************/
2176 static HRESULT WINAPI
2177 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2178                             WORD VertexIndex)
2179 {
2180     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2181     FIXME("(%p)->(%04x): stub!\n", This, VertexIndex);
2182     return D3D_OK;
2183 }
2184
2185 static HRESULT WINAPI
2186 Thunk_IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface,
2187                                   WORD wVertexIndex)
2188 {
2189     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2190     TRACE_(ddraw_thunk)("(%p)->(%04x) thunking to IDirect3DDevice3 interface.\n", This, wVertexIndex);
2191     return IDirect3DDevice3_Index(ICOM_INTERFACE(This, IDirect3DDevice3),
2192                                   wVertexIndex);
2193 }
2194
2195 /*****************************************************************************
2196  * IDirect3DDevice3::End
2197  *
2198  * Ends a draw begun with IDirect3DDevice3::Begin or
2199  * IDirect3DDevice::BeginIndexed. The vertices specified with
2200  * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2201  * the IDirect3DDevice7::DrawPrimitive method. So far only
2202  * non-indexed mode is supported
2203  *
2204  * Version 2 and 3
2205  *
2206  * Params:
2207  *  Flags: Some flags, as usual. Don't know which are defined
2208  *
2209  * Returns:
2210  *  The return value of IDirect3DDevice7::DrawPrimitive
2211  *
2212  *****************************************************************************/
2213 static HRESULT WINAPI
2214 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2215                           DWORD Flags)
2216 {
2217     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2218     TRACE("(%p)->(%08x)\n", This, Flags);
2219
2220     return IDirect3DDevice7_DrawPrimitive(ICOM_INTERFACE(This, IDirect3DDevice7),
2221                                           This->primitive_type, This->vertex_type,
2222                                           This->vertex_buffer, This->nb_vertices,
2223                                           This->render_flags);
2224 }
2225
2226 static HRESULT WINAPI
2227 Thunk_IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface,
2228                                 DWORD dwFlags)
2229 {
2230     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2231     TRACE_(ddraw_thunk)("(%p)->(%08x) thunking to IDirect3DDevice3 interface.\n", This, dwFlags);
2232     return IDirect3DDevice3_End(ICOM_INTERFACE(This, IDirect3DDevice3),
2233                                 dwFlags);
2234 }
2235
2236 /*****************************************************************************
2237  * IDirect3DDevice7::GetRenderState
2238  *
2239  * Returns the value of a render state. The possible render states are
2240  * defined in include/d3dtypes.h
2241  *
2242  * Version 2, 3 and 7
2243  *
2244  * Params:
2245  *  RenderStateType: Render state to return the current setting of
2246  *  Value: Address to store the value at
2247  *
2248  * Returns:
2249  *  D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2250  *  DDERR_INVALIDPARAMS if Value == NULL
2251  *
2252  *****************************************************************************/
2253 static HRESULT WINAPI
2254 IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2255                                      D3DRENDERSTATETYPE RenderStateType,
2256                                      DWORD *Value)
2257 {
2258     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2259     HRESULT hr;
2260     TRACE("(%p)->(%08x,%p): Relay\n", This, RenderStateType, Value);
2261
2262     if(!Value)
2263         return DDERR_INVALIDPARAMS;
2264
2265     EnterCriticalSection(&ddraw_cs);
2266     switch(RenderStateType)
2267     {
2268         case D3DRENDERSTATE_TEXTUREHANDLE:
2269         {
2270             /* This state is wrapped to SetTexture in SetRenderState, so
2271              * it has to be wrapped to GetTexture here
2272              */
2273             IWineD3DBaseTexture *tex = NULL;
2274             *Value = 0;
2275
2276             hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2277                                            0,
2278                                            &tex);
2279
2280             if(hr == WINED3D_OK && tex)
2281             {
2282                 IDirectDrawSurface7 *parent = NULL;
2283                 hr = IWineD3DBaseTexture_GetParent(tex,
2284                                                    (IUnknown **) &parent);
2285                 if(parent)
2286                 {
2287                     /* The parent of the texture is the IDirectDrawSurface7 interface
2288                      * of the ddraw surface
2289                      */
2290                     IDirectDrawSurfaceImpl *texImpl = ICOM_OBJECT(IDirectDrawSurfaceImpl,
2291                                                                   IDirectDrawSurface7,
2292                                                                   parent);
2293                     *Value = texImpl->Handle;
2294                     IDirectDrawSurface7_Release(parent);
2295                 }
2296                 IWineD3DBaseTexture_Release(tex);
2297             }
2298             break;
2299         }
2300
2301         case D3DRENDERSTATE_TEXTUREMAG:
2302         {
2303             WINED3DTEXTUREFILTERTYPE tex_mag;
2304
2305             hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2306                                                 0, WINED3DSAMP_MAGFILTER,
2307                                                 &tex_mag);
2308
2309             switch (tex_mag)
2310             {
2311                 case WINED3DTEXF_POINT:
2312                     *Value = D3DFILTER_NEAREST;
2313                     break;
2314                 case WINED3DTEXF_LINEAR:
2315                     *Value = D3DFILTER_LINEAR;
2316                     break;
2317                 default:
2318                     ERR("Unhandled texture mag %d !\n",tex_mag);
2319                     *Value = 0;
2320             }
2321             break;
2322         }
2323
2324         case D3DRENDERSTATE_TEXTUREMIN:
2325         {
2326             WINED3DTEXTUREFILTERTYPE tex_min;
2327
2328             hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2329                                                 0, WINED3DSAMP_MINFILTER,
2330                                                 &tex_min);
2331
2332             switch (tex_min)
2333             {
2334                 case WINED3DTEXF_POINT:
2335                     *Value = D3DFILTER_NEAREST;
2336                     break;
2337                 case WINED3DTEXF_LINEAR:
2338                     *Value = D3DFILTER_LINEAR;
2339                     break;
2340                 default:
2341                     ERR("Unhandled texture mag %d !\n",tex_min);
2342                     *Value = 0;
2343             }
2344             break;
2345         }
2346
2347         case D3DRENDERSTATE_TEXTUREADDRESS:
2348         case D3DRENDERSTATE_TEXTUREADDRESSU:
2349             hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2350                                                 0, WINED3DSAMP_ADDRESSU,
2351                                                 Value);
2352             break;
2353         case D3DRENDERSTATE_TEXTUREADDRESSV:
2354             hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2355                                                 0, WINED3DSAMP_ADDRESSV,
2356                                                 Value);
2357             break;
2358
2359         default:
2360             /* FIXME: Unhandled: D3DRENDERSTATE_STIPPLEPATTERN00 - 31 */
2361             hr = IWineD3DDevice_GetRenderState(This->wineD3DDevice,
2362                                                RenderStateType,
2363                                                Value);
2364     }
2365     LeaveCriticalSection(&ddraw_cs);
2366     return hr;
2367 }
2368
2369 static HRESULT WINAPI
2370 Thunk_IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2371                                            D3DRENDERSTATETYPE dwRenderStateType,
2372                                            DWORD *lpdwRenderState)
2373 {
2374     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2375     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, dwRenderStateType, lpdwRenderState);
2376     return IDirect3DDevice7_GetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
2377                                            dwRenderStateType,
2378                                            lpdwRenderState);
2379 }
2380
2381 static HRESULT WINAPI
2382 IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2383                                            D3DRENDERSTATETYPE dwRenderStateType,
2384                                            DWORD *lpdwRenderState)
2385 {
2386     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2387     TRACE("(%p)->(%08x,%p): Relay\n", This, dwRenderStateType, lpdwRenderState);
2388
2389     /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2390        the mapping to get the value; other states relayed to IDirect3DDevice7::GetRenderState */
2391     switch(dwRenderStateType)
2392     {
2393         case D3DRENDERSTATE_TEXTUREMAPBLEND:
2394         {
2395             DWORD colorop, colorarg1, colorarg2;
2396             DWORD alphaop, alphaarg1, alphaarg2;
2397
2398             EnterCriticalSection(&ddraw_cs);
2399
2400             IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, &colorop);
2401             IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, &colorarg1);
2402             IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, &colorarg2);
2403             IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, &alphaop);
2404             IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2405             IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2406
2407             if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2408                 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2409             {
2410                 *lpdwRenderState = D3DTBLEND_DECAL;
2411             }
2412             else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2413                 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2414             {
2415                 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2416             }
2417             else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2418                 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2419             {
2420                 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2421             }
2422             else
2423             {
2424                 HRESULT hr;
2425                 BOOL tex_alpha = FALSE;
2426                 IWineD3DBaseTexture *tex = NULL;
2427                 WINED3DSURFACE_DESC desc;
2428                 WINED3DFORMAT fmt;
2429                 DDPIXELFORMAT ddfmt;
2430
2431                 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2432                                             0,
2433                                             &tex);
2434
2435                 if(hr == WINED3D_OK && tex)
2436                 {
2437                     memset(&desc, 0, sizeof(desc));
2438                     desc.Format = &fmt;
2439                     hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2440                     if (SUCCEEDED(hr))
2441                     {
2442                         ddfmt.dwSize = sizeof(ddfmt);
2443                         PixelFormat_WineD3DtoDD(&ddfmt, fmt);
2444                         if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2445                     }
2446
2447                     IWineD3DBaseTexture_Release(tex);
2448                 }
2449
2450                 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2451                       alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == (tex_alpha ? WINED3DTA_TEXTURE : WINED3DTA_CURRENT)))
2452                 {
2453                     ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2454                 }
2455
2456                 *lpdwRenderState = D3DTBLEND_MODULATE;
2457             }
2458
2459             LeaveCriticalSection(&ddraw_cs);
2460
2461             return D3D_OK;
2462         }
2463
2464         default:
2465             return IDirect3DDevice7_GetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
2466                                            dwRenderStateType,
2467                                            lpdwRenderState);
2468     }
2469 }
2470
2471 /*****************************************************************************
2472  * IDirect3DDevice7::SetRenderState
2473  *
2474  * Sets a render state. The possible render states are defined in
2475  * include/d3dtypes.h
2476  *
2477  * Version 2, 3 and 7
2478  *
2479  * Params:
2480  *  RenderStateType: State to set
2481  *  Value: Value to assign to that state
2482  *
2483  * Returns:
2484  *  D3D_OK on success,
2485  *  for details see IWineD3DDevice::SetRenderState
2486  *
2487  *****************************************************************************/
2488 static HRESULT WINAPI
2489 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2490                                      D3DRENDERSTATETYPE RenderStateType,
2491                                      DWORD Value)
2492 {
2493     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2494     HRESULT hr;
2495     TRACE("(%p)->(%08x,%d): Relay\n", This, RenderStateType, Value);
2496
2497     EnterCriticalSection(&ddraw_cs);
2498     /* Some render states need special care */
2499     switch(RenderStateType)
2500     {
2501         case D3DRENDERSTATE_TEXTUREHANDLE:
2502         {
2503             if(Value == 0)
2504             {
2505                 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
2506                                                0,
2507                                                NULL);
2508                 break;
2509             }
2510
2511             if(Value > This->numHandles)
2512             {
2513                 FIXME("Specified handle %d out of range\n", Value);
2514                 hr = DDERR_INVALIDPARAMS;
2515                 break;
2516             }
2517             if(This->Handles[Value - 1].type != DDrawHandle_Texture)
2518             {
2519                 FIXME("Handle %d isn't a texture handle\n", Value);
2520                 hr = DDERR_INVALIDPARAMS;
2521                 break;
2522             }
2523             else
2524             {
2525                 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *) This->Handles[Value - 1].ptr;
2526                 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
2527                                                0,
2528                                                surf->wineD3DTexture);
2529                 break;
2530             }
2531         }
2532
2533         case D3DRENDERSTATE_TEXTUREMAG:
2534         {
2535             WINED3DTEXTUREFILTERTYPE tex_mag = WINED3DTEXF_NONE;
2536
2537             switch ((D3DTEXTUREFILTER) Value)
2538             {
2539                 case D3DFILTER_NEAREST:
2540                 case D3DFILTER_LINEARMIPNEAREST:
2541                     tex_mag = WINED3DTEXF_POINT;
2542                     break;
2543                 case D3DFILTER_LINEAR:
2544                 case D3DFILTER_LINEARMIPLINEAR:
2545                     tex_mag = WINED3DTEXF_LINEAR;
2546                     break;
2547                 default:
2548                     ERR("Unhandled texture mag %d !\n",Value);
2549             }
2550
2551             hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2552                                                 0, WINED3DSAMP_MAGFILTER,
2553                                                 tex_mag);
2554             break;
2555         }
2556
2557         case D3DRENDERSTATE_TEXTUREMIN:
2558         {
2559             WINED3DTEXTUREFILTERTYPE tex_min = WINED3DTEXF_NONE;
2560             WINED3DTEXTUREFILTERTYPE tex_mip = WINED3DTEXF_NONE;
2561
2562             switch ((D3DTEXTUREFILTER) Value)
2563             {
2564                 case D3DFILTER_NEAREST:
2565                     tex_min = WINED3DTEXF_POINT;
2566                     break;
2567                 case D3DFILTER_LINEAR:
2568                     tex_min = WINED3DTEXF_LINEAR;
2569                     break;
2570                 case D3DFILTER_MIPNEAREST:
2571                     tex_min = WINED3DTEXF_NONE;
2572                     tex_mip = WINED3DTEXF_POINT;
2573                     break;
2574                 case D3DFILTER_MIPLINEAR:
2575                     tex_min = WINED3DTEXF_NONE;
2576                     tex_mip = WINED3DTEXF_LINEAR;
2577                     break;
2578                 case D3DFILTER_LINEARMIPNEAREST:
2579                     tex_min = WINED3DTEXF_POINT;
2580                     tex_mip = WINED3DTEXF_LINEAR;
2581                     break;
2582                 case D3DFILTER_LINEARMIPLINEAR:
2583                     tex_min = WINED3DTEXF_LINEAR;
2584                     tex_mip = WINED3DTEXF_LINEAR;
2585                     break;
2586
2587                 default:
2588                     ERR("Unhandled texture min %d !\n",Value);
2589             }
2590
2591                    IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2592                                                   0, WINED3DSAMP_MIPFILTER,
2593                                                   tex_mip);
2594             hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2595                                                 0, WINED3DSAMP_MINFILTER,
2596                                                 tex_min);
2597             break;
2598         }
2599
2600         case D3DRENDERSTATE_TEXTUREADDRESS:
2601                    IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2602                                                   0, WINED3DSAMP_ADDRESSV,
2603                                                   Value);
2604             /* Drop through */
2605         case D3DRENDERSTATE_TEXTUREADDRESSU:
2606             hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2607                                                 0, WINED3DSAMP_ADDRESSU,
2608                                                 Value);
2609             break;
2610         case D3DRENDERSTATE_TEXTUREADDRESSV:
2611             hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2612                                                 0, WINED3DSAMP_ADDRESSV,
2613                                                 Value);
2614             break;
2615
2616         default:
2617
2618             /* FIXME: Unhandled: D3DRENDERSTATE_STIPPLEPATTERN00 - 31 */
2619
2620             hr = IWineD3DDevice_SetRenderState(This->wineD3DDevice,
2621                                                RenderStateType,
2622                                                Value);
2623             break;
2624     }
2625     LeaveCriticalSection(&ddraw_cs);
2626     return hr;
2627 }
2628
2629 static HRESULT WINAPI
2630 Thunk_IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2631                                            D3DRENDERSTATETYPE RenderStateType,
2632                                            DWORD Value)
2633 {
2634     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2635     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, RenderStateType, Value);
2636     return IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
2637                                            RenderStateType,
2638                                            Value);
2639 }
2640
2641 static HRESULT WINAPI
2642 IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2643                                            D3DRENDERSTATETYPE RenderStateType,
2644                                            DWORD Value)
2645 {
2646     /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2647     for this state can be directly mapped to texture stage colorop and alphaop, but
2648     D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2649     from diffuse otherwise. So changing the texture is monitored here to modify
2650     alphaarg when needed.
2651
2652     Other states are relayed to IDirect3DDevice7
2653
2654     Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation */
2655
2656     HRESULT hr;
2657     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2658     TRACE("(%p)->(%08x,%d): Relay\n", This, RenderStateType, Value);
2659
2660     switch(RenderStateType)
2661     {
2662         case D3DRENDERSTATE_TEXTUREMAPBLEND:
2663         {
2664             EnterCriticalSection(&ddraw_cs);
2665
2666             switch ( (D3DTEXTUREBLEND) Value)
2667             {
2668                 case D3DTBLEND_MODULATE:
2669                 {
2670                     BOOL tex_alpha = FALSE;
2671                     IWineD3DBaseTexture *tex = NULL;
2672                     WINED3DSURFACE_DESC desc;
2673                     WINED3DFORMAT fmt;
2674                     DDPIXELFORMAT ddfmt;
2675
2676                     hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2677                                                 0,
2678                                                 &tex);
2679
2680                     if(hr == WINED3D_OK && tex)
2681                     {
2682                         memset(&desc, 0, sizeof(desc));
2683                         desc.Format = &fmt;
2684                         hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2685                         if (SUCCEEDED(hr))
2686                         {
2687                             ddfmt.dwSize = sizeof(ddfmt);
2688                             PixelFormat_WineD3DtoDD(&ddfmt, fmt);
2689                             if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2690                         }
2691
2692                         IWineD3DBaseTexture_Release(tex);
2693                     }
2694
2695                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2696                     if (tex_alpha)
2697                     {
2698                         IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2699                     }
2700                     else
2701                     {
2702                         IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_CURRENT);
2703                     }
2704
2705                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2706                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2707                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2708
2709                     break;
2710                 }
2711
2712                 case D3DTBLEND_MODULATEALPHA:
2713                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2714                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2715                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2716                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2717                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2718                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2719                     break;
2720
2721                 case D3DTBLEND_DECAL:
2722                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2723                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2724                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2725                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2726                     break;
2727
2728                 case D3DTBLEND_DECALALPHA:
2729                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2730                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2731                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2732                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2733                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2734                     break;
2735
2736                 default:
2737                     ERR("Unhandled texture environment %d !\n",Value);
2738             }
2739
2740             LeaveCriticalSection(&ddraw_cs);
2741
2742             hr = D3D_OK;
2743             break;
2744         }
2745
2746         case D3DRENDERSTATE_TEXTUREHANDLE:
2747         {
2748             DWORD texmapblend;
2749
2750             IDirect3DDevice2_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
2751
2752             hr = IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
2753                                            D3DRENDERSTATE_TEXTUREHANDLE,
2754                                            Value);
2755
2756             if (texmapblend == D3DTBLEND_MODULATE)
2757             {
2758                 BOOL tex_alpha = FALSE;
2759                 IWineD3DBaseTexture *tex = NULL;
2760                 WINED3DSURFACE_DESC desc;
2761                 WINED3DFORMAT fmt;
2762                 DDPIXELFORMAT ddfmt;
2763
2764                 EnterCriticalSection(&ddraw_cs);
2765
2766                 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2767                                             0,
2768                                             &tex);
2769
2770                 if(hr == WINED3D_OK && tex)
2771                 {
2772                     memset(&desc, 0, sizeof(desc));
2773                     desc.Format = &fmt;
2774                     hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2775                     if (SUCCEEDED(hr))
2776                     {
2777                         ddfmt.dwSize = sizeof(ddfmt);
2778                         PixelFormat_WineD3DtoDD(&ddfmt, fmt);
2779                         if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2780                     }
2781
2782                     IWineD3DBaseTexture_Release(tex);
2783                 }
2784
2785                 /* alphaop is WINED3DTOP_SELECTARG1 if it's D3DTBLEND_MODULATE, so only modify alphaarg1 */
2786                 if (tex_alpha)
2787                 {
2788                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2789                 }
2790                 else
2791                 {
2792                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_CURRENT);
2793                 }
2794
2795                 LeaveCriticalSection(&ddraw_cs);
2796             }
2797
2798             break;
2799         }
2800
2801         default:
2802             hr = IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
2803                                            RenderStateType,
2804                                            Value);
2805             break;
2806     }
2807
2808     return hr;
2809 }
2810
2811 /*****************************************************************************
2812  * Direct3DDevice3::SetLightState
2813  *
2814  * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2815  * light states are forwarded to Direct3DDevice7 render states
2816  *
2817  * Version 2 and 3
2818  *
2819  * Params:
2820  *  LightStateType: The light state to change
2821  *  Value: The value to assign to that light state
2822  *
2823  * Returns:
2824  *  D3D_OK on success
2825  *  DDERR_INVALIDPARAMS if the parameters were incorrect
2826  *  Also check IDirect3DDevice7::SetRenderState
2827  *
2828  *****************************************************************************/
2829 static HRESULT WINAPI
2830 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
2831                                     D3DLIGHTSTATETYPE LightStateType,
2832                                     DWORD Value)
2833 {
2834     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2835     HRESULT hr;
2836
2837     TRACE("(%p)->(%08x,%08x)\n", This, LightStateType, Value);
2838
2839     if (!LightStateType && (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2840     {
2841         TRACE("Unexpected Light State Type\n");
2842         return DDERR_INVALIDPARAMS;
2843     }
2844
2845     EnterCriticalSection(&ddraw_cs);
2846     if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
2847     {
2848         IDirect3DMaterialImpl *mat;
2849
2850         if(Value == 0) mat = NULL;
2851         else if(Value > This->numHandles)
2852         {
2853             ERR("Material handle out of range(%d)\n", Value);
2854             LeaveCriticalSection(&ddraw_cs);
2855             return DDERR_INVALIDPARAMS;
2856         }
2857         else if(This->Handles[Value - 1].type != DDrawHandle_Material)
2858         {
2859             ERR("Invalid handle %d\n", Value);
2860             LeaveCriticalSection(&ddraw_cs);
2861             return DDERR_INVALIDPARAMS;
2862         }
2863         else
2864         {
2865             mat = (IDirect3DMaterialImpl *) This->Handles[Value - 1].ptr;
2866         }
2867
2868         if (mat != NULL)
2869         {
2870             TRACE(" activating material %p.\n", mat);
2871             mat->activate(mat);
2872         }
2873         else
2874         {
2875             FIXME(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
2876         }
2877         This->material = Value;
2878     }
2879     else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
2880     {
2881         switch (Value)
2882         {
2883             case D3DCOLOR_MONO:
2884                 ERR("DDCOLOR_MONO should not happen!\n");
2885                 break;
2886             case D3DCOLOR_RGB:
2887                 /* We are already in this mode */
2888                 TRACE("Setting color model to RGB (no-op).\n");
2889                 break;
2890             default:
2891                 ERR("Unknown color model!\n");
2892                 LeaveCriticalSection(&ddraw_cs);
2893                 return DDERR_INVALIDPARAMS;
2894         }
2895     }
2896     else
2897     {
2898         D3DRENDERSTATETYPE rs;
2899         switch (LightStateType)
2900         {
2901             case D3DLIGHTSTATE_AMBIENT:       /* 2 */
2902                 rs = D3DRENDERSTATE_AMBIENT;
2903                 break;          
2904             case D3DLIGHTSTATE_FOGMODE:       /* 4 */
2905                 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2906                 break;
2907             case D3DLIGHTSTATE_FOGSTART:      /* 5 */
2908                 rs = D3DRENDERSTATE_FOGSTART;
2909                 break;
2910             case D3DLIGHTSTATE_FOGEND:        /* 6 */
2911                 rs = D3DRENDERSTATE_FOGEND;
2912                 break;
2913             case D3DLIGHTSTATE_FOGDENSITY:    /* 7 */
2914                 rs = D3DRENDERSTATE_FOGDENSITY;
2915                 break;
2916             case D3DLIGHTSTATE_COLORVERTEX:   /* 8 */
2917                 rs = D3DRENDERSTATE_COLORVERTEX;
2918                 break;
2919             default:
2920                 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
2921                 LeaveCriticalSection(&ddraw_cs);
2922                 return DDERR_INVALIDPARAMS;
2923         }
2924
2925         hr = IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
2926                                              rs,
2927                                              Value);
2928         LeaveCriticalSection(&ddraw_cs);
2929         return hr;
2930     }
2931
2932     LeaveCriticalSection(&ddraw_cs);
2933     return D3D_OK;
2934 }
2935
2936 static HRESULT WINAPI
2937 Thunk_IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
2938                                           D3DLIGHTSTATETYPE LightStateType,
2939                                           DWORD Value)
2940 {
2941     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2942     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x) thunking to IDirect3DDevice3 interface.\n", This, LightStateType, Value);
2943     return IDirect3DDevice3_SetLightState(ICOM_INTERFACE(This, IDirect3DDevice3),
2944                                           LightStateType,
2945                                           Value);
2946 }
2947
2948 /*****************************************************************************
2949  * IDirect3DDevice3::GetLightState
2950  *
2951  * Returns the current setting of a light state. The state is read from
2952  * the Direct3DDevice7 render state.
2953  *
2954  * Version 2 and 3
2955  *
2956  * Params:
2957  *  LightStateType: The light state to return
2958  *  Value: The address to store the light state setting at
2959  *
2960  * Returns:
2961  *  D3D_OK on success
2962  *  DDDERR_INVALIDPARAMS if the parameters were incorrect
2963  *  Also see IDirect3DDevice7::GetRenderState
2964  *
2965  *****************************************************************************/
2966 static HRESULT WINAPI
2967 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
2968                                     D3DLIGHTSTATETYPE LightStateType,
2969                                     DWORD *Value)
2970 {
2971     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2972     HRESULT hr;
2973
2974     TRACE("(%p)->(%08x,%p)\n", This, LightStateType, Value);
2975
2976     if (!LightStateType && (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2977     {
2978         TRACE("Unexpected Light State Type\n");
2979         return DDERR_INVALIDPARAMS;
2980     }
2981
2982     if(!Value)
2983         return DDERR_INVALIDPARAMS;
2984
2985     EnterCriticalSection(&ddraw_cs);
2986     if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
2987     {
2988         *Value = This->material;
2989     }
2990     else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
2991     {
2992         *Value = D3DCOLOR_RGB;
2993     }
2994     else
2995     {
2996         D3DRENDERSTATETYPE rs;
2997         switch (LightStateType)
2998         {
2999             case D3DLIGHTSTATE_AMBIENT:       /* 2 */
3000                 rs = D3DRENDERSTATE_AMBIENT;
3001                 break;          
3002             case D3DLIGHTSTATE_FOGMODE:       /* 4 */
3003                 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3004                 break;
3005             case D3DLIGHTSTATE_FOGSTART:      /* 5 */
3006                 rs = D3DRENDERSTATE_FOGSTART;
3007                 break;
3008             case D3DLIGHTSTATE_FOGEND:        /* 6 */
3009                 rs = D3DRENDERSTATE_FOGEND;
3010                 break;
3011             case D3DLIGHTSTATE_FOGDENSITY:    /* 7 */
3012                 rs = D3DRENDERSTATE_FOGDENSITY;
3013                 break;
3014             case D3DLIGHTSTATE_COLORVERTEX:   /* 8 */
3015                 rs = D3DRENDERSTATE_COLORVERTEX;
3016                 break;
3017             default:
3018                 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3019                 LeaveCriticalSection(&ddraw_cs);
3020                 return DDERR_INVALIDPARAMS;
3021         }
3022
3023         hr = IDirect3DDevice7_GetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
3024                                              rs,
3025                                              Value);
3026         LeaveCriticalSection(&ddraw_cs);
3027         return hr;
3028     }
3029
3030     LeaveCriticalSection(&ddraw_cs);
3031     return D3D_OK;
3032 }
3033
3034 static HRESULT WINAPI
3035 Thunk_IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3036                                           D3DLIGHTSTATETYPE LightStateType,
3037                                           DWORD *Value)
3038 {
3039     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3040     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice3 interface.\n", This, LightStateType, Value);
3041     return IDirect3DDevice3_GetLightState(ICOM_INTERFACE(This, IDirect3DDevice3),
3042                                           LightStateType,
3043                                           Value);
3044 }
3045
3046 /*****************************************************************************
3047  * IDirect3DDevice7::SetTransform
3048  *
3049  * Assigns a D3DMATRIX to a transform type. The transform types are defined
3050  * in include/d3dtypes.h.
3051  * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3052  * (=255) for wined3d, because the 1 transform state was removed in d3d8
3053  * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3054  *
3055  * Version 2, 3 and 7
3056  *
3057  * Params:
3058  *  TransformStateType: transform state to set
3059  *  Matrix: Matrix to assign to the state
3060  *
3061  * Returns:
3062  *  D3D_OK on success
3063  *  DDERR_INVALIDPARAMS if Matrix == NULL
3064  *  For details see IWineD3DDevice::SetTransform
3065  *
3066  *****************************************************************************/
3067 static HRESULT WINAPI
3068 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3069                                    D3DTRANSFORMSTATETYPE TransformStateType,
3070                                    D3DMATRIX *Matrix)
3071 {
3072     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3073     D3DTRANSFORMSTATETYPE type = TransformStateType;
3074     HRESULT hr;
3075     TRACE("(%p)->(%08x,%p): Relay\n", This, TransformStateType, Matrix);
3076
3077     switch(TransformStateType)
3078     {
3079         case D3DTRANSFORMSTATE_WORLD :  type = WINED3DTS_WORLDMATRIX(0); break;
3080         case D3DTRANSFORMSTATE_WORLD1:  type = WINED3DTS_WORLDMATRIX(1); break;
3081         case D3DTRANSFORMSTATE_WORLD2:  type = WINED3DTS_WORLDMATRIX(2); break;
3082         case D3DTRANSFORMSTATE_WORLD3:  type = WINED3DTS_WORLDMATRIX(3); break;
3083         default:                        type = TransformStateType;
3084     }
3085
3086     if(!Matrix)
3087        return DDERR_INVALIDPARAMS;
3088
3089     /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3090     EnterCriticalSection(&ddraw_cs);
3091     hr = IWineD3DDevice_SetTransform(This->wineD3DDevice,
3092                                      type,
3093                                      (WINED3DMATRIX*) Matrix);
3094     LeaveCriticalSection(&ddraw_cs);
3095     return hr;
3096 }
3097
3098 static HRESULT WINAPI
3099 Thunk_IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3100                                          D3DTRANSFORMSTATETYPE TransformStateType,
3101                                          D3DMATRIX *D3DMatrix)
3102 {
3103     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3104     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3105     return IDirect3DDevice7_SetTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
3106                                          TransformStateType,
3107                                          D3DMatrix);
3108 }
3109
3110 static HRESULT WINAPI
3111 Thunk_IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3112                                          D3DTRANSFORMSTATETYPE TransformStateType,
3113                                          D3DMATRIX *D3DMatrix)
3114 {
3115     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3116     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3117     return IDirect3DDevice7_SetTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
3118                                          TransformStateType,
3119                                          D3DMatrix);
3120 }
3121
3122 /*****************************************************************************
3123  * IDirect3DDevice7::GetTransform
3124  *
3125  * Returns the matrix assigned to a transform state
3126  * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3127  * SetTransform
3128  *
3129  * Params:
3130  *  TransformStateType: State to read the matrix from
3131  *  Matrix: Address to store the matrix at
3132  *
3133  * Returns:
3134  *  D3D_OK on success
3135  *  DDERR_INVALIDPARAMS if Matrix == NULL
3136  *  For details, see IWineD3DDevice::GetTransform
3137  *
3138  *****************************************************************************/
3139 static HRESULT WINAPI
3140 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3141                                    D3DTRANSFORMSTATETYPE TransformStateType,
3142                                    D3DMATRIX *Matrix)
3143 {
3144     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3145     D3DTRANSFORMSTATETYPE type = TransformStateType;
3146     HRESULT hr;
3147     TRACE("(%p)->(%08x,%p): Relay\n", This, TransformStateType, Matrix);
3148
3149     switch(TransformStateType)
3150     {
3151         case D3DTRANSFORMSTATE_WORLD :  type = WINED3DTS_WORLDMATRIX(0); break;
3152         case D3DTRANSFORMSTATE_WORLD1:  type = WINED3DTS_WORLDMATRIX(1); break;
3153         case D3DTRANSFORMSTATE_WORLD2:  type = WINED3DTS_WORLDMATRIX(2); break;
3154         case D3DTRANSFORMSTATE_WORLD3:  type = WINED3DTS_WORLDMATRIX(3); break;
3155         default:                        type = TransformStateType;
3156     }
3157
3158     if(!Matrix)
3159         return DDERR_INVALIDPARAMS;
3160
3161     /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3162     EnterCriticalSection(&ddraw_cs);
3163     hr = IWineD3DDevice_GetTransform(This->wineD3DDevice, type, (WINED3DMATRIX*) Matrix);
3164     LeaveCriticalSection(&ddraw_cs);
3165     return hr;
3166 }
3167
3168 static HRESULT WINAPI
3169 Thunk_IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3170                                          D3DTRANSFORMSTATETYPE TransformStateType,
3171                                          D3DMATRIX *D3DMatrix)
3172 {
3173     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3174     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3175     return IDirect3DDevice7_GetTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
3176                                          TransformStateType,
3177                                          D3DMatrix);
3178 }
3179
3180 static HRESULT WINAPI
3181 Thunk_IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3182                                          D3DTRANSFORMSTATETYPE TransformStateType,
3183                                          D3DMATRIX *D3DMatrix)
3184 {
3185     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3186     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3187     return IDirect3DDevice7_GetTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
3188                                          TransformStateType,
3189                                          D3DMatrix);
3190 }
3191
3192 /*****************************************************************************
3193  * IDirect3DDevice7::MultiplyTransform
3194  *
3195  * Multiplies the already-set transform matrix of a transform state
3196  * with another matrix. For the world matrix, see SetTransform
3197  *
3198  * Version 2, 3 and 7
3199  *
3200  * Params:
3201  *  TransformStateType: Transform state to multiply
3202  *  D3DMatrix Matrix to multiply with.
3203  *
3204  * Returns
3205  *  D3D_OK on success
3206  *  DDERR_INVALIDPARAMS if D3DMatrix is NULL
3207  *  For details, see IWineD3DDevice::MultiplyTransform
3208  *
3209  *****************************************************************************/
3210 static HRESULT WINAPI
3211 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3212                                         D3DTRANSFORMSTATETYPE TransformStateType,
3213                                         D3DMATRIX *D3DMatrix)
3214 {
3215     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3216     HRESULT hr;
3217     D3DTRANSFORMSTATETYPE type;
3218     TRACE("(%p)->(%08x,%p): Relay\n", This, TransformStateType, D3DMatrix);
3219
3220     switch(TransformStateType)
3221     {
3222         case D3DTRANSFORMSTATE_WORLD :  type = WINED3DTS_WORLDMATRIX(0); break;
3223         case D3DTRANSFORMSTATE_WORLD1:  type = WINED3DTS_WORLDMATRIX(1); break;
3224         case D3DTRANSFORMSTATE_WORLD2:  type = WINED3DTS_WORLDMATRIX(2); break;
3225         case D3DTRANSFORMSTATE_WORLD3:  type = WINED3DTS_WORLDMATRIX(3); break;
3226         default:                        type = TransformStateType;
3227     }
3228
3229     /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3230     EnterCriticalSection(&ddraw_cs);
3231     hr = IWineD3DDevice_MultiplyTransform(This->wineD3DDevice,
3232                                           type,
3233                                           (WINED3DMATRIX*) D3DMatrix);
3234     LeaveCriticalSection(&ddraw_cs);
3235     return hr;
3236 }
3237
3238 static HRESULT WINAPI
3239 Thunk_IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3240                                               D3DTRANSFORMSTATETYPE TransformStateType,
3241                                               D3DMATRIX *D3DMatrix)
3242 {
3243     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3244     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3245     return IDirect3DDevice7_MultiplyTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
3246                                               TransformStateType,
3247                                               D3DMatrix);
3248 }
3249
3250 static HRESULT WINAPI
3251 Thunk_IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3252                                               D3DTRANSFORMSTATETYPE TransformStateType,
3253                                               D3DMATRIX *D3DMatrix)
3254 {
3255     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3256     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3257     return IDirect3DDevice7_MultiplyTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
3258                                               TransformStateType,
3259                                               D3DMatrix);
3260 }
3261
3262 /*****************************************************************************
3263  * IDirect3DDevice7::DrawPrimitive
3264  *
3265  * Draws primitives based on vertices in an application-provided pointer
3266  *
3267  * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3268  * an FVF format for D3D7
3269  *
3270  * Params:
3271  *  PrimitiveType: The type of the primitives to draw
3272  *  Vertex type: Flexible vertex format vertex description
3273  *  Vertices: Pointer to the vertex array
3274  *  VertexCount: The number of vertices to draw
3275  *  Flags: As usual a few flags
3276  *
3277  * Returns:
3278  *  D3D_OK on success
3279  *  DDERR_INVALIDPARAMS if Vertices is NULL
3280  *  For details, see IWineD3DDevice::DrawPrimitiveUP
3281  *
3282  *****************************************************************************/
3283 static HRESULT WINAPI
3284 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3285                                     D3DPRIMITIVETYPE PrimitiveType,
3286                                     DWORD VertexType,
3287                                     void *Vertices,
3288                                     DWORD VertexCount,
3289                                     DWORD Flags)
3290 {
3291     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3292     UINT PrimitiveCount, stride;
3293     HRESULT hr;
3294     TRACE("(%p)->(%08x,%08x,%p,%08x,%08x): Relay!\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3295
3296     if(!Vertices)
3297         return DDERR_INVALIDPARAMS;
3298
3299     /* Get the vertex count */
3300     switch(PrimitiveType)
3301     {
3302       case D3DPT_POINTLIST: 
3303         PrimitiveCount = VertexCount;
3304         break;
3305
3306       case D3DPT_LINELIST: 
3307         PrimitiveCount = VertexCount / 2;
3308         break;
3309
3310       case D3DPT_LINESTRIP:
3311         PrimitiveCount = VertexCount - 1;
3312         break;
3313
3314       case D3DPT_TRIANGLELIST:
3315         PrimitiveCount = VertexCount / 3;
3316         break;
3317
3318       case D3DPT_TRIANGLESTRIP:
3319         PrimitiveCount = VertexCount - 2;
3320         break;
3321
3322       case D3DPT_TRIANGLEFAN:
3323         PrimitiveCount = VertexCount - 2;
3324         break;
3325
3326       default:
3327         return DDERR_INVALIDPARAMS;
3328     }
3329
3330     /* Get the stride */
3331     stride = get_flexible_vertex_size(VertexType);
3332
3333     /* Set the FVF */
3334     EnterCriticalSection(&ddraw_cs);
3335     hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
3336                                              IDirectDrawImpl_FindDecl(This->ddraw, VertexType));
3337     if(hr != D3D_OK)
3338     {
3339         LeaveCriticalSection(&ddraw_cs);
3340         return hr;
3341     }
3342
3343     /* This method translates to the user pointer draw of WineD3D */
3344     hr = IWineD3DDevice_DrawPrimitiveUP(This->wineD3DDevice,
3345                                         PrimitiveType,
3346                                         PrimitiveCount,
3347                                         Vertices,
3348                                         stride);
3349     LeaveCriticalSection(&ddraw_cs);
3350     return hr;
3351 }
3352
3353 static HRESULT WINAPI
3354 Thunk_IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3355                                           D3DPRIMITIVETYPE PrimitiveType,
3356                                           DWORD VertexType,
3357                                           void *Vertices,
3358                                           DWORD VertexCount,
3359                                           DWORD Flags)
3360 {
3361     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3362     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3363     return IDirect3DDevice7_DrawPrimitive(ICOM_INTERFACE(This, IDirect3DDevice7),
3364                                           PrimitiveType,
3365                                           VertexType,
3366                                           Vertices,
3367                                           VertexCount,
3368                                           Flags);
3369 }
3370
3371 static HRESULT WINAPI
3372 Thunk_IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3373                                           D3DPRIMITIVETYPE PrimitiveType,
3374                                           D3DVERTEXTYPE VertexType,
3375                                           void *Vertices,
3376                                           DWORD VertexCount,
3377                                           DWORD Flags)
3378 {
3379     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3380     DWORD FVF;
3381     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3382
3383     switch(VertexType)
3384     {
3385         case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3386         case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3387         case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3388         default:
3389             ERR("Unexpected vertex type %d\n", VertexType);
3390             return DDERR_INVALIDPARAMS;  /* Should never happen */
3391     }
3392
3393     return IDirect3DDevice7_DrawPrimitive(ICOM_INTERFACE(This, IDirect3DDevice7),
3394                                           PrimitiveType,
3395                                           FVF,
3396                                           Vertices,
3397                                           VertexCount,
3398                                           Flags);
3399 }
3400
3401 /*****************************************************************************
3402  * IDirect3DDevice7::DrawIndexedPrimitive
3403  *
3404  * Draws vertices from an application-provided pointer, based on the index
3405  * numbers in a WORD array.
3406  *
3407  * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3408  * an FVF format for D3D7
3409  *
3410  * Params:
3411  *  PrimitiveType: The primitive type to draw
3412  *  VertexType: The FVF vertex description
3413  *  Vertices: Pointer to the vertex array
3414  *  VertexCount: ?
3415  *  Indices: Pointer to the index array
3416  *  IndexCount: Number of indices = Number of vertices to draw
3417  *  Flags: As usual, some flags
3418  *
3419  * Returns:
3420  *  D3D_OK on success
3421  *  DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3422  *  For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3423  *
3424  *****************************************************************************/
3425 static HRESULT WINAPI
3426 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3427                                            D3DPRIMITIVETYPE PrimitiveType,
3428                                            DWORD VertexType,
3429                                            void *Vertices,
3430                                            DWORD VertexCount,
3431                                            WORD *Indices,
3432                                            DWORD IndexCount,
3433                                            DWORD Flags)
3434 {
3435     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3436     UINT PrimitiveCount = 0;
3437     HRESULT hr;
3438     TRACE("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x): Relay!\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3439
3440     /* Get the primitive number */
3441     switch(PrimitiveType)
3442     {
3443       case D3DPT_POINTLIST: 
3444         PrimitiveCount = IndexCount;
3445         break;
3446
3447       case D3DPT_LINELIST: 
3448         PrimitiveCount = IndexCount / 2;
3449         break;
3450
3451       case D3DPT_LINESTRIP:
3452         PrimitiveCount = IndexCount - 1;
3453         break;
3454
3455       case D3DPT_TRIANGLELIST:
3456         PrimitiveCount = IndexCount / 3;
3457         break;
3458
3459       case D3DPT_TRIANGLESTRIP:
3460         PrimitiveCount = IndexCount - 2;
3461         break;
3462
3463       case D3DPT_TRIANGLEFAN:
3464         PrimitiveCount = IndexCount - 2;
3465         break;
3466
3467       default:
3468         return DDERR_INVALIDPARAMS;
3469     }
3470
3471     /* Set the D3DDevice's FVF */
3472     EnterCriticalSection(&ddraw_cs);
3473     hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
3474                                              IDirectDrawImpl_FindDecl(This->ddraw, VertexType));
3475     if(FAILED(hr))
3476     {
3477         ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3478         LeaveCriticalSection(&ddraw_cs);
3479         return hr;
3480     }
3481
3482     hr = IWineD3DDevice_DrawIndexedPrimitiveUP(This->wineD3DDevice,
3483                                                PrimitiveType,
3484                                                0 /* MinVertexIndex */,
3485                                                VertexCount /* UINT NumVertexIndex */,
3486                                                PrimitiveCount,
3487                                                Indices,
3488                                                WINED3DFMT_INDEX16,
3489                                                Vertices,
3490                                                get_flexible_vertex_size(VertexType));
3491     LeaveCriticalSection(&ddraw_cs);
3492     return hr;
3493 }
3494
3495 static HRESULT WINAPI
3496 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3497                                                  D3DPRIMITIVETYPE PrimitiveType,
3498                                                  DWORD VertexType,
3499                                                  void *Vertices,
3500                                                  DWORD VertexCount,
3501                                                  WORD *Indices,
3502                                                  DWORD IndexCount,
3503                                                  DWORD Flags)
3504 {
3505     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3506     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3507     return IDirect3DDevice7_DrawIndexedPrimitive(ICOM_INTERFACE(This, IDirect3DDevice7),
3508                                                  PrimitiveType,
3509                                                  VertexType,
3510                                                  Vertices,
3511                                                  VertexCount,
3512                                                  Indices,
3513                                                  IndexCount,
3514                                                  Flags);
3515 }
3516
3517 static HRESULT WINAPI
3518 Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3519                                                  D3DPRIMITIVETYPE PrimitiveType,
3520                                                  D3DVERTEXTYPE VertexType,
3521                                                  void *Vertices,
3522                                                  DWORD VertexCount,
3523                                                  WORD *Indices,
3524                                                  DWORD IndexCount,
3525                                                  DWORD Flags)
3526 {
3527     DWORD FVF;
3528     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3529     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3530
3531     switch(VertexType)
3532     {
3533         case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3534         case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3535         case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3536         default:
3537             ERR("Unexpected vertex type %d\n", VertexType);
3538             return DDERR_INVALIDPARAMS;  /* Should never happen */
3539     }
3540
3541     return IDirect3DDevice7_DrawIndexedPrimitive(ICOM_INTERFACE(This, IDirect3DDevice7),
3542                                                  PrimitiveType,
3543                                                  FVF,
3544                                                  Vertices,
3545                                                  VertexCount,
3546                                                  Indices,
3547                                                  IndexCount,
3548                                                  Flags);
3549 }
3550
3551 /*****************************************************************************
3552  * IDirect3DDevice7::SetClipStatus
3553  *
3554  * Sets the clip status. This defines things as clipping conditions and
3555  * the extents of the clipping region.
3556  *
3557  * Version 2, 3 and 7
3558  *
3559  * Params:
3560  *  ClipStatus:
3561  *
3562  * Returns:
3563  *  D3D_OK because it's a stub
3564  *  (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3565  *
3566  *****************************************************************************/
3567 static HRESULT WINAPI
3568 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3569                                     D3DCLIPSTATUS *ClipStatus)
3570 {
3571     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3572     FIXME("(%p)->(%p): Stub!\n", This, ClipStatus);
3573
3574     /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3575      * Perhaps this needs a new data type and an additional IWineD3DDevice method
3576      */
3577     /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3578     return D3D_OK;
3579 }
3580
3581 static HRESULT WINAPI
3582 Thunk_IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3583                                           D3DCLIPSTATUS *ClipStatus)
3584 {
3585     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3586     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3587     return IDirect3DDevice7_SetClipStatus(ICOM_INTERFACE(This, IDirect3DDevice7),
3588                                           ClipStatus);
3589 }
3590
3591 static HRESULT WINAPI
3592 Thunk_IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3593                                           D3DCLIPSTATUS *ClipStatus)
3594 {
3595     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3596     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3597     return IDirect3DDevice7_SetClipStatus(ICOM_INTERFACE(This, IDirect3DDevice7),
3598                                           ClipStatus);
3599 }
3600
3601 /*****************************************************************************
3602  * IDirect3DDevice7::GetClipStatus
3603  *
3604  * Returns the clip status
3605  *
3606  * Params:
3607  *  ClipStatus: Address to write the clip status to
3608  *
3609  * Returns:
3610  *  D3D_OK because it's a stub
3611  *
3612  *****************************************************************************/
3613 static HRESULT WINAPI
3614 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3615                                     D3DCLIPSTATUS *ClipStatus)
3616 {
3617     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3618     FIXME("(%p)->(%p): Stub!\n", This, ClipStatus);
3619
3620     /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3621     /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3622     return D3D_OK;
3623 }
3624
3625 static HRESULT WINAPI
3626 Thunk_IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3627                                           D3DCLIPSTATUS *ClipStatus)
3628 {
3629     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3630     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3631     return IDirect3DDevice7_GetClipStatus(ICOM_INTERFACE(This, IDirect3DDevice7),
3632                                           ClipStatus);
3633 }
3634
3635 static HRESULT WINAPI
3636 Thunk_IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3637                                           D3DCLIPSTATUS *ClipStatus)
3638 {
3639     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3640     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3641     return IDirect3DDevice7_GetClipStatus(ICOM_INTERFACE(This, IDirect3DDevice7),
3642                                           ClipStatus);
3643 }
3644
3645 /*****************************************************************************
3646  * IDirect3DDevice::DrawPrimitiveStrided
3647  *
3648  * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3649  *
3650  * Version 3 and 7
3651  *
3652  * Params:
3653  *  PrimitiveType: The primitive type to draw
3654  *  VertexType: The FVF description of the vertices to draw (for the stride??)
3655  *  D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3656  *                         the vertex data locations
3657  *  VertexCount: The number of vertices to draw
3658  *  Flags: Some flags
3659  *
3660  * Returns:
3661  *  D3D_OK, because it's a stub
3662  *  (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3663  *  (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3664  *
3665  *****************************************************************************/
3666 static HRESULT WINAPI
3667 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3668                                            D3DPRIMITIVETYPE PrimitiveType,
3669                                            DWORD VertexType,
3670                                            D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3671                                            DWORD VertexCount,
3672                                            DWORD Flags)
3673 {
3674     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3675     WineDirect3DVertexStridedData WineD3DStrided;
3676     int i;
3677     UINT PrimitiveCount;
3678     HRESULT hr;
3679
3680     TRACE("(%p)->(%08x,%08x,%p,%08x,%08x): stub!\n", This, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3681
3682     memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3683     /* Get the strided data right. the wined3d structure is a bit bigger
3684      * Watch out: The contents of the strided data are determined by the fvf,
3685      * not by the members set in D3DDrawPrimStrideData. So it's valid
3686      * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3687      * not set in the fvf.
3688      */
3689     if(VertexType & D3DFVF_POSITION_MASK)
3690     {
3691         WineD3DStrided.u.s.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3692         WineD3DStrided.u.s.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3693         WineD3DStrided.u.s.position.dwType = WINED3DDECLTYPE_FLOAT3;
3694         if (VertexType & D3DFVF_XYZRHW)
3695         {
3696             WineD3DStrided.u.s.position.dwType = WINED3DDECLTYPE_FLOAT4;
3697             WineD3DStrided.u.s.position_transformed = TRUE;
3698         } else
3699             WineD3DStrided.u.s.position_transformed = FALSE;
3700     }
3701
3702     if(VertexType & D3DFVF_NORMAL)
3703     {
3704         WineD3DStrided.u.s.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3705         WineD3DStrided.u.s.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3706         WineD3DStrided.u.s.normal.dwType = WINED3DDECLTYPE_FLOAT3;
3707     }
3708
3709     if(VertexType & D3DFVF_DIFFUSE)
3710     {
3711         WineD3DStrided.u.s.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3712         WineD3DStrided.u.s.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3713         WineD3DStrided.u.s.diffuse.dwType = WINED3DDECLTYPE_D3DCOLOR;
3714     }
3715
3716     if(VertexType & D3DFVF_SPECULAR)
3717     {
3718         WineD3DStrided.u.s.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3719         WineD3DStrided.u.s.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3720         WineD3DStrided.u.s.specular.dwType = WINED3DDECLTYPE_D3DCOLOR;
3721     }
3722
3723     for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3724     {
3725         WineD3DStrided.u.s.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3726         WineD3DStrided.u.s.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3727         switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3728         {
3729             case 1: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT1; break;
3730             case 2: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT2; break;
3731             case 3: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT3; break;
3732             case 4: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT4; break;
3733             default: ERR("Unexpected texture coordinate size %d\n",
3734                          GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3735         }
3736     }
3737
3738     /* Get the primitive count */
3739     switch(PrimitiveType)
3740     {
3741         case D3DPT_POINTLIST: 
3742           PrimitiveCount = VertexCount;
3743           break;
3744
3745         case D3DPT_LINELIST: 
3746           PrimitiveCount = VertexCount / 2;
3747           break;
3748
3749         case D3DPT_LINESTRIP:
3750           PrimitiveCount = VertexCount - 1;
3751           break;
3752
3753         case D3DPT_TRIANGLELIST:
3754           PrimitiveCount = VertexCount / 3;
3755           break;
3756
3757         case D3DPT_TRIANGLESTRIP:
3758           PrimitiveCount = VertexCount - 2;
3759           break;
3760
3761         case D3DPT_TRIANGLEFAN:
3762           PrimitiveCount = VertexCount - 2;
3763           break;
3764
3765         default: return DDERR_INVALIDPARAMS;
3766     }
3767
3768     /* WineD3D doesn't need the FVF here */
3769     EnterCriticalSection(&ddraw_cs);
3770     hr = IWineD3DDevice_DrawPrimitiveStrided(This->wineD3DDevice,
3771                                              PrimitiveType,
3772                                              PrimitiveCount,
3773                                              &WineD3DStrided);
3774     LeaveCriticalSection(&ddraw_cs);
3775     return hr;
3776 }
3777
3778 static HRESULT WINAPI
3779 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3780                                                  D3DPRIMITIVETYPE PrimitiveType,
3781                                                  DWORD VertexType,
3782                                                  D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3783                                                  DWORD VertexCount,
3784                                                  DWORD Flags)
3785 {
3786     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3787     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3788     return IDirect3DDevice7_DrawPrimitiveStrided(ICOM_INTERFACE(This, IDirect3DDevice7),
3789                                                  PrimitiveType,
3790                                                  VertexType,
3791                                                  D3DDrawPrimStrideData,
3792                                                  VertexCount,
3793                                                  Flags);
3794 }
3795
3796 /*****************************************************************************
3797  * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3798  *
3799  * Draws primitives specified by strided data locations based on indices
3800  *
3801  * Version 3 and 7
3802  *
3803  * Params:
3804  *  PrimitiveType:
3805  *
3806  * Returns:
3807  *  D3D_OK, because it's a stub
3808  *  (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3809  *  (DDERR_INVALIDPARAMS if Indices is NULL)
3810  *  (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3811  *
3812  *****************************************************************************/
3813 static HRESULT WINAPI
3814 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3815                                                   D3DPRIMITIVETYPE PrimitiveType,
3816                                                   DWORD VertexType,
3817                                                   D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3818                                                   DWORD VertexCount,
3819                                                   WORD *Indices,
3820                                                   DWORD IndexCount,
3821                                                   DWORD Flags)
3822 {
3823     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3824     WineDirect3DVertexStridedData WineD3DStrided;
3825     int i;
3826     UINT PrimitiveCount;
3827     HRESULT hr;
3828
3829     TRACE("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x)\n", This, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3830
3831     memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3832     /* Get the strided data right. the wined3d structure is a bit bigger
3833      * Watch out: The contents of the strided data are determined by the fvf,
3834      * not by the members set in D3DDrawPrimStrideData. So it's valid
3835      * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3836      * not set in the fvf.
3837      */
3838     if(VertexType & D3DFVF_POSITION_MASK)
3839     {
3840         WineD3DStrided.u.s.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3841         WineD3DStrided.u.s.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3842         WineD3DStrided.u.s.position.dwType = WINED3DDECLTYPE_FLOAT3;
3843         if (VertexType & D3DFVF_XYZRHW)
3844         {
3845             WineD3DStrided.u.s.position.dwType = WINED3DDECLTYPE_FLOAT4;
3846             WineD3DStrided.u.s.position_transformed = TRUE;
3847         } else
3848             WineD3DStrided.u.s.position_transformed = FALSE;
3849     }
3850
3851     if(VertexType & D3DFVF_NORMAL)
3852     {
3853         WineD3DStrided.u.s.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3854         WineD3DStrided.u.s.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3855         WineD3DStrided.u.s.normal.dwType = WINED3DDECLTYPE_FLOAT3;
3856     }
3857
3858     if(VertexType & D3DFVF_DIFFUSE)
3859     {
3860         WineD3DStrided.u.s.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3861         WineD3DStrided.u.s.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3862         WineD3DStrided.u.s.diffuse.dwType = WINED3DDECLTYPE_D3DCOLOR;
3863     }
3864
3865     if(VertexType & D3DFVF_SPECULAR)
3866     {
3867         WineD3DStrided.u.s.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3868         WineD3DStrided.u.s.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3869         WineD3DStrided.u.s.specular.dwType = WINED3DDECLTYPE_D3DCOLOR;
3870     }
3871
3872     for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3873     {
3874         WineD3DStrided.u.s.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3875         WineD3DStrided.u.s.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3876         switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3877         {
3878             case 1: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT1; break;
3879             case 2: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT2; break;
3880             case 3: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT3; break;
3881             case 4: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT4; break;
3882             default: ERR("Unexpected texture coordinate size %d\n",
3883                          GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3884         }
3885     }
3886
3887     /* Get the primitive count */
3888     switch(PrimitiveType)
3889     {
3890         case D3DPT_POINTLIST:
3891             PrimitiveCount = IndexCount;
3892             break;
3893
3894         case D3DPT_LINELIST:
3895             PrimitiveCount = IndexCount / 2;
3896             break;
3897
3898         case D3DPT_LINESTRIP:
3899             PrimitiveCount = IndexCount - 1;
3900             break;
3901
3902         case D3DPT_TRIANGLELIST:
3903             PrimitiveCount = IndexCount / 3;
3904             break;
3905
3906         case D3DPT_TRIANGLESTRIP:
3907             PrimitiveCount = IndexCount - 2;
3908             break;
3909
3910         case D3DPT_TRIANGLEFAN:
3911             PrimitiveCount = IndexCount - 2;
3912             break;
3913
3914             default: return DDERR_INVALIDPARAMS;
3915     }
3916
3917     /* WineD3D doesn't need the FVF here */
3918     EnterCriticalSection(&ddraw_cs);
3919     hr = IWineD3DDevice_DrawIndexedPrimitiveStrided(This->wineD3DDevice,
3920                                                     PrimitiveType,
3921                                                     PrimitiveCount,
3922                                                     &WineD3DStrided,
3923                                                     VertexCount,
3924                                                     Indices,
3925                                                     WINED3DFMT_INDEX16);
3926     LeaveCriticalSection(&ddraw_cs);
3927     return hr;
3928 }
3929
3930 static HRESULT WINAPI
3931 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
3932                                                         D3DPRIMITIVETYPE PrimitiveType,
3933                                                         DWORD VertexType,
3934                                                         D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3935                                                         DWORD VertexCount,
3936                                                         WORD *Indices,
3937                                                         DWORD IndexCount,
3938                                                         DWORD Flags)
3939 {
3940     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3941     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3942     return IDirect3DDevice7_DrawIndexedPrimitiveStrided(ICOM_INTERFACE(This, IDirect3DDevice7),
3943                                                         PrimitiveType,
3944                                                         VertexType,
3945                                                         D3DDrawPrimStrideData,
3946                                                         VertexCount,
3947                                                         Indices,
3948                                                         IndexCount,
3949                                                         Flags);
3950 }
3951
3952 /*****************************************************************************
3953  * IDirect3DDevice7::DrawPrimitiveVB
3954  *
3955  * Draws primitives from a vertex buffer to the screen.
3956  *
3957  * Version 3 and 7
3958  *
3959  * Params:
3960  *  PrimitiveType: Type of primitive to be rendered.
3961  *  D3DVertexBuf: Source Vertex Buffer
3962  *  StartVertex: Index of the first vertex from the buffer to be rendered
3963  *  NumVertices: Number of vertices to be rendered
3964  *  Flags: Can be D3DDP_WAIT to wait until rendering has finished
3965  *
3966  * Return values
3967  *  D3D_OK on success
3968  *  DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
3969  *
3970  *****************************************************************************/
3971 static HRESULT WINAPI
3972 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
3973                                       D3DPRIMITIVETYPE PrimitiveType,
3974                                       IDirect3DVertexBuffer7 *D3DVertexBuf,
3975                                       DWORD StartVertex,
3976                                       DWORD NumVertices,
3977                                       DWORD Flags)
3978 {
3979     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3980     IDirect3DVertexBufferImpl *vb = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, D3DVertexBuf);
3981     UINT PrimitiveCount;
3982     HRESULT hr;
3983     DWORD stride;
3984     WINED3DVERTEXBUFFER_DESC Desc;
3985
3986     TRACE("(%p)->(%08x,%p,%08x,%08x,%08x)\n", This, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
3987
3988     /* Sanity checks */
3989     if(!vb)
3990     {
3991         ERR("(%p) No Vertex buffer specified\n", This);
3992         return DDERR_INVALIDPARAMS;
3993     }
3994
3995     /* Get the primitive count */
3996     switch(PrimitiveType)
3997     {
3998         case D3DPT_POINTLIST: 
3999           PrimitiveCount = NumVertices;
4000           break;
4001
4002         case D3DPT_LINELIST: 
4003           PrimitiveCount = NumVertices / 2;
4004           break;
4005
4006         case D3DPT_LINESTRIP:
4007           PrimitiveCount = NumVertices - 1;
4008           break;
4009
4010         case D3DPT_TRIANGLELIST:
4011           PrimitiveCount = NumVertices / 3;
4012           break;
4013
4014         case D3DPT_TRIANGLESTRIP:
4015           PrimitiveCount = NumVertices - 2;
4016           break;
4017
4018         case D3DPT_TRIANGLEFAN:
4019           PrimitiveCount = NumVertices - 2;
4020           break;
4021
4022         default:
4023           return DDERR_INVALIDPARAMS;
4024     }
4025
4026     /* Get the FVF of the vertex buffer, and its stride */
4027     EnterCriticalSection(&ddraw_cs);
4028     hr = IWineD3DVertexBuffer_GetDesc(vb->wineD3DVertexBuffer,
4029                                       &Desc);
4030     if(hr != D3D_OK)
4031     {
4032         ERR("(%p) IWineD3DVertexBuffer::GetDesc failed with hr = %08x\n", This, hr);
4033         LeaveCriticalSection(&ddraw_cs);
4034         return hr;
4035     }
4036     stride = get_flexible_vertex_size(Desc.FVF);
4037
4038     hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4039                                              vb->wineD3DVertexDeclaration);
4040     if(FAILED(hr))
4041     {
4042         ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4043         LeaveCriticalSection(&ddraw_cs);
4044         return hr;
4045     }
4046
4047     /* Set the vertex stream source */
4048     hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4049                                         0 /* StreamNumber */,
4050                                         vb->wineD3DVertexBuffer,
4051                                         0 /* StartVertex - we pass this to DrawPrimitive */,
4052                                         stride);
4053     if(hr != D3D_OK)
4054     {
4055         ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4056         LeaveCriticalSection(&ddraw_cs);
4057         return hr;
4058     }
4059
4060     /* Now draw the primitives */
4061     hr = IWineD3DDevice_DrawPrimitive(This->wineD3DDevice,
4062                                       PrimitiveType,
4063                                       StartVertex,
4064                                       PrimitiveCount);
4065     LeaveCriticalSection(&ddraw_cs);
4066     return hr;
4067 }
4068
4069 static HRESULT WINAPI
4070 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4071                                             D3DPRIMITIVETYPE PrimitiveType,
4072                                             IDirect3DVertexBuffer *D3DVertexBuf,
4073                                             DWORD StartVertex,
4074                                             DWORD NumVertices,
4075                                             DWORD Flags)
4076 {
4077     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4078     IDirect3DVertexBufferImpl *vb = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, D3DVertexBuf);
4079     TRACE_(ddraw_thunk)("(%p)->(%08x,%p,%08x,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This,  PrimitiveType, vb, StartVertex, NumVertices, Flags);
4080     return IDirect3DDevice7_DrawPrimitiveVB(ICOM_INTERFACE(This, IDirect3DDevice7),
4081                                             PrimitiveType,
4082                                             ICOM_INTERFACE(vb, IDirect3DVertexBuffer7),
4083                                             StartVertex,
4084                                             NumVertices,
4085                                             Flags);
4086 }
4087
4088
4089 /*****************************************************************************
4090  * IDirect3DDevice7::DrawIndexedPrimitiveVB
4091  *
4092  * Draws primitives from a vertex buffer to the screen
4093  *
4094  * Params:
4095  *  PrimitiveType: Type of primitive to be rendered.
4096  *  D3DVertexBuf: Source Vertex Buffer
4097  *  StartVertex: Index of the first vertex from the buffer to be rendered
4098  *  NumVertices: Number of vertices to be rendered
4099  *  Indices: Array of DWORDs used to index into the Vertices
4100  *  IndexCount: Number of indices in Indices
4101  *  Flags: Can be D3DDP_WAIT to wait until rendering has finished
4102  *
4103  * Return values
4104  *
4105  *****************************************************************************/
4106 static HRESULT WINAPI
4107 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4108                                              D3DPRIMITIVETYPE PrimitiveType,
4109                                              IDirect3DVertexBuffer7 *D3DVertexBuf,
4110                                              DWORD StartVertex,
4111                                              DWORD NumVertices,
4112                                              WORD *Indices,
4113                                              DWORD IndexCount,
4114                                              DWORD Flags)
4115 {
4116     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4117     IDirect3DVertexBufferImpl *vb = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, D3DVertexBuf);
4118     DWORD stride;
4119     UINT PrimitiveCount;
4120     WORD *LockedIndices;
4121     HRESULT hr;
4122     WINED3DVERTEXBUFFER_DESC Desc;
4123
4124     TRACE("(%p)->(%08x,%p,%d,%d,%p,%d,%08x)\n", This, PrimitiveType, vb, StartVertex, NumVertices, Indices, IndexCount, Flags);
4125
4126     /* Steps:
4127      * 1) Calculate some things: Vertex count -> Primitive count, stride, ...
4128      * 2) Upload the Indices to the index buffer
4129      * 3) Set the index source
4130      * 4) Set the Vertex Buffer as the Stream source
4131      * 5) Call IWineD3DDevice::DrawIndexedPrimitive
4132      */
4133
4134     /* Get the primitive count */
4135     switch(PrimitiveType)
4136     {
4137         case D3DPT_POINTLIST: 
4138           PrimitiveCount = IndexCount;
4139           break;
4140
4141         case D3DPT_LINELIST: 
4142           PrimitiveCount = IndexCount / 2;
4143           break;
4144
4145         case D3DPT_LINESTRIP:
4146           PrimitiveCount = IndexCount - 1;
4147           break;
4148
4149         case D3DPT_TRIANGLELIST:
4150           PrimitiveCount = IndexCount / 3;
4151           break;
4152
4153         case D3DPT_TRIANGLESTRIP:
4154           PrimitiveCount = IndexCount - 2;
4155           break;
4156
4157         case D3DPT_TRIANGLEFAN:
4158           PrimitiveCount = IndexCount - 2;
4159           break;
4160
4161         default: return DDERR_INVALIDPARAMS;
4162     }
4163
4164     EnterCriticalSection(&ddraw_cs);
4165     /* Get the FVF of the vertex buffer, and its stride */
4166     hr = IWineD3DVertexBuffer_GetDesc(vb->wineD3DVertexBuffer,
4167                                       &Desc);
4168     if(hr != D3D_OK)
4169     {
4170         ERR("(%p) IWineD3DVertexBuffer::GetDesc failed with hr = %08x\n", This, hr);
4171         LeaveCriticalSection(&ddraw_cs);
4172         return hr;
4173     }
4174     stride = get_flexible_vertex_size(Desc.FVF);
4175     TRACE("Vertex buffer FVF = %08x, stride=%d\n", Desc.FVF, stride);
4176
4177     hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4178                                              vb->wineD3DVertexDeclaration);
4179     if(FAILED(hr))
4180     {
4181         ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4182         LeaveCriticalSection(&ddraw_cs);
4183         return hr;
4184     }
4185
4186     /* copy the index stream into the index buffer.
4187      * A new IWineD3DDevice method could be created
4188      * which takes an user pointer containing the indices
4189      * or a SetData-Method for the index buffer, which
4190      * overrides the index buffer data with our pointer.
4191      */
4192     hr = IWineD3DIndexBuffer_Lock(This->indexbuffer,
4193                                   0 /* OffSetToLock */,
4194                                   IndexCount * sizeof(WORD),
4195                                   (BYTE **) &LockedIndices,
4196                                   0 /* Flags */);
4197     assert(IndexCount < 0x100000);
4198     if(hr != D3D_OK)
4199     {
4200         ERR("(%p) IWineD3DIndexBuffer::Lock failed with hr = %08x\n", This, hr);
4201         LeaveCriticalSection(&ddraw_cs);
4202         return hr;
4203     }
4204     memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4205     hr = IWineD3DIndexBuffer_Unlock(This->indexbuffer);
4206     if(hr != D3D_OK)
4207     {
4208         ERR("(%p) IWineD3DIndexBuffer::Unlock failed with hr = %08x\n", This, hr);
4209         LeaveCriticalSection(&ddraw_cs);
4210         return hr;
4211     }
4212
4213     /* Set the index stream */
4214     IWineD3DDevice_SetBaseVertexIndex(This->wineD3DDevice, StartVertex);
4215     hr = IWineD3DDevice_SetIndices(This->wineD3DDevice, This->indexbuffer);
4216
4217     /* Set the vertex stream source */
4218     hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4219                                         0 /* StreamNumber */,
4220                                         vb->wineD3DVertexBuffer,
4221                                         0 /* offset, we pass this to DrawIndexedPrimitive */,
4222                                         stride);
4223     if(hr != D3D_OK)
4224     {
4225         ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4226         LeaveCriticalSection(&ddraw_cs);
4227         return hr;
4228     }
4229
4230
4231     hr = IWineD3DDevice_DrawIndexedPrimitive(This->wineD3DDevice,
4232                                              PrimitiveType,
4233                                              0 /* minIndex */,
4234                                              NumVertices,
4235                                              0 /* StartIndex */,
4236                                              PrimitiveCount);
4237
4238     LeaveCriticalSection(&ddraw_cs);
4239     return hr;
4240 }
4241
4242 static HRESULT WINAPI
4243 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4244                                                    D3DPRIMITIVETYPE PrimitiveType,
4245                                                    IDirect3DVertexBuffer *D3DVertexBuf,
4246                                                    WORD *Indices,
4247                                                    DWORD IndexCount,
4248                                                    DWORD Flags)
4249 {
4250     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4251     IDirect3DVertexBufferImpl *VB = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, D3DVertexBuf);
4252     TRACE_(ddraw_thunk)("(%p)->(%08x,%p,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VB, Indices, IndexCount, Flags);
4253
4254     return IDirect3DDevice7_DrawIndexedPrimitiveVB(ICOM_INTERFACE(This, IDirect3DDevice7),
4255                                                    PrimitiveType,
4256                                                    ICOM_INTERFACE(VB, IDirect3DVertexBuffer7),
4257                                                    0,
4258                                                    IndexCount,
4259                                                    Indices,
4260                                                    IndexCount,
4261                                                    Flags);
4262 }
4263
4264 /*****************************************************************************
4265  * IDirect3DDevice7::ComputeSphereVisibility
4266  *
4267  * Calculates the visibility of spheres in the current viewport. The spheres
4268  * are passed in the Centers and Radii arrays, the results are passed back
4269  * in the ReturnValues array. Return values are either completely visible,
4270  * partially visible or completely invisible.
4271  * The return value consist of a combination of D3DCLIP_* flags, or it's
4272  * 0 if the sphere is completely visible(according to the SDK, not checked)
4273  *
4274  * Sounds like an overdose of math ;)
4275  *
4276  * Version 3 and 7
4277  *
4278  * Params:
4279  *  Centers: Array containing the sphere centers
4280  *  Radii: Array containing the sphere radii
4281  *  NumSpheres: The number of centers and radii in the arrays
4282  *  Flags: Some flags
4283  *  ReturnValues: Array to write the results to
4284  *
4285  * Returns:
4286  *  D3D_OK because it's a stub
4287  *  (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4288  *  (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4289  *  is singular)
4290  *
4291  *****************************************************************************/
4292 static HRESULT WINAPI
4293 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4294                                               D3DVECTOR *Centers,
4295                                               D3DVALUE *Radii,
4296                                               DWORD NumSpheres,
4297                                               DWORD Flags,
4298                                               DWORD *ReturnValues)
4299 {
4300     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4301     FIXME("(%p)->(%p,%p,%08x,%08x,%p): stub!\n", This, Centers, Radii, NumSpheres, Flags, ReturnValues);
4302
4303     /* the DirectX 7 sdk says that the visibility is computed by
4304      * back-transforming the viewing frustum to model space
4305      * using the inverse of the combined world, view and projection
4306      * matrix. If the matrix can't be reversed, D3DERR_INVALIDMATRIX
4307      * is returned.
4308      *
4309      * Basic implementation idea:
4310      * 1) Check if the center is in the viewing frustum
4311      * 2) Cut the sphere with the planes of the viewing
4312      *    frustum
4313      *
4314      * ->Center inside the frustum, no intersections:
4315      *    Fully visible
4316      * ->Center outside the frustum, no intersections:
4317      *    Not visible
4318      * ->Some intersections: Partially visible
4319      *
4320      * Implement this call in WineD3D. Either implement the
4321      * matrix and vector stuff in WineD3D, or use some external
4322      * math library.
4323      */
4324
4325     return D3D_OK;
4326 }
4327
4328 static HRESULT WINAPI
4329 Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4330                                                     D3DVECTOR *Centers,
4331                                                     D3DVALUE *Radii,
4332                                                     DWORD NumSpheres,
4333                                                     DWORD Flags,
4334                                                     DWORD *ReturnValues)
4335 {
4336     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4337     TRACE_(ddraw_thunk)("(%p)->(%p,%p,%08x,%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, Centers, Radii, NumSpheres, Flags, ReturnValues);
4338     return IDirect3DDevice7_ComputeSphereVisibility(ICOM_INTERFACE(This, IDirect3DDevice7),
4339                                                     Centers,
4340                                                     Radii,
4341                                                     NumSpheres,
4342                                                     Flags,
4343                                                     ReturnValues);
4344 }
4345
4346 /*****************************************************************************
4347  * IDirect3DDevice7::GetTexture
4348  *
4349  * Returns the texture interface handle assigned to a texture stage.
4350  * The returned texture is AddRefed. This is taken from old ddraw,
4351  * not checked in Windows.
4352  *
4353  * Version 3 and 7
4354  *
4355  * Params:
4356  *  Stage: Texture stage to read the texture from
4357  *  Texture: Address to store the interface pointer at
4358  *
4359  * Returns:
4360  *  D3D_OK on success
4361  *  DDERR_INVALIDPARAMS if Texture is NULL
4362  *  For details, see IWineD3DDevice::GetTexture
4363  *
4364  *****************************************************************************/
4365 static HRESULT WINAPI
4366 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4367                                  DWORD Stage,
4368                                  IDirectDrawSurface7 **Texture)
4369 {
4370     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4371     IWineD3DBaseTexture *Surf;
4372     HRESULT hr;
4373     TRACE("(%p)->(%d,%p): Relay\n", This, Stage, Texture);
4374
4375     if(!Texture)
4376     {
4377         TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4378         return DDERR_INVALIDPARAMS;
4379     }
4380
4381     EnterCriticalSection(&ddraw_cs);
4382     hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, Stage, &Surf);
4383     if( (hr != D3D_OK) || (!Surf) ) 
4384     {
4385         *Texture = NULL;
4386         LeaveCriticalSection(&ddraw_cs);
4387         return hr;
4388     }
4389
4390     /* GetParent AddRef()s, which is perfectly OK.
4391      * We have passed the IDirectDrawSurface7 interface to WineD3D, so that's OK too.
4392      */
4393     hr = IWineD3DBaseTexture_GetParent(Surf,
4394                                        (IUnknown **) Texture);
4395     LeaveCriticalSection(&ddraw_cs);
4396     return hr;
4397 }
4398
4399 static HRESULT WINAPI
4400 Thunk_IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface,
4401                                        DWORD Stage,
4402                                        IDirect3DTexture2 **Texture2)
4403 {
4404     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4405     HRESULT ret;
4406     IDirectDrawSurface7 *ret_val;
4407
4408     TRACE_(ddraw_thunk)("(%p)->(%d,%p) thunking to IDirect3DDevice7 interface.\n", This, Stage, Texture2);
4409     ret = IDirect3DDevice7_GetTexture(ICOM_INTERFACE(This, IDirect3DDevice7),
4410                                       Stage,
4411                                       &ret_val);
4412
4413     *Texture2 = COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirectDrawSurface7, IDirect3DTexture2, ret_val);
4414
4415     TRACE_(ddraw_thunk)(" returning interface %p.\n", *Texture2);
4416
4417     return ret;
4418 }
4419
4420 /*****************************************************************************
4421  * IDirect3DDevice7::SetTexture
4422  *
4423  * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4424  *
4425  * Version 3 and 7
4426  *
4427  * Params:
4428  *  Stage: The stage to assign the texture to
4429  *  Texture: Interface pointer to the texture surface
4430  *
4431  * Returns
4432  * D3D_OK on success
4433  * For details, see IWineD3DDevice::SetTexture
4434  *
4435  *****************************************************************************/
4436 static HRESULT WINAPI
4437 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4438                                  DWORD Stage,
4439                                  IDirectDrawSurface7 *Texture)
4440 {
4441     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4442     IDirectDrawSurfaceImpl *surf = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, Texture);
4443     HRESULT hr;
4444     TRACE("(%p)->(%08x,%p): Relay!\n", This, Stage, surf);
4445
4446     /* Texture may be NULL here */
4447     EnterCriticalSection(&ddraw_cs);
4448     hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
4449                                    Stage,
4450                                    surf ? surf->wineD3DTexture : NULL);
4451     LeaveCriticalSection(&ddraw_cs);
4452     return hr;
4453 }
4454
4455 static HRESULT WINAPI
4456 Thunk_IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4457                                        DWORD Stage,
4458                                        IDirect3DTexture2 *Texture2)
4459 {
4460     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4461     IDirectDrawSurfaceImpl *tex = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture2, Texture2);
4462     TRACE_(ddraw_thunk)("(%p)->(%d,%p) thunking to IDirect3DDevice7 interface.\n", This, Stage, tex);
4463     return IDirect3DDevice7_SetTexture(ICOM_INTERFACE(This, IDirect3DDevice7),
4464                                        Stage,
4465                                        ICOM_INTERFACE(tex, IDirectDrawSurface7));
4466 }
4467
4468 /*****************************************************************************
4469  * IDirect3DDevice7::GetTextureStageState
4470  *
4471  * Retrieves a state from a texture stage.
4472  *
4473  * Version 3 and 7
4474  *
4475  * Params:
4476  *  Stage: The stage to retrieve the state from
4477  *  TexStageStateType: The state type to retrieve
4478  *  State: Address to store the state's value at
4479  *
4480  * Returns:
4481  *  D3D_OK on success
4482  *  DDERR_INVALIDPARAMS if State is NULL
4483  *  For details, see IWineD3DDevice::GetTextureStageState
4484  *
4485  *****************************************************************************/
4486 static HRESULT WINAPI
4487 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4488                                            DWORD Stage,
4489                                            D3DTEXTURESTAGESTATETYPE TexStageStateType,
4490                                            DWORD *State)
4491 {
4492     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4493     HRESULT hr;
4494     TRACE("(%p)->(%08x,%08x,%p): Relay!\n", This, Stage, TexStageStateType, State);
4495
4496     if(!State)
4497         return DDERR_INVALIDPARAMS;
4498
4499     EnterCriticalSection(&ddraw_cs);
4500     switch(TexStageStateType)
4501     {
4502         /* Mipfilter is a sampler state with different values */
4503         case D3DTSS_MIPFILTER:
4504         {
4505             WINED3DTEXTUREFILTERTYPE value;
4506
4507             hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
4508                                                 Stage,
4509                                                 WINED3DSAMP_MIPFILTER,
4510                                                 &value);
4511             switch(value)
4512             {
4513                 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4514                 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4515                 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4516                 default:
4517                     ERR("Unexpected mipfilter value %d\n", value);
4518                     *State = D3DTFP_NONE;
4519             }
4520             break;
4521         }
4522
4523         /* Minfilter is a sampler state too, equal values */
4524         case D3DTSS_MINFILTER:
4525             hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
4526                                                 Stage,
4527                                                 WINED3DSAMP_MINFILTER,
4528                                                 State);
4529             break;
4530
4531         /* Magfilter has slightly different values */
4532         case D3DTSS_MAGFILTER:
4533         {
4534             WINED3DTEXTUREFILTERTYPE wined3dfilter;
4535             hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
4536                                                 Stage,
4537                                                 WINED3DSAMP_MAGFILTER,
4538                                                 &wined3dfilter);
4539             switch(wined3dfilter)
4540             {
4541                 case WINED3DTEXF_POINT:             *State = D3DTFG_POINT;          break;
4542                 case WINED3DTEXF_LINEAR:            *State = D3DTFG_LINEAR;         break;
4543                 case WINED3DTEXF_ANISOTROPIC:       *State = D3DTFG_ANISOTROPIC;    break;
4544                 case WINED3DTEXF_FLATCUBIC:         *State = D3DTFG_FLATCUBIC;      break;
4545                 case WINED3DTEXF_GAUSSIANCUBIC:     *State = D3DTFG_GAUSSIANCUBIC;  break;
4546                 default:
4547                     ERR("Unexpected wined3d mag filter value %d\n", wined3dfilter);
4548                     *State = D3DTFG_POINT;
4549             }
4550             break;
4551         }
4552
4553         case D3DTSS_ADDRESS:
4554         case D3DTSS_ADDRESSU:
4555             hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
4556                                                 Stage,
4557                                                 WINED3DSAMP_ADDRESSU,
4558                                                 State);
4559             break;
4560         case D3DTSS_ADDRESSV:
4561             hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
4562                                                 Stage,
4563                                                 WINED3DSAMP_ADDRESSV,
4564                                                 State);
4565             break;
4566         default:
4567             hr = IWineD3DDevice_GetTextureStageState(This->wineD3DDevice,
4568                                                      Stage,
4569                                                      TexStageStateType,
4570                                                      State);
4571             break;
4572     }
4573     LeaveCriticalSection(&ddraw_cs);
4574     return hr;
4575 }
4576
4577 static HRESULT WINAPI
4578 Thunk_IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4579                                                  DWORD Stage,
4580                                                  D3DTEXTURESTAGESTATETYPE TexStageStateType,
4581                                                  DWORD *State)
4582 {
4583     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4584     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, Stage, TexStageStateType, State);
4585     return IDirect3DDevice7_GetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
4586                                                  Stage,
4587                                                  TexStageStateType,
4588                                                  State);
4589 }
4590
4591 /*****************************************************************************
4592  * IDirect3DDevice7::SetTextureStageState
4593  *
4594  * Sets a texture stage state. Some stage types need to be handled specially,
4595  * because they do not exist in WineD3D and were moved to another place
4596  *
4597  * Version 3 and 7
4598  *
4599  * Params:
4600  *  Stage: The stage to modify
4601  *  TexStageStateType: The state to change
4602  *  State: The new value for the state
4603  *
4604  * Returns:
4605  *  D3D_OK on success
4606  *  For details, see IWineD3DDevice::SetTextureStageState
4607  *
4608  *****************************************************************************/
4609 static HRESULT WINAPI
4610 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4611                                            DWORD Stage,
4612                                            D3DTEXTURESTAGESTATETYPE TexStageStateType,
4613                                            DWORD State)
4614 {
4615     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4616     HRESULT hr;
4617     TRACE("(%p)->(%08x,%08x,%08x): Relay!\n", This, Stage, TexStageStateType, State);
4618
4619     EnterCriticalSection(&ddraw_cs);
4620     switch(TexStageStateType)
4621     {
4622         /* Mipfilter is a sampler state with different values */
4623         case D3DTSS_MIPFILTER:
4624         {
4625             WINED3DTEXTUREFILTERTYPE value;
4626             switch(State)
4627             {
4628                 case D3DTFP_NONE: value = WINED3DTEXF_NONE; break;
4629                 case D3DTFP_POINT: value = WINED3DTEXF_POINT; break;
4630                 case 0: /* Unchecked */
4631                 case D3DTFP_LINEAR: value = WINED3DTEXF_LINEAR; break;
4632                 default:
4633                     ERR("Unexpected mipfilter value %d\n", State);
4634                     value = WINED3DTEXF_NONE;
4635             }
4636             hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
4637                                                 Stage,
4638                                                 WINED3DSAMP_MIPFILTER,
4639                                                 value);
4640             break;
4641         }
4642
4643         /* Minfilter is a sampler state too, equal values */
4644         case D3DTSS_MINFILTER:
4645             hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
4646                                                 Stage,
4647                                                 WINED3DSAMP_MINFILTER,
4648                                                 State);
4649             break;
4650
4651         /* Magfilter has slightly different values */
4652         case D3DTSS_MAGFILTER:
4653         {
4654             WINED3DTEXTUREFILTERTYPE wined3dfilter;
4655             switch((D3DTEXTUREMAGFILTER) State)
4656             {
4657                 case D3DTFG_POINT:          wined3dfilter = WINED3DTEXF_POINT;          break;
4658                 case D3DTFG_LINEAR:         wined3dfilter = WINED3DTEXF_LINEAR;         break;
4659                 case D3DTFG_FLATCUBIC:      wined3dfilter = WINED3DTEXF_FLATCUBIC;      break;
4660                 case D3DTFG_GAUSSIANCUBIC:  wined3dfilter = WINED3DTEXF_GAUSSIANCUBIC;  break;
4661                 case D3DTFG_ANISOTROPIC:    wined3dfilter = WINED3DTEXF_ANISOTROPIC;    break;
4662                 default:
4663                     ERR("Unexpected d3d7 mag filter type %d\n", State);
4664                     wined3dfilter = WINED3DTEXF_POINT;
4665             }
4666             hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
4667                                                 Stage,
4668                                                 WINED3DSAMP_MAGFILTER,
4669                                                 wined3dfilter);
4670             break;
4671         }
4672
4673         case D3DTSS_ADDRESS:
4674                    IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
4675                                                   Stage,
4676                                                   WINED3DSAMP_ADDRESSV,
4677                                                   State);
4678             /* Drop through */
4679         case D3DTSS_ADDRESSU:
4680             hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
4681                                                 Stage,
4682                                                 WINED3DSAMP_ADDRESSU,
4683                                                 State);
4684             break;
4685
4686         case D3DTSS_ADDRESSV:
4687             hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
4688                                                 Stage,
4689                                                 WINED3DSAMP_ADDRESSV,
4690                                                 State);
4691             break;
4692
4693         default:
4694             hr = IWineD3DDevice_SetTextureStageState(This->wineD3DDevice,
4695                                                      Stage,
4696                                                      TexStageStateType,
4697                                                      State);
4698             break;
4699     }
4700     LeaveCriticalSection(&ddraw_cs);
4701     return hr;
4702 }
4703
4704 static HRESULT WINAPI
4705 Thunk_IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
4706                                                  DWORD Stage,
4707                                                  D3DTEXTURESTAGESTATETYPE TexStageStateType,
4708                                                  DWORD State)
4709 {
4710     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4711     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, Stage, TexStageStateType, State);
4712     return IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
4713                                                  Stage,
4714                                                  TexStageStateType,
4715                                                  State);
4716 }
4717
4718 /*****************************************************************************
4719  * IDirect3DDevice7::ValidateDevice
4720  *
4721  * SDK: "Reports the device's ability to render the currently set
4722  * texture-blending operations in a single pass". Whatever that means
4723  * exactly...
4724  *
4725  * Version 3 and 7
4726  *
4727  * Params:
4728  *  NumPasses: Address to write the number of necessary passes for the
4729  *             desired effect to.
4730  *
4731  * Returns:
4732  *  D3D_OK on success
4733  *  See IWineD3DDevice::ValidateDevice for more details
4734  *
4735  *****************************************************************************/
4736 static HRESULT WINAPI
4737 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
4738                                      DWORD *NumPasses)
4739 {
4740     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4741     HRESULT hr;
4742     TRACE("(%p)->(%p): Relay\n", This, NumPasses);
4743
4744     EnterCriticalSection(&ddraw_cs);
4745     hr = IWineD3DDevice_ValidateDevice(This->wineD3DDevice, NumPasses);
4746     LeaveCriticalSection(&ddraw_cs);
4747     return hr;
4748 }
4749
4750 static HRESULT WINAPI
4751 Thunk_IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface,
4752                                            DWORD *Passes)
4753 {
4754     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4755     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Passes);
4756     return IDirect3DDevice7_ValidateDevice(ICOM_INTERFACE(This, IDirect3DDevice7),
4757                                            Passes);
4758 }
4759
4760 /*****************************************************************************
4761  * IDirect3DDevice7::Clear
4762  *
4763  * Fills the render target, the z buffer and the stencil buffer with a
4764  * clear color / value
4765  *
4766  * Version 7 only
4767  *
4768  * Params:
4769  *  Count: Number of rectangles in Rects must be 0 if Rects is NULL
4770  *  Rects: Rectangles to clear. If NULL, the whole surface is cleared
4771  *  Flags: Some flags, as usual
4772  *  Color: Clear color for the render target
4773  *  Z: Clear value for the Z buffer
4774  *  Stencil: Clear value to store in each stencil buffer entry
4775  *
4776  * Returns:
4777  *  D3D_OK on success
4778  *  For details, see IWineD3DDevice::Clear
4779  *
4780  *****************************************************************************/
4781 static HRESULT WINAPI
4782 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
4783                             DWORD Count,
4784                             D3DRECT *Rects,
4785                             DWORD Flags,
4786                             D3DCOLOR Color,
4787                             D3DVALUE Z,
4788                             DWORD Stencil)
4789 {
4790     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4791     HRESULT hr;
4792     TRACE("(%p)->(%08x,%p,%08x,%08x,%f,%08x): Relay\n", This, Count, Rects, Flags, Color, Z, Stencil);
4793
4794     /* Note; D3DRECT is compatible with WINED3DRECT */
4795     EnterCriticalSection(&ddraw_cs);
4796     hr = IWineD3DDevice_Clear(This->wineD3DDevice, Count, (WINED3DRECT*) Rects, Flags, Color, Z, Stencil);
4797     LeaveCriticalSection(&ddraw_cs);
4798     return hr;
4799 }
4800
4801 /*****************************************************************************
4802  * IDirect3DDevice7::SetViewport
4803  *
4804  * Sets the current viewport.
4805  *
4806  * Version 7 only, but IDirect3DViewport uses this call for older
4807  * versions
4808  *
4809  * Params:
4810  *  Data: The new viewport to set
4811  *
4812  * Returns:
4813  *  D3D_OK on success
4814  *  DDERR_INVALIDPARAMS if Data is NULL
4815  *  For more details, see IWineDDDevice::SetViewport
4816  *
4817  *****************************************************************************/
4818 static HRESULT WINAPI
4819 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
4820                                   D3DVIEWPORT7 *Data)
4821 {
4822     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4823     HRESULT hr;
4824     TRACE("(%p)->(%p) Relay!\n", This, Data);
4825
4826     if(!Data)
4827         return DDERR_INVALIDPARAMS;
4828
4829     /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
4830     EnterCriticalSection(&ddraw_cs);
4831     hr = IWineD3DDevice_SetViewport(This->wineD3DDevice,
4832                                     (WINED3DVIEWPORT*) Data);
4833     LeaveCriticalSection(&ddraw_cs);
4834     return hr;
4835 }
4836
4837 /*****************************************************************************
4838  * IDirect3DDevice::GetViewport
4839  *
4840  * Returns the current viewport
4841  *
4842  * Version 7
4843  *
4844  * Params:
4845  *  Data: D3D7Viewport structure to write the viewport information to
4846  *
4847  * Returns:
4848  *  D3D_OK on success
4849  *  DDERR_INVALIDPARAMS if Data is NULL
4850  *  For more details, see IWineD3DDevice::GetViewport
4851  *
4852  *****************************************************************************/
4853 static HRESULT WINAPI
4854 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
4855                                   D3DVIEWPORT7 *Data)
4856 {
4857     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4858     HRESULT hr;
4859     TRACE("(%p)->(%p) Relay!\n", This, Data);
4860
4861     if(!Data)
4862         return DDERR_INVALIDPARAMS;
4863
4864     /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
4865     EnterCriticalSection(&ddraw_cs);
4866     hr = IWineD3DDevice_GetViewport(This->wineD3DDevice,
4867                                     (WINED3DVIEWPORT*) Data);
4868
4869     LeaveCriticalSection(&ddraw_cs);
4870     return hr_ddraw_from_wined3d(hr);
4871 }
4872
4873 /*****************************************************************************
4874  * IDirect3DDevice7::SetMaterial
4875  *
4876  * Sets the Material
4877  *
4878  * Version 7
4879  *
4880  * Params:
4881  *  Mat: The material to set
4882  *
4883  * Returns:
4884  *  D3D_OK on success
4885  *  DDERR_INVALIDPARAMS if Mat is NULL.
4886  *  For more details, see IWineD3DDevice::SetMaterial
4887  *
4888  *****************************************************************************/
4889 static HRESULT WINAPI
4890 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
4891                                   D3DMATERIAL7 *Mat)
4892 {
4893     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4894     HRESULT hr;
4895     TRACE("(%p)->(%p): Relay!\n", This, Mat);
4896
4897     /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
4898     EnterCriticalSection(&ddraw_cs);
4899     hr = IWineD3DDevice_SetMaterial(This->wineD3DDevice,
4900                                     (WINED3DMATERIAL*) Mat);
4901     LeaveCriticalSection(&ddraw_cs);
4902     return hr_ddraw_from_wined3d(hr);
4903 }
4904
4905 /*****************************************************************************
4906  * IDirect3DDevice7::GetMaterial
4907  *
4908  * Returns the current material
4909  *
4910  * Version 7
4911  *
4912  * Params:
4913  *  Mat: D3DMATERIAL7 structure to write the material parameters to
4914  *
4915  * Returns:
4916  *  D3D_OK on success
4917  *  DDERR_INVALIDPARAMS if Mat is NULL
4918  *  For more details, see IWineD3DDevice::GetMaterial
4919  *
4920  *****************************************************************************/
4921 static HRESULT WINAPI
4922 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
4923                                   D3DMATERIAL7 *Mat)
4924 {
4925     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4926     HRESULT hr;
4927     TRACE("(%p)->(%p): Relay!\n", This, Mat);
4928
4929     EnterCriticalSection(&ddraw_cs);
4930     /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */ 
4931     hr = IWineD3DDevice_GetMaterial(This->wineD3DDevice,
4932                                     (WINED3DMATERIAL*) Mat);
4933     LeaveCriticalSection(&ddraw_cs);
4934     return hr_ddraw_from_wined3d(hr);
4935 }
4936
4937 /*****************************************************************************
4938  * IDirect3DDevice7::SetLight
4939  *
4940  * Assigns a light to a light index, but doesn't activate it yet.
4941  *
4942  * Version 7, IDirect3DLight uses this method for older versions
4943  *
4944  * Params:
4945  *  LightIndex: The index of the new light
4946  *  Light: A D3DLIGHT7 structure describing the light
4947  *
4948  * Returns:
4949  *  D3D_OK on success
4950  *  For more details, see IWineD3DDevice::SetLight
4951  *
4952  *****************************************************************************/
4953 static HRESULT WINAPI
4954 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
4955                                DWORD LightIndex,
4956                                D3DLIGHT7 *Light)
4957 {
4958     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4959     HRESULT hr;
4960     TRACE("(%p)->(%08x,%p): Relay!\n", This, LightIndex, Light);
4961
4962     EnterCriticalSection(&ddraw_cs);
4963     /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
4964     hr = IWineD3DDevice_SetLight(This->wineD3DDevice,
4965                                  LightIndex,
4966                                  (WINED3DLIGHT*) Light);
4967     LeaveCriticalSection(&ddraw_cs);
4968     return hr_ddraw_from_wined3d(hr);
4969 }
4970
4971 /*****************************************************************************
4972  * IDirect3DDevice7::GetLight
4973  *
4974  * Returns the light assigned to a light index
4975  *
4976  * Params:
4977  *  Light: Structure to write the light information to
4978  *
4979  * Returns:
4980  *  D3D_OK on success
4981  *  DDERR_INVALIDPARAMS if Light is NULL
4982  *  For details, see IWineD3DDevice::GetLight
4983  *
4984  *****************************************************************************/
4985 static HRESULT WINAPI
4986 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
4987                                DWORD LightIndex,
4988                                D3DLIGHT7 *Light)
4989 {
4990     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4991     HRESULT rc;
4992     TRACE("(%p)->(%08x,%p): Relay!\n", This, LightIndex, Light);
4993
4994     EnterCriticalSection(&ddraw_cs);
4995     /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
4996     rc =  IWineD3DDevice_GetLight(This->wineD3DDevice,
4997                                   LightIndex,
4998                                   (WINED3DLIGHT*) Light);
4999
5000     /* Translate the result. WineD3D returns other values than D3D7 */
5001     LeaveCriticalSection(&ddraw_cs);
5002     return hr_ddraw_from_wined3d(rc);
5003 }
5004
5005 /*****************************************************************************
5006  * IDirect3DDevice7::BeginStateBlock
5007  *
5008  * Begins recording to a stateblock
5009  *
5010  * Version 7
5011  *
5012  * Returns:
5013  *  D3D_OK on success
5014  *  For details see IWineD3DDevice::BeginStateBlock
5015  *
5016  *****************************************************************************/
5017 static HRESULT WINAPI
5018 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5019 {
5020     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5021     HRESULT hr;
5022     TRACE("(%p)->(): Relay!\n", This);
5023
5024     EnterCriticalSection(&ddraw_cs);
5025     hr = IWineD3DDevice_BeginStateBlock(This->wineD3DDevice);
5026     LeaveCriticalSection(&ddraw_cs);
5027     return hr_ddraw_from_wined3d(hr);
5028 }
5029
5030 /*****************************************************************************
5031  * IDirect3DDevice7::EndStateBlock
5032  *
5033  * Stops recording to a state block and returns the created stateblock
5034  * handle.
5035  *
5036  * Version 7
5037  *
5038  * Params:
5039  *  BlockHandle: Address to store the stateblock's handle to
5040  *
5041  * Returns:
5042  *  D3D_OK on success
5043  *  DDERR_INVALIDPARAMS if BlockHandle is NULL
5044  *  See IWineD3DDevice::EndStateBlock for more details
5045  *
5046  *****************************************************************************/
5047 static HRESULT WINAPI
5048 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5049                                     DWORD *BlockHandle)
5050 {
5051     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5052     HRESULT hr;
5053     TRACE("(%p)->(%p): Relay!\n", This, BlockHandle);
5054
5055     if(!BlockHandle)
5056     {
5057         WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5058         return DDERR_INVALIDPARAMS;
5059     }
5060
5061     EnterCriticalSection(&ddraw_cs);
5062     *BlockHandle = IDirect3DDeviceImpl_CreateHandle(This);
5063     if(!*BlockHandle)
5064     {
5065         ERR("Cannot get a handle number for the stateblock\n");
5066         LeaveCriticalSection(&ddraw_cs);
5067         return DDERR_OUTOFMEMORY;
5068     }
5069     This->Handles[*BlockHandle - 1].type = DDrawHandle_StateBlock;
5070     hr = IWineD3DDevice_EndStateBlock(This->wineD3DDevice,
5071                                       (IWineD3DStateBlock **) &This->Handles[*BlockHandle - 1].ptr);
5072     LeaveCriticalSection(&ddraw_cs);
5073     return hr_ddraw_from_wined3d(hr);
5074 }
5075
5076 /*****************************************************************************
5077  * IDirect3DDevice7::PreLoad
5078  *
5079  * Allows the app to signal that a texture will be used soon, to allow
5080  * the Direct3DDevice to load it to the video card in the meantime.
5081  *
5082  * Version 7
5083  *
5084  * Params:
5085  *  Texture: The texture to preload
5086  *
5087  * Returns:
5088  *  D3D_OK on success
5089  *  DDERR_INVALIDPARAMS if Texture is NULL
5090  *  See IWineD3DSurface::PreLoad for details
5091  *
5092  *****************************************************************************/
5093 static HRESULT WINAPI
5094 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5095                               IDirectDrawSurface7 *Texture)
5096 {
5097     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5098     IDirectDrawSurfaceImpl *surf = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, Texture);
5099
5100     TRACE("(%p)->(%p): Relay!\n", This, surf);
5101
5102     if(!Texture)
5103         return DDERR_INVALIDPARAMS;
5104
5105     EnterCriticalSection(&ddraw_cs);
5106     IWineD3DSurface_PreLoad(surf->WineD3DSurface);
5107     LeaveCriticalSection(&ddraw_cs);
5108     return D3D_OK;
5109 }
5110
5111 /*****************************************************************************
5112  * IDirect3DDevice7::ApplyStateBlock
5113  *
5114  * Activates the state stored in a state block handle.
5115  *
5116  * Params:
5117  *  BlockHandle: The stateblock handle to activate
5118  *
5119  * Returns:
5120  *  D3D_OK on success
5121  *  D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5122  *
5123  *****************************************************************************/
5124 static HRESULT WINAPI
5125 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5126                                       DWORD BlockHandle)
5127 {
5128     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5129     HRESULT hr;
5130     TRACE("(%p)->(%08x): Relay!\n", This, BlockHandle);
5131
5132     EnterCriticalSection(&ddraw_cs);
5133     if(!BlockHandle || BlockHandle > This->numHandles)
5134     {
5135         WARN("Out of range handle %d, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5136         LeaveCriticalSection(&ddraw_cs);
5137         return D3DERR_INVALIDSTATEBLOCK;
5138     }
5139     if(This->Handles[BlockHandle - 1].type != DDrawHandle_StateBlock)
5140     {
5141         WARN("Handle %d is not a stateblock, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5142         LeaveCriticalSection(&ddraw_cs);
5143         return D3DERR_INVALIDSTATEBLOCK;
5144     }
5145
5146     hr = IWineD3DStateBlock_Apply((IWineD3DStateBlock *) This->Handles[BlockHandle - 1].ptr);
5147     LeaveCriticalSection(&ddraw_cs);
5148     return hr_ddraw_from_wined3d(hr);
5149 }
5150
5151 /*****************************************************************************
5152  * IDirect3DDevice7::CaptureStateBlock
5153  *
5154  * Updates a stateblock's values to the values currently set for the device
5155  *
5156  * Version 7
5157  *
5158  * Params:
5159  *  BlockHandle: Stateblock to update
5160  *
5161  * Returns:
5162  *  D3D_OK on success
5163  *  D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5164  *  See IWineD3DDevice::CaptureStateBlock for more details
5165  *
5166  *****************************************************************************/
5167 static HRESULT WINAPI
5168 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5169                                         DWORD BlockHandle)
5170 {
5171     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5172     HRESULT hr;
5173     TRACE("(%p)->(%08x): Relay!\n", This, BlockHandle);
5174
5175     EnterCriticalSection(&ddraw_cs);
5176     if(BlockHandle == 0 || BlockHandle > This->numHandles)
5177     {
5178         WARN("Out of range handle %d, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5179         LeaveCriticalSection(&ddraw_cs);
5180         return D3DERR_INVALIDSTATEBLOCK;
5181     }
5182     if(This->Handles[BlockHandle - 1].type != DDrawHandle_StateBlock)
5183     {
5184         WARN("Handle %d is not a stateblock, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5185         LeaveCriticalSection(&ddraw_cs);
5186         return D3DERR_INVALIDSTATEBLOCK;
5187     }
5188
5189     hr = IWineD3DStateBlock_Capture((IWineD3DStateBlock *) This->Handles[BlockHandle - 1].ptr);
5190     LeaveCriticalSection(&ddraw_cs);
5191     return hr_ddraw_from_wined3d(hr);
5192 }
5193
5194 /*****************************************************************************
5195  * IDirect3DDevice7::DeleteStateBlock
5196  *
5197  * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5198  *
5199  * Version 7
5200  *
5201  * Params:
5202  *  BlockHandle: Stateblock handle to delete
5203  *
5204  * Returns:
5205  *  D3D_OK on success
5206  *  D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5207  *
5208  *****************************************************************************/
5209 static HRESULT WINAPI
5210 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5211                                        DWORD BlockHandle)
5212 {
5213     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5214     ULONG ref;
5215     TRACE("(%p)->(%08x): Relay!\n", This, BlockHandle);
5216
5217     EnterCriticalSection(&ddraw_cs);
5218     if(BlockHandle == 0 || BlockHandle > This->numHandles)
5219     {
5220         WARN("Out of range handle %d, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5221         LeaveCriticalSection(&ddraw_cs);
5222         return D3DERR_INVALIDSTATEBLOCK;
5223     }
5224     if(This->Handles[BlockHandle - 1].type != DDrawHandle_StateBlock)
5225     {
5226         WARN("Handle %d is not a stateblock, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5227         LeaveCriticalSection(&ddraw_cs);
5228         return D3DERR_INVALIDSTATEBLOCK;
5229     }
5230
5231     ref = IWineD3DStateBlock_Release((IWineD3DStateBlock *) This->Handles[BlockHandle - 1].ptr);
5232     if(ref)
5233     {
5234         ERR("Something is still holding the stateblock %p(Handle %d). Ref = %d\n", This->Handles[BlockHandle - 1].ptr, BlockHandle, ref);
5235     }
5236     This->Handles[BlockHandle - 1].ptr = NULL;
5237     This->Handles[BlockHandle - 1].type = DDrawHandle_Unknown;
5238
5239     LeaveCriticalSection(&ddraw_cs);
5240     return D3D_OK;
5241 }
5242
5243 /*****************************************************************************
5244  * IDirect3DDevice7::CreateStateBlock
5245  *
5246  * Creates a new state block handle.
5247  *
5248  * Version 7
5249  *
5250  * Params:
5251  *  Type: The state block type
5252  *  BlockHandle: Address to write the created handle to
5253  *
5254  * Returns:
5255  *   D3D_OK on success
5256  *   DDERR_INVALIDPARAMS if BlockHandle is NULL
5257  *
5258  *****************************************************************************/
5259 static HRESULT WINAPI
5260 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5261                                        D3DSTATEBLOCKTYPE Type,
5262                                        DWORD *BlockHandle)
5263 {
5264     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5265     HRESULT hr;
5266     TRACE("(%p)->(%08x,%p)!\n", This, Type, BlockHandle);
5267
5268     if(!BlockHandle)
5269     {
5270         WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5271         return DDERR_INVALIDPARAMS;
5272     }
5273     if(Type != D3DSBT_ALL         && Type != D3DSBT_PIXELSTATE &&
5274        Type != D3DSBT_VERTEXSTATE                              ) {
5275         WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5276         return DDERR_INVALIDPARAMS;
5277     }
5278
5279     EnterCriticalSection(&ddraw_cs);
5280     *BlockHandle = IDirect3DDeviceImpl_CreateHandle(This);
5281     if(!*BlockHandle)
5282     {
5283         ERR("Cannot get a handle number for the stateblock\n");
5284         LeaveCriticalSection(&ddraw_cs);
5285         return DDERR_OUTOFMEMORY;
5286     }
5287     This->Handles[*BlockHandle - 1].type = DDrawHandle_StateBlock;
5288
5289     /* The D3DSTATEBLOCKTYPE enum is fine here */
5290     hr = IWineD3DDevice_CreateStateBlock(This->wineD3DDevice,
5291                                          Type,
5292                                          (IWineD3DStateBlock **) &This->Handles[*BlockHandle - 1].ptr,
5293                                          NULL /* Parent, hope that works */);
5294     LeaveCriticalSection(&ddraw_cs);
5295     return hr_ddraw_from_wined3d(hr);
5296 }
5297
5298 /*****************************************************************************
5299  * IDirect3DDevice7::Load
5300  *
5301  * Loads a rectangular area from the source into the destination texture.
5302  * It can also copy the source to the faces of a cubic environment map
5303  *
5304  * Version 7
5305  *
5306  * Params:
5307  *  DestTex: Destination texture
5308  *  DestPoint: Point in the destination where the source image should be
5309  *             written to
5310  *  SrcTex: Source texture
5311  *  SrcRect: Source rectangle
5312  *  Flags: Some flags
5313  *
5314  * Returns:
5315  *  D3D_OK on success
5316  *  DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL
5317  *  See IDirect3DTexture2::Load for details
5318  *
5319  *****************************************************************************/
5320 static HRESULT WINAPI
5321 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
5322                            IDirectDrawSurface7 *DestTex,
5323                            POINT *DestPoint,
5324                            IDirectDrawSurface7 *SrcTex,
5325                            RECT *SrcRect,
5326                            DWORD Flags)
5327 {
5328     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5329     IDirectDrawSurfaceImpl *dest = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, DestTex);
5330     IDirectDrawSurfaceImpl *src = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, SrcTex);
5331     FIXME("(%p)->(%p,%p,%p,%p,%08x): Partially Implemented!\n", This, dest, DestPoint, src, SrcRect, Flags);
5332
5333     if( (!src) || (!dest) )
5334         return DDERR_INVALIDPARAMS;
5335
5336     IDirect3DTexture2_Load(ICOM_INTERFACE(dest, IDirect3DTexture2),
5337                            ICOM_INTERFACE(src, IDirect3DTexture2));
5338     return D3D_OK;
5339 }
5340
5341 /*****************************************************************************
5342  * IDirect3DDevice7::LightEnable
5343  *
5344  * Enables or disables a light
5345  *
5346  * Version 7, IDirect3DLight uses this method too.
5347  *
5348  * Params:
5349  *  LightIndex: The index of the light to enable / disable
5350  *  Enable: Enable or disable the light
5351  *
5352  * Returns:
5353  *  D3D_OK on success
5354  *  For more details, see IWineD3DDevice::SetLightEnable
5355  *
5356  *****************************************************************************/
5357 static HRESULT WINAPI
5358 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
5359                                   DWORD LightIndex,
5360                                   BOOL Enable)
5361 {
5362     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5363     HRESULT hr;
5364     TRACE("(%p)->(%08x,%d): Relay!\n", This, LightIndex, Enable);
5365
5366     EnterCriticalSection(&ddraw_cs);
5367     hr = IWineD3DDevice_SetLightEnable(This->wineD3DDevice, LightIndex, Enable);
5368     LeaveCriticalSection(&ddraw_cs);
5369     return hr_ddraw_from_wined3d(hr);
5370 }
5371
5372 /*****************************************************************************
5373  * IDirect3DDevice7::GetLightEnable
5374  *
5375  * Retrieves if the light with the given index is enabled or not
5376  *
5377  * Version 7
5378  *
5379  * Params:
5380  *  LightIndex: Index of desired light
5381  *  Enable: Pointer to a BOOL which contains the result
5382  *
5383  * Returns:
5384  *  D3D_OK on success
5385  *  DDERR_INVALIDPARAMS if Enable is NULL
5386  *  See IWineD3DDevice::GetLightEnable for more details
5387  *
5388  *****************************************************************************/
5389 static HRESULT WINAPI
5390 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
5391                                      DWORD LightIndex,
5392                                      BOOL* Enable)
5393 {
5394     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5395     HRESULT hr;
5396     TRACE("(%p)->(%08x,%p): Relay\n", This, LightIndex, Enable);
5397
5398     if(!Enable)
5399         return DDERR_INVALIDPARAMS;
5400
5401     EnterCriticalSection(&ddraw_cs);
5402     hr = IWineD3DDevice_GetLightEnable(This->wineD3DDevice, LightIndex, Enable);
5403     LeaveCriticalSection(&ddraw_cs);
5404     return hr_ddraw_from_wined3d(hr);
5405 }
5406
5407 /*****************************************************************************
5408  * IDirect3DDevice7::SetClipPlane
5409  *
5410  * Sets custom clipping plane
5411  *
5412  * Version 7
5413  *
5414  * Params:
5415  *  Index: The index of the clipping plane
5416  *  PlaneEquation: An equation defining the clipping plane
5417  *
5418  * Returns:
5419  *  D3D_OK on success
5420  *  DDERR_INVALIDPARAMS if PlaneEquation is NULL
5421  *  See IWineD3DDevice::SetClipPlane for more details
5422  *
5423  *****************************************************************************/
5424 static HRESULT WINAPI
5425 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
5426                                    DWORD Index,
5427                                    D3DVALUE* PlaneEquation)
5428 {
5429     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5430     HRESULT hr;
5431     TRACE("(%p)->(%08x,%p): Relay!\n", This, Index, PlaneEquation);
5432
5433     if(!PlaneEquation)
5434         return DDERR_INVALIDPARAMS;
5435
5436     EnterCriticalSection(&ddraw_cs);
5437     hr = IWineD3DDevice_SetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
5438     LeaveCriticalSection(&ddraw_cs);
5439     return hr;
5440 }
5441
5442 /*****************************************************************************
5443  * IDirect3DDevice7::GetClipPlane
5444  *
5445  * Returns the clipping plane with a specific index
5446  *
5447  * Params:
5448  *  Index: The index of the desired plane
5449  *  PlaneEquation: Address to store the plane equation to
5450  *
5451  * Returns:
5452  *  D3D_OK on success
5453  *  DDERR_INVALIDPARAMS if PlaneEquation is NULL
5454  *  See IWineD3DDevice::GetClipPlane for more details
5455  *
5456  *****************************************************************************/
5457 static HRESULT WINAPI
5458 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
5459                                    DWORD Index,
5460                                    D3DVALUE* PlaneEquation)
5461 {
5462     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5463     HRESULT hr;
5464     TRACE("(%p)->(%d,%p): Relay!\n", This, Index, PlaneEquation);
5465
5466     if(!PlaneEquation)
5467         return DDERR_INVALIDPARAMS;
5468
5469     EnterCriticalSection(&ddraw_cs);
5470     hr = IWineD3DDevice_GetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
5471     LeaveCriticalSection(&ddraw_cs);
5472     return hr;
5473 }
5474
5475 /*****************************************************************************
5476  * IDirect3DDevice7::GetInfo
5477  *
5478  * Retrieves some information about the device. The DirectX sdk says that
5479  * this version returns S_FALSE for all retail builds of DirectX, that's what
5480  * this implementation does.
5481  *
5482  * Params:
5483  *  DevInfoID: Information type requested
5484  *  DevInfoStruct: Pointer to a structure to store the info to
5485  *  Size: Size of the structure
5486  *
5487  * Returns:
5488  *  S_FALSE, because it's a non-debug driver
5489  *
5490  *****************************************************************************/
5491 static HRESULT WINAPI
5492 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
5493                               DWORD DevInfoID,
5494                               void *DevInfoStruct,
5495                               DWORD Size)
5496 {
5497     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5498     TRACE("(%p)->(%08x,%p,%08x)\n", This, DevInfoID, DevInfoStruct, Size);
5499
5500     if (TRACE_ON(d3d7))
5501     {
5502         TRACE(" info requested : ");
5503         switch (DevInfoID)
5504         {
5505             case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
5506             case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
5507             case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
5508             default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
5509         }
5510     }
5511
5512     return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
5513 }
5514
5515 const IDirect3DDevice7Vtbl IDirect3DDevice7_Vtbl =
5516 {
5517     /*** IUnknown Methods ***/
5518     IDirect3DDeviceImpl_7_QueryInterface,
5519     IDirect3DDeviceImpl_7_AddRef,
5520     IDirect3DDeviceImpl_7_Release,
5521     /*** IDirect3DDevice7 ***/
5522     IDirect3DDeviceImpl_7_GetCaps,
5523     IDirect3DDeviceImpl_7_EnumTextureFormats,
5524     IDirect3DDeviceImpl_7_BeginScene,
5525     IDirect3DDeviceImpl_7_EndScene,
5526     IDirect3DDeviceImpl_7_GetDirect3D,
5527     IDirect3DDeviceImpl_7_SetRenderTarget,
5528     IDirect3DDeviceImpl_7_GetRenderTarget,
5529     IDirect3DDeviceImpl_7_Clear,
5530     IDirect3DDeviceImpl_7_SetTransform,
5531     IDirect3DDeviceImpl_7_GetTransform,
5532     IDirect3DDeviceImpl_7_SetViewport,
5533     IDirect3DDeviceImpl_7_MultiplyTransform,
5534     IDirect3DDeviceImpl_7_GetViewport,
5535     IDirect3DDeviceImpl_7_SetMaterial,
5536     IDirect3DDeviceImpl_7_GetMaterial,
5537     IDirect3DDeviceImpl_7_SetLight,
5538     IDirect3DDeviceImpl_7_GetLight,
5539     IDirect3DDeviceImpl_7_SetRenderState,
5540     IDirect3DDeviceImpl_7_GetRenderState,
5541     IDirect3DDeviceImpl_7_BeginStateBlock,
5542     IDirect3DDeviceImpl_7_EndStateBlock,
5543     IDirect3DDeviceImpl_7_PreLoad,
5544     IDirect3DDeviceImpl_7_DrawPrimitive,
5545     IDirect3DDeviceImpl_7_DrawIndexedPrimitive,
5546     IDirect3DDeviceImpl_7_SetClipStatus,
5547     IDirect3DDeviceImpl_7_GetClipStatus,
5548     IDirect3DDeviceImpl_7_DrawPrimitiveStrided,
5549     IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided,
5550     IDirect3DDeviceImpl_7_DrawPrimitiveVB,
5551     IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB,
5552     IDirect3DDeviceImpl_7_ComputeSphereVisibility,
5553     IDirect3DDeviceImpl_7_GetTexture,
5554     IDirect3DDeviceImpl_7_SetTexture,
5555     IDirect3DDeviceImpl_7_GetTextureStageState,
5556     IDirect3DDeviceImpl_7_SetTextureStageState,
5557     IDirect3DDeviceImpl_7_ValidateDevice,
5558     IDirect3DDeviceImpl_7_ApplyStateBlock,
5559     IDirect3DDeviceImpl_7_CaptureStateBlock,
5560     IDirect3DDeviceImpl_7_DeleteStateBlock,
5561     IDirect3DDeviceImpl_7_CreateStateBlock,
5562     IDirect3DDeviceImpl_7_Load,
5563     IDirect3DDeviceImpl_7_LightEnable,
5564     IDirect3DDeviceImpl_7_GetLightEnable,
5565     IDirect3DDeviceImpl_7_SetClipPlane,
5566     IDirect3DDeviceImpl_7_GetClipPlane,
5567     IDirect3DDeviceImpl_7_GetInfo
5568 };
5569
5570 const IDirect3DDevice3Vtbl IDirect3DDevice3_Vtbl =
5571 {
5572     /*** IUnknown Methods ***/
5573     Thunk_IDirect3DDeviceImpl_3_QueryInterface,
5574     Thunk_IDirect3DDeviceImpl_3_AddRef,
5575     Thunk_IDirect3DDeviceImpl_3_Release,
5576     /*** IDirect3DDevice3 ***/
5577     IDirect3DDeviceImpl_3_GetCaps,
5578     IDirect3DDeviceImpl_3_GetStats,
5579     IDirect3DDeviceImpl_3_AddViewport,
5580     IDirect3DDeviceImpl_3_DeleteViewport,
5581     IDirect3DDeviceImpl_3_NextViewport,
5582     Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
5583     Thunk_IDirect3DDeviceImpl_3_BeginScene,
5584     Thunk_IDirect3DDeviceImpl_3_EndScene,
5585     Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
5586     IDirect3DDeviceImpl_3_SetCurrentViewport,
5587     IDirect3DDeviceImpl_3_GetCurrentViewport,
5588     Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
5589     Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
5590     IDirect3DDeviceImpl_3_Begin,
5591     IDirect3DDeviceImpl_3_BeginIndexed,
5592     IDirect3DDeviceImpl_3_Vertex,
5593     IDirect3DDeviceImpl_3_Index,
5594     IDirect3DDeviceImpl_3_End,
5595     Thunk_IDirect3DDeviceImpl_3_GetRenderState,
5596     Thunk_IDirect3DDeviceImpl_3_SetRenderState,
5597     IDirect3DDeviceImpl_3_GetLightState,
5598     IDirect3DDeviceImpl_3_SetLightState,
5599     Thunk_IDirect3DDeviceImpl_3_SetTransform,
5600     Thunk_IDirect3DDeviceImpl_3_GetTransform,
5601     Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
5602     Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
5603     Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
5604     Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
5605     Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
5606     Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
5607     Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
5608     Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
5609     Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
5610     Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
5611     Thunk_IDirect3DDeviceImpl_3_GetTexture,
5612     Thunk_IDirect3DDeviceImpl_3_SetTexture,
5613     Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
5614     Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
5615     Thunk_IDirect3DDeviceImpl_3_ValidateDevice
5616 };
5617
5618 const IDirect3DDevice2Vtbl IDirect3DDevice2_Vtbl =
5619 {
5620     /*** IUnknown Methods ***/
5621     Thunk_IDirect3DDeviceImpl_2_QueryInterface,
5622     Thunk_IDirect3DDeviceImpl_2_AddRef,
5623     Thunk_IDirect3DDeviceImpl_2_Release,
5624     /*** IDirect3DDevice2 ***/
5625     Thunk_IDirect3DDeviceImpl_2_GetCaps,
5626     IDirect3DDeviceImpl_2_SwapTextureHandles,
5627     Thunk_IDirect3DDeviceImpl_2_GetStats,
5628     Thunk_IDirect3DDeviceImpl_2_AddViewport,
5629     Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
5630     Thunk_IDirect3DDeviceImpl_2_NextViewport,
5631     IDirect3DDeviceImpl_2_EnumTextureFormats,
5632     Thunk_IDirect3DDeviceImpl_2_BeginScene,
5633     Thunk_IDirect3DDeviceImpl_2_EndScene,
5634     Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
5635     Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
5636     Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
5637     Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
5638     Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
5639     Thunk_IDirect3DDeviceImpl_2_Begin,
5640     Thunk_IDirect3DDeviceImpl_2_BeginIndexed,
5641     Thunk_IDirect3DDeviceImpl_2_Vertex,
5642     Thunk_IDirect3DDeviceImpl_2_Index,
5643     Thunk_IDirect3DDeviceImpl_2_End,
5644     IDirect3DDeviceImpl_2_GetRenderState,
5645     IDirect3DDeviceImpl_2_SetRenderState,
5646     Thunk_IDirect3DDeviceImpl_2_GetLightState,
5647     Thunk_IDirect3DDeviceImpl_2_SetLightState,
5648     Thunk_IDirect3DDeviceImpl_2_SetTransform,
5649     Thunk_IDirect3DDeviceImpl_2_GetTransform,
5650     Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
5651     Thunk_IDirect3DDeviceImpl_2_DrawPrimitive,
5652     Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
5653     Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
5654     Thunk_IDirect3DDeviceImpl_2_GetClipStatus
5655 };
5656
5657 const IDirect3DDeviceVtbl IDirect3DDevice1_Vtbl =
5658 {
5659     /*** IUnknown Methods ***/
5660     Thunk_IDirect3DDeviceImpl_1_QueryInterface,
5661     Thunk_IDirect3DDeviceImpl_1_AddRef,
5662     Thunk_IDirect3DDeviceImpl_1_Release,
5663     /*** IDirect3DDevice1 ***/
5664     IDirect3DDeviceImpl_1_Initialize,
5665     Thunk_IDirect3DDeviceImpl_1_GetCaps,
5666     Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
5667     IDirect3DDeviceImpl_1_CreateExecuteBuffer,
5668     Thunk_IDirect3DDeviceImpl_1_GetStats,
5669     IDirect3DDeviceImpl_1_Execute,
5670     Thunk_IDirect3DDeviceImpl_1_AddViewport,
5671     Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
5672     Thunk_IDirect3DDeviceImpl_1_NextViewport,
5673     IDirect3DDeviceImpl_1_Pick,
5674     IDirect3DDeviceImpl_1_GetPickRecords,
5675     Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
5676     IDirect3DDeviceImpl_1_CreateMatrix,
5677     IDirect3DDeviceImpl_1_SetMatrix,
5678     IDirect3DDeviceImpl_1_GetMatrix,
5679     IDirect3DDeviceImpl_1_DeleteMatrix,
5680     Thunk_IDirect3DDeviceImpl_1_BeginScene,
5681     Thunk_IDirect3DDeviceImpl_1_EndScene,
5682     Thunk_IDirect3DDeviceImpl_1_GetDirect3D
5683 };
5684
5685 /*****************************************************************************
5686  * IDirect3DDeviceImpl_CreateHandle
5687  *
5688  * Not called from the VTable
5689  *
5690  * Some older interface versions operate with handles, which are basically
5691  * DWORDs which identify an interface, for example
5692  * IDirect3DDevice::SetRenderState with DIRECT3DRENDERSTATE_TEXTUREHANDLE
5693  *
5694  * Those handle could be just casts to the interface pointers or vice versa,
5695  * but that is not 64 bit safe and would mean blindly derefering a DWORD
5696  * passed by the app. Instead there is a dynamic array in the device which
5697  * keeps a DWORD to pointer information and a type for the handle.
5698  *
5699  * Basically this array only grows, when a handle is freed its pointer is
5700  * just set to NULL. There will be much more reads from the array than
5701  * insertion operations, so a dynamic array is fine.
5702  *
5703  * Params:
5704  *  This: D3DDevice implementation for which this handle should be created
5705  *
5706  * Returns:
5707  *  A free handle on success
5708  *  0 on failure
5709  *
5710  *****************************************************************************/
5711 DWORD
5712 IDirect3DDeviceImpl_CreateHandle(IDirect3DDeviceImpl *This)
5713 {
5714     DWORD i;
5715     struct HandleEntry *oldHandles = This->Handles;
5716
5717     TRACE("(%p)\n", This);
5718
5719     for(i = 0; i < This->numHandles; i++)
5720     {
5721         if(This->Handles[i].ptr == NULL &&
5722            This->Handles[i].type == DDrawHandle_Unknown)
5723         {
5724             TRACE("Reusing freed handle %d\n", i + 1);
5725             return i + 1;
5726         }
5727     }
5728
5729     TRACE("Growing the handle array\n");
5730
5731     This->numHandles++;
5732     This->Handles = HeapAlloc(GetProcessHeap(), 0, sizeof(struct HandleEntry) * This->numHandles);
5733     if(!This->Handles)
5734     {
5735         ERR("Out of memory\n");
5736         This->Handles = oldHandles;
5737         This->numHandles--;
5738         return 0;
5739     }
5740     if(oldHandles)
5741     {
5742         memcpy(This->Handles, oldHandles, (This->numHandles - 1) * sizeof(struct HandleEntry));
5743         HeapFree(GetProcessHeap(), 0, oldHandles);
5744     }
5745
5746     TRACE("Returning %d\n", This->numHandles);
5747     return This->numHandles;
5748 }
5749
5750 /*****************************************************************************
5751  * IDirect3DDeviceImpl_UpdateDepthStencil
5752  *
5753  * Checks the current render target for attached depth stencils and sets the
5754  * WineD3D depth stencil accordingly.
5755  *
5756  * Returns:
5757  *  The depth stencil state to set if creating the device
5758  *
5759  *****************************************************************************/
5760 WINED3DZBUFFERTYPE
5761 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
5762 {
5763     IDirectDrawSurface7 *depthStencil = NULL;
5764     IDirectDrawSurfaceImpl *dsi;
5765     static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
5766
5767     IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(This->target, IDirectDrawSurface7),
5768                                            &depthcaps,
5769                                            &depthStencil);
5770     if(!depthStencil)
5771     {
5772         TRACE("Setting wined3d depth stencil to NULL\n");
5773         IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
5774                                               NULL);
5775         return WINED3DZB_FALSE;
5776     }
5777
5778     dsi = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, depthStencil);
5779     TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->WineD3DSurface);
5780     IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
5781                                           dsi->WineD3DSurface);
5782
5783     IDirectDrawSurface7_Release(depthStencil);
5784     return WINED3DZB_TRUE;
5785 }