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