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