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