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