~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/ddraw/device.c

Version: ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  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 static inline void set_fpu_control_word(WORD fpucw)
 65 {
 66 #if defined(__i386__) && defined(__GNUC__)
 67     __asm__ volatile ("fldcw %0" : : "m" (fpucw));
 68 #elif defined(__i386__) && defined(_MSC_VER)
 69     __asm fldcw fpucw;
 70 #endif
 71 }
 72 
 73 static inline WORD d3d_fpu_setup(void)
 74 {
 75     WORD oldcw;
 76 
 77 #if defined(__i386__) && defined(__GNUC__)
 78     __asm__ volatile ("fnstcw %0" : "=m" (oldcw));
 79 #elif defined(__i386__) && defined(_MSC_VER)
 80     __asm fnstcw oldcw;
 81 #else
 82     static BOOL warned = FALSE;
 83     if(!warned)
 84     {
 85         FIXME("FPUPRESERVE not implemented for this platform / compiler\n");
 86         warned = TRUE;
 87     }
 88     return 0;
 89 #endif
 90 
 91     set_fpu_control_word(0x37f);
 92 
 93     return oldcw;
 94 }
 95 
 96 /*****************************************************************************
 97  * IUnknown Methods. Common for Version 1, 2, 3 and 7
 98  *****************************************************************************/
 99 
100 /*****************************************************************************
101  * IDirect3DDevice7::QueryInterface
102  *
103  * Used to query other interfaces from a Direct3DDevice interface.
104  * It can return interface pointers to all Direct3DDevice versions as well
105  * as IDirectDraw and IDirect3D. For a link to QueryInterface
106  * rules see ddraw.c, IDirectDraw7::QueryInterface
107  *
108  * Exists in Version 1, 2, 3 and 7
109  *
110  * Params:
111  *  refiid: Interface ID queried for
112  *  obj: Used to return the interface pointer
113  *
114  * Returns:
115  *  D3D_OK or E_NOINTERFACE
116  *
117  *****************************************************************************/
118 static HRESULT WINAPI
119 IDirect3DDeviceImpl_7_QueryInterface(IDirect3DDevice7 *iface,
120                                      REFIID refiid,
121                                      void **obj)
122 {
123     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
124     TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(refiid), obj);
125 
126     /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
127     *obj = NULL;
128 
129     if(!refiid)
130         return DDERR_INVALIDPARAMS;
131 
132     if ( IsEqualGUID( &IID_IUnknown, refiid ) )
133     {
134         *obj = iface;
135     }
136 
137     /* Check DirectDraw Interfacs */
138     else if( IsEqualGUID( &IID_IDirectDraw7, refiid ) )
139     {
140         *obj = This->ddraw;
141         TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
142     }
143     else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
144     {
145         *obj = &This->ddraw->IDirectDraw4_vtbl;
146         TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
147     }
148     else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
149     {
150         *obj = &This->ddraw->IDirectDraw2_vtbl;
151         TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
152     }
153     else if( IsEqualGUID( &IID_IDirectDraw, refiid ) )
154     {
155         *obj = &This->ddraw->IDirectDraw_vtbl;
156         TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
157     }
158 
159     /* Direct3D */
160     else if ( IsEqualGUID( &IID_IDirect3D  , refiid ) )
161     {
162         *obj = &This->ddraw->IDirect3D_vtbl;
163         TRACE("(%p) Returning IDirect3D interface at %p\n", This, *obj);
164     }
165     else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) )
166     {
167         *obj = &This->ddraw->IDirect3D2_vtbl;
168         TRACE("(%p) Returning IDirect3D2 interface at %p\n", This, *obj);
169     }
170     else if ( IsEqualGUID( &IID_IDirect3D3 , refiid ) )
171     {
172         *obj = &This->ddraw->IDirect3D3_vtbl;
173         TRACE("(%p) Returning IDirect3D3 interface at %p\n", This, *obj);
174     }
175     else if ( IsEqualGUID( &IID_IDirect3D7 , refiid ) )
176     {
177         *obj = &This->ddraw->IDirect3D7_vtbl;
178         TRACE("(%p) Returning IDirect3D7 interface at %p\n", This, *obj);
179     }
180 
181     /* Direct3DDevice */
182     else if ( IsEqualGUID( &IID_IDirect3DDevice  , refiid ) )
183     {
184         *obj = &This->IDirect3DDevice_vtbl;
185         TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
186     }
187     else if ( IsEqualGUID( &IID_IDirect3DDevice2  , refiid ) ) {
188         *obj = &This->IDirect3DDevice2_vtbl;
189         TRACE("(%p) Returning IDirect3DDevice2 interface at %p\n", This, *obj);
190     }
191     else if ( IsEqualGUID( &IID_IDirect3DDevice3  , refiid ) ) {
192         *obj = &This->IDirect3DDevice3_vtbl;
193         TRACE("(%p) Returning IDirect3DDevice3 interface at %p\n", This, *obj);
194     }
195     else if ( IsEqualGUID( &IID_IDirect3DDevice7  , refiid ) ) {
196         *obj = This;
197         TRACE("(%p) Returning IDirect3DDevice7 interface at %p\n", This, *obj);
198     }
199 
200     /* Unknown interface */
201     else
202     {
203         ERR("(%p)->(%s, %p): No interface found\n", This, debugstr_guid(refiid), obj);
204         return E_NOINTERFACE;
205     }
206 
207     /* AddRef the returned interface */
208     IUnknown_AddRef( (IUnknown *) *obj);
209     return D3D_OK;
210 }
211 
212 static HRESULT WINAPI
213 Thunk_IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface,
214                                            REFIID riid,
215                                            void **obj)
216 {
217     IDirect3DDeviceImpl *This = device_from_device3(iface);
218     TRACE_(ddraw_thunk)("(%p)->(%s,%p) thunking to IDirect3DDevice7 interface.\n", This, debugstr_guid(riid), obj);
219     return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)This, riid, obj);
220 }
221 
222 static HRESULT WINAPI
223 Thunk_IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface,
224                                            REFIID riid,
225                                            void **obj)
226 {
227     IDirect3DDeviceImpl *This = device_from_device2(iface);
228     TRACE_(ddraw_thunk)("(%p)->(%s,%p) thunking to IDirect3DDevice7 interface.\n", This, debugstr_guid(riid), obj);
229     return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)This, riid, obj);
230 }
231 
232 static HRESULT WINAPI
233 Thunk_IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface,
234                                            REFIID riid,
235                                            void **obp)
236 {
237     IDirect3DDeviceImpl *This = device_from_device1(iface);
238     TRACE_(ddraw_thunk)("(%p)->(%s,%p) thunking to IDirect3DDevice7 interface.\n", This, debugstr_guid(riid), obp);
239     return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)This, riid, obp);
240 }
241 
242 /*****************************************************************************
243  * IDirect3DDevice7::AddRef
244  *
245  * Increases the refcount....
246  * The most exciting Method, definitely
247  *
248  * Exists in Version 1, 2, 3 and 7
249  *
250  * Returns:
251  *  The new refcount
252  *
253  *****************************************************************************/
254 static ULONG WINAPI
255 IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
256 {
257     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
258     ULONG ref = InterlockedIncrement(&This->ref);
259 
260     TRACE("(%p) : incrementing from %u.\n", This, ref -1);
261 
262     return ref;
263 }
264 
265 static ULONG WINAPI
266 Thunk_IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
267 {
268     IDirect3DDeviceImpl *This = device_from_device3(iface);
269     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
270     return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)This);
271 }
272 
273 static ULONG WINAPI
274 Thunk_IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
275 {
276     IDirect3DDeviceImpl *This = device_from_device2(iface);
277     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
278     return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)This);
279 }
280 
281 static ULONG WINAPI
282 Thunk_IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
283 {
284     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", iface);
285     return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device1(iface));
286 }
287 
288 /*****************************************************************************
289  * IDirect3DDevice7::Release
290  *
291  * Decreases the refcount of the interface
292  * When the refcount is reduced to 0, the object is destroyed.
293  *
294  * Exists in Version 1, 2, 3 and 7
295  *
296  * Returns:d
297  *  The new refcount
298  *
299  *****************************************************************************/
300 static ULONG WINAPI
301 IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
302 {
303     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
304     ULONG ref = InterlockedDecrement(&This->ref);
305 
306     TRACE("(%p)->() decrementing from %u.\n", This, ref +1);
307 
308     /* This method doesn't destroy the WineD3DDevice, because it's still in use for
309      * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
310      * when the render target is released
311      */
312     if (ref == 0)
313     {
314         IParent *IndexBufferParent;
315         DWORD i;
316 
317         EnterCriticalSection(&ddraw_cs);
318         /* Free the index buffer. */
319         IWineD3DDevice_SetIndexBuffer(This->wineD3DDevice, NULL, WINED3DFMT_UNKNOWN);
320         IWineD3DBuffer_GetParent(This->indexbuffer,
321                                  (IUnknown **) &IndexBufferParent);
322         IParent_Release(IndexBufferParent); /* Once for the getParent */
323         if( IParent_Release(IndexBufferParent) != 0)  /* And now to destroy it */
324         {
325             ERR(" (%p) Something is still holding the index buffer parent %p\n", This, IndexBufferParent);
326         }
327 
328         /* There is no need to unset the vertex buffer here, IWineD3DDevice_Uninit3D will do that when
329          * destroying the primary stateblock. If a vertex buffer is destroyed while it is bound
330          * IDirect3DVertexBuffer::Release will unset it.
331          */
332 
333         /* Restore the render targets */
334         if(This->OffScreenTarget)
335         {
336             WINED3DVIEWPORT vp;
337 
338             vp.X = 0;
339             vp.Y = 0;
340             vp.Width = This->ddraw->d3d_target->surface_desc.dwWidth;
341             vp.Height = This->ddraw->d3d_target->surface_desc.dwHeight;
342             vp.MinZ = 0.0;
343             vp.MaxZ = 1.0;
344             IWineD3DDevice_SetViewport(This->wineD3DDevice,
345                                        &vp);
346 
347             /* Set the device up to render to the front buffer since the back buffer will
348              * vanish soon.
349              */
350             IWineD3DDevice_SetRenderTarget(This->wineD3DDevice, 0,
351                                            This->ddraw->d3d_target->WineD3DSurface,
352                                            FALSE);
353             /* This->target is the offscreen target.
354              * This->ddraw->d3d_target is the target used by DDraw
355              */
356             TRACE("(%p) Release: Using %p as front buffer, %p as back buffer\n", This, This->ddraw->d3d_target, NULL);
357             IWineD3DDevice_SetFrontBackBuffers(This->wineD3DDevice,
358                                                This->ddraw->d3d_target->WineD3DSurface,
359                                                NULL);
360         }
361 
362         /* Release the WineD3DDevice. This won't destroy it */
363         if(IWineD3DDevice_Release(This->wineD3DDevice) <= 0)
364         {
365             ERR(" (%p) The wineD3D device %p was destroyed unexpectedly. Prepare for trouble\n", This, This->wineD3DDevice);
366         }
367 
368         /* The texture handles should be unset by now, but there might be some bits
369          * missing in our reference counting(needs test). Do a sanity check
370          */
371         for(i = 0; i < This->numHandles; i++)
372         {
373             if(This->Handles[i].ptr)
374             {
375                 switch(This->Handles[i].type)
376                 {
377                     case DDrawHandle_Texture:
378                     {
379                         IDirectDrawSurfaceImpl *surf = This->Handles[i].ptr;
380                         FIXME("Texture Handle %d not unset properly\n", i + 1);
381                         surf->Handle = 0;
382                     }
383                     break;
384 
385                     case DDrawHandle_Material:
386                     {
387                         IDirect3DMaterialImpl *mat = This->Handles[i].ptr;
388                         FIXME("Material handle %d not unset properly\n", i + 1);
389                         mat->Handle = 0;
390                     }
391                     break;
392 
393                     case DDrawHandle_Matrix:
394                     {
395                         /* No fixme here because this might happen because of sloppy apps */
396                         WARN("Leftover matrix handle %d, deleting\n", i + 1);
397                         IDirect3DDevice_DeleteMatrix((IDirect3DDevice *)&This->IDirect3DDevice_vtbl, i + 1);
398                     }
399                     break;
400 
401                     case DDrawHandle_StateBlock:
402                     {
403                         /* No fixme here because this might happen because of sloppy apps */
404                         WARN("Leftover stateblock handle %d, deleting\n", i + 1);
405                         IDirect3DDevice7_DeleteStateBlock((IDirect3DDevice7 *)This, i + 1);
406                     }
407                     break;
408 
409                     default:
410                         FIXME("Unknown handle %d not unset properly\n", i + 1);
411                 }
412             }
413         }
414 
415         HeapFree(GetProcessHeap(), 0, This->Handles);
416 
417         TRACE("Releasing target %p %p\n", This->target, This->ddraw->d3d_target);
418         /* Release the render target and the WineD3D render target
419          * (See IDirect3D7::CreateDevice for more comments on this)
420          */
421         IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->target);
422         IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->ddraw->d3d_target);
423         TRACE("Target release done\n");
424 
425         This->ddraw->d3ddevice = NULL;
426 
427         /* Now free the structure */
428         HeapFree(GetProcessHeap(), 0, This);
429         LeaveCriticalSection(&ddraw_cs);
430     }
431 
432     TRACE("Done\n");
433     return ref;
434 }
435 
436 static ULONG WINAPI
437 Thunk_IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
438 {
439     IDirect3DDeviceImpl *This = device_from_device3(iface);
440     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
441     return IDirect3DDevice7_Release((IDirect3DDevice7 *)This);
442 }
443 
444 static ULONG WINAPI
445 Thunk_IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
446 {
447     IDirect3DDeviceImpl *This = device_from_device2(iface);
448     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
449     return IDirect3DDevice7_Release((IDirect3DDevice7 *)This);
450 }
451 
452 static ULONG WINAPI
453 Thunk_IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
454 {
455     IDirect3DDeviceImpl *This = device_from_device1(iface);
456     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
457     return IDirect3DDevice7_Release((IDirect3DDevice7 *)This);
458 }
459 
460 /*****************************************************************************
461  * IDirect3DDevice Methods
462  *****************************************************************************/
463 
464 /*****************************************************************************
465  * IDirect3DDevice::Initialize
466  *
467  * Initializes a Direct3DDevice. This implementation is a no-op, as all
468  * initialization is done at create time.
469  *
470  * Exists in Version 1
471  *
472  * Parameters:
473  *  No idea what they mean, as the MSDN page is gone
474  *
475  * Returns: DD_OK
476  *
477  *****************************************************************************/
478 static HRESULT WINAPI
479 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
480                                  IDirect3D *Direct3D, GUID *guid,
481                                  D3DDEVICEDESC *Desc)
482 {
483     IDirect3DDeviceImpl *This = device_from_device1(iface);
484 
485     /* It shouldn't be crucial, but print a FIXME, I'm interested if
486      * any game calls it and when
487      */
488     FIXME("(%p)->(%p,%p,%p): No-op!\n", This, Direct3D, guid, Desc);
489 
490     return D3D_OK;
491 }
492 
493 /*****************************************************************************
494  * IDirect3DDevice7::GetCaps
495  *
496  * Retrieves the device's capabilities
497  *
498  * This implementation is used for Version 7 only, the older versions have
499  * their own implementation.
500  *
501  * Parameters:
502  *  Desc: Pointer to a D3DDEVICEDESC7 structure to fill
503  *
504  * Returns:
505  *  D3D_OK on success
506  *  D3DERR_* if a problem occurs. See WineD3D
507  *
508  *****************************************************************************/
509 static HRESULT
510 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
511                               D3DDEVICEDESC7 *Desc)
512 {
513     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
514     D3DDEVICEDESC OldDesc;
515     TRACE("(%p)->(%p)\n", This, Desc);
516 
517     /* Call the same function used by IDirect3D, this saves code */
518     return IDirect3DImpl_GetCaps(This->ddraw->wineD3D, &OldDesc, Desc);
519 }
520 
521 static HRESULT WINAPI
522 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
523                               D3DDEVICEDESC7 *Desc)
524 {
525     return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
526 }
527 
528 static HRESULT WINAPI
529 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
530                               D3DDEVICEDESC7 *Desc)
531 {
532     HRESULT hr;
533     WORD old_fpucw;
534 
535     old_fpucw = d3d_fpu_setup();
536     hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
537     set_fpu_control_word(old_fpucw);
538 
539     return hr;
540 }
541 /*****************************************************************************
542  * IDirect3DDevice3::GetCaps
543  *
544  * Retrieves the capabilities of the hardware device and the emulation
545  * device. For Wine, hardware and emulation are the same (it's all HW).
546  *
547  * This implementation is used for Version 1, 2, and 3. Version 7 has its own
548  *
549  * Parameters:
550  *  HWDesc: Structure to fill with the HW caps
551  *  HelDesc: Structure to fill with the hardware emulation caps
552  *
553  * Returns:
554  *  D3D_OK on success
555  *  D3DERR_* if a problem occurs. See WineD3D
556  *
557  *****************************************************************************/
558 static HRESULT WINAPI
559 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
560                               D3DDEVICEDESC *HWDesc,
561                               D3DDEVICEDESC *HelDesc)
562 {
563     IDirect3DDeviceImpl *This = device_from_device3(iface);
564     D3DDEVICEDESC7 newDesc;
565     HRESULT hr;
566     TRACE("(%p)->(%p,%p)\n", iface, HWDesc, HelDesc);
567 
568     hr = IDirect3DImpl_GetCaps(This->ddraw->wineD3D, HWDesc, &newDesc);
569     if(hr != D3D_OK) return hr;
570 
571     *HelDesc = *HWDesc;
572     return D3D_OK;
573 }
574 
575 static HRESULT WINAPI
576 Thunk_IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
577                                     D3DDEVICEDESC *D3DHWDevDesc,
578                                     D3DDEVICEDESC *D3DHELDevDesc)
579 {
580     IDirect3DDeviceImpl *This = device_from_device2(iface);
581     TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice3 interface.\n", This, D3DHWDevDesc, D3DHELDevDesc);
582     return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
583 }
584 
585 static HRESULT WINAPI
586 Thunk_IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
587                                     D3DDEVICEDESC *D3DHWDevDesc,
588                                     D3DDEVICEDESC *D3DHELDevDesc)
589 {
590     IDirect3DDeviceImpl *This = device_from_device1(iface);
591     TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice3 interface.\n", This, D3DHWDevDesc, D3DHELDevDesc);
592     return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
593 }
594 
595 /*****************************************************************************
596  * IDirect3DDevice2::SwapTextureHandles
597  *
598  * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
599  *
600  * Parameters:
601  *  Tex1, Tex2: The 2 Textures to swap
602  *
603  * Returns:
604  *  D3D_OK
605  *
606  *****************************************************************************/
607 static HRESULT WINAPI
608 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
609                                          IDirect3DTexture2 *Tex1,
610                                          IDirect3DTexture2 *Tex2)
611 {
612     IDirect3DDeviceImpl *This = device_from_device2(iface);
613     DWORD swap;
614     IDirectDrawSurfaceImpl *surf1 = surface_from_texture2(Tex1);
615     IDirectDrawSurfaceImpl *surf2 = surface_from_texture2(Tex2);
616     TRACE("(%p)->(%p,%p)\n", This, surf1, surf2);
617 
618     EnterCriticalSection(&ddraw_cs);
619     This->Handles[surf1->Handle - 1].ptr = surf2;
620     This->Handles[surf2->Handle - 1].ptr = surf1;
621 
622     swap = surf2->Handle;
623     surf2->Handle = surf1->Handle;
624     surf1->Handle = swap;
625     LeaveCriticalSection(&ddraw_cs);
626 
627     return D3D_OK;
628 }
629 
630 static HRESULT WINAPI
631 Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
632                                                IDirect3DTexture *D3DTex1,
633                                                IDirect3DTexture *D3DTex2)
634 {
635     IDirect3DDeviceImpl *This = device_from_device1(iface);
636     IDirectDrawSurfaceImpl *surf1 = surface_from_texture1(D3DTex1);
637     IDirectDrawSurfaceImpl *surf2 = surface_from_texture1(D3DTex2);
638     IDirect3DTexture2 *t1 = surf1 ? (IDirect3DTexture2 *)&surf1->IDirect3DTexture2_vtbl : NULL;
639     IDirect3DTexture2 *t2 = surf2 ? (IDirect3DTexture2 *)&surf2->IDirect3DTexture2_vtbl : NULL;
640     TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice2 interface.\n", This, surf1, surf2);
641     return IDirect3DDevice2_SwapTextureHandles((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, t1, t2);
642 }
643 
644 /*****************************************************************************
645  * IDirect3DDevice3::GetStats
646  *
647  * This method seems to retrieve some stats from the device.
648  * The MSDN documentation doesn't exist any more, but the D3DSTATS
649  * structure suggests that the amount of drawn primitives and processed
650  * vertices is returned.
651  *
652  * Exists in Version 1, 2 and 3
653  *
654  * Parameters:
655  *  Stats: Pointer to a D3DSTATS structure to be filled
656  *
657  * Returns:
658  *  D3D_OK on success
659  *  DDERR_INVALIDPARAMS if Stats == NULL
660  *
661  *****************************************************************************/
662 static HRESULT WINAPI
663 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
664                                D3DSTATS *Stats)
665 {
666     IDirect3DDeviceImpl *This = device_from_device3(iface);
667     FIXME("(%p)->(%p): Stub!\n", This, Stats);
668 
669     if(!Stats)
670         return DDERR_INVALIDPARAMS;
671 
672     /* Fill the Stats with 0 */
673     Stats->dwTrianglesDrawn = 0;
674     Stats->dwLinesDrawn = 0;
675     Stats->dwPointsDrawn = 0;
676     Stats->dwSpansDrawn = 0;
677     Stats->dwVerticesProcessed = 0;
678 
679     return D3D_OK;
680 }
681 
682 static HRESULT WINAPI
683 Thunk_IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface,
684                                      D3DSTATS *Stats)
685 {
686     IDirect3DDeviceImpl *This = device_from_device2(iface);
687     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, Stats);
688     return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
689 }
690 
691 static HRESULT WINAPI
692 Thunk_IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface,
693                                      D3DSTATS *Stats)
694 {
695     IDirect3DDeviceImpl *This = device_from_device1(iface);
696     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, Stats);
697     return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
698 }
699 
700 /*****************************************************************************
701  * IDirect3DDevice::CreateExecuteBuffer
702  *
703  * Creates an IDirect3DExecuteBuffer, used for rendering with a
704  * Direct3DDevice.
705  *
706  * Version 1 only.
707  *
708  * Params:
709  *  Desc: Buffer description
710  *  ExecuteBuffer: Address to return the Interface pointer at
711  *  UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
712  *            support
713  *
714  * Returns:
715  *  CLASS_E_NOAGGREGATION if UnkOuter != NULL
716  *  DDERR_OUTOFMEMORY if we ran out of memory
717  *  D3D_OK on success
718  *
719  *****************************************************************************/
720 static HRESULT WINAPI
721 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
722                                           D3DEXECUTEBUFFERDESC *Desc,
723                                           IDirect3DExecuteBuffer **ExecuteBuffer,
724                                           IUnknown *UnkOuter)
725 {
726     IDirect3DDeviceImpl *This = device_from_device1(iface);
727     IDirect3DExecuteBufferImpl* object;
728     TRACE("(%p)->(%p,%p,%p)!\n", This, Desc, ExecuteBuffer, UnkOuter);
729 
730     if(UnkOuter)
731         return CLASS_E_NOAGGREGATION;
732 
733     /* Allocate the new Execute Buffer */
734     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
735     if(!object)
736     {
737         ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
738         return DDERR_OUTOFMEMORY;
739     }
740 
741     object->lpVtbl = &IDirect3DExecuteBuffer_Vtbl;
742     object->ref = 1;
743     object->d3ddev = This;
744 
745     /* Initializes memory */
746     memcpy(&object->desc, Desc, Desc->dwSize);
747 
748     /* No buffer given */
749     if ((object->desc.dwFlags & D3DDEB_LPDATA) == 0)
750         object->desc.lpData = NULL;
751 
752     /* No buffer size given */
753     if ((object->desc.dwFlags & D3DDEB_BUFSIZE) == 0)
754         object->desc.dwBufferSize = 0;
755 
756     /* Create buffer if asked */
757     if ((object->desc.lpData == NULL) && (object->desc.dwBufferSize > 0))
758     {
759         object->need_free = TRUE;
760         object->desc.lpData = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,object->desc.dwBufferSize);
761         if(!object->desc.lpData)
762         {
763             ERR("Out of memory when allocating the execute buffer data\n");
764             HeapFree(GetProcessHeap(), 0, object);
765             return DDERR_OUTOFMEMORY;
766         }
767     }
768     else
769     {
770         object->need_free = FALSE;
771     }
772 
773     /* No vertices for the moment */
774     object->vertex_data = NULL;
775 
776     object->desc.dwFlags |= D3DDEB_LPDATA;
777 
778     object->indices = NULL;
779     object->nb_indices = 0;
780 
781     *ExecuteBuffer = (IDirect3DExecuteBuffer *)object;
782 
783     TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
784 
785     return D3D_OK;
786 }
787 
788 /*****************************************************************************
789  * IDirect3DDevice::Execute
790  *
791  * Executes all the stuff in an execute buffer.
792  *
793  * Params:
794  *  ExecuteBuffer: The buffer to execute
795  *  Viewport: The viewport used for rendering
796  *  Flags: Some flags
797  *
798  * Returns:
799  *  DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
800  *  D3D_OK on success
801  *
802  *****************************************************************************/
803 static HRESULT WINAPI
804 IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
805                               IDirect3DExecuteBuffer *ExecuteBuffer,
806                               IDirect3DViewport *Viewport,
807                               DWORD Flags)
808 {
809     IDirect3DDeviceImpl *This = device_from_device1(iface);
810     IDirect3DExecuteBufferImpl *Direct3DExecuteBufferImpl = (IDirect3DExecuteBufferImpl *)ExecuteBuffer;
811     IDirect3DViewportImpl *Direct3DViewportImpl = (IDirect3DViewportImpl *)Viewport;
812 
813     TRACE("(%p)->(%p,%p,%08x)\n", This, Direct3DExecuteBufferImpl, Direct3DViewportImpl, Flags);
814 
815     if(!Direct3DExecuteBufferImpl)
816         return DDERR_INVALIDPARAMS;
817 
818     /* Execute... */
819     EnterCriticalSection(&ddraw_cs);
820     IDirect3DExecuteBufferImpl_Execute(Direct3DExecuteBufferImpl, This, Direct3DViewportImpl);
821     LeaveCriticalSection(&ddraw_cs);
822 
823     return D3D_OK;
824 }
825 
826 /*****************************************************************************
827  * IDirect3DDevice3::AddViewport
828  *
829  * Add a Direct3DViewport to the device's viewport list. These viewports
830  * are wrapped to IDirect3DDevice7 viewports in viewport.c
831  *
832  * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
833  * are the same interfaces.
834  *
835  * Params:
836  *  Viewport: The viewport to add
837  *
838  * Returns:
839  *  DDERR_INVALIDPARAMS if Viewport == NULL
840  *  D3D_OK on success
841  *
842  *****************************************************************************/
843 static HRESULT WINAPI
844 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
845                                   IDirect3DViewport3 *Viewport)
846 {
847     IDirect3DDeviceImpl *This = device_from_device3(iface);
848     IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
849 
850     TRACE("(%p)->(%p)\n", This, vp);
851 
852     /* Sanity check */
853     if(!vp)
854         return DDERR_INVALIDPARAMS;
855 
856     EnterCriticalSection(&ddraw_cs);
857     vp->next = This->viewport_list;
858     This->viewport_list = vp;
859     vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
860                                     so set active_device here. */
861     LeaveCriticalSection(&ddraw_cs);
862 
863     return D3D_OK;
864 }
865 
866 static HRESULT WINAPI
867 Thunk_IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
868                                         IDirect3DViewport2 *Direct3DViewport2)
869 {
870     IDirect3DDeviceImpl *This = device_from_device2(iface);
871     IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
872     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
873     return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
874 }
875 
876 static HRESULT WINAPI
877 Thunk_IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
878                                         IDirect3DViewport *Direct3DViewport)
879 {
880     IDirect3DDeviceImpl *This = device_from_device1(iface);
881     IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
882     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
883     return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
884 }
885 
886 /*****************************************************************************
887  * IDirect3DDevice3::DeleteViewport
888  *
889  * Deletes a Direct3DViewport from the device's viewport list.
890  *
891  * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
892  * are equal.
893  *
894  * Params:
895  *  Viewport: The viewport to delete
896  *
897  * Returns:
898  *  D3D_OK on success
899  *  DDERR_INVALIDPARAMS if the viewport wasn't found in the list
900  *
901  *****************************************************************************/
902 static HRESULT WINAPI
903 IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface,
904                                      IDirect3DViewport3 *Viewport)
905 {
906     IDirect3DDeviceImpl *This = device_from_device3(iface);
907     IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *) Viewport;
908     IDirect3DViewportImpl *cur_viewport, *prev_viewport = NULL;
909 
910     TRACE("(%p)->(%p)\n", This, vp);
911 
912     EnterCriticalSection(&ddraw_cs);
913     cur_viewport = This->viewport_list;
914     while (cur_viewport != NULL)
915     {
916         if (cur_viewport == vp)
917         {
918             if (prev_viewport == NULL) This->viewport_list = cur_viewport->next;
919             else prev_viewport->next = cur_viewport->next;
920             /* TODO : add desactivate of the viewport and all associated lights... */
921             LeaveCriticalSection(&ddraw_cs);
922             return D3D_OK;
923         }
924         prev_viewport = cur_viewport;
925         cur_viewport = cur_viewport->next;
926     }
927 
928     LeaveCriticalSection(&ddraw_cs);
929     return DDERR_INVALIDPARAMS;
930 }
931 
932 static HRESULT WINAPI
933 Thunk_IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
934                                            IDirect3DViewport2 *Direct3DViewport2)
935 {
936     IDirect3DDeviceImpl *This = device_from_device2(iface);
937     IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
938     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
939     return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
940 }
941 
942 static HRESULT WINAPI
943 Thunk_IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
944                                            IDirect3DViewport *Direct3DViewport)
945 {
946     IDirect3DDeviceImpl *This = device_from_device1(iface);
947     IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
948     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
949     return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
950 }
951 
952 /*****************************************************************************
953  * IDirect3DDevice3::NextViewport
954  *
955  * Returns a viewport from the viewport list, depending on the
956  * passed viewport and the flags.
957  *
958  * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
959  * are equal.
960  *
961  * Params:
962  *  Viewport: Viewport to use for beginning the search
963  *  Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
964  *
965  * Returns:
966  *  D3D_OK on success
967  *  DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
968  *
969  *****************************************************************************/
970 static HRESULT WINAPI
971 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
972                                    IDirect3DViewport3 *Viewport3,
973                                    IDirect3DViewport3 **lplpDirect3DViewport3,
974                                    DWORD Flags)
975 {
976     IDirect3DDeviceImpl *This = device_from_device3(iface);
977     IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport3;
978     IDirect3DViewportImpl *res = NULL;
979 
980     TRACE("(%p)->(%p,%p,%08x)\n", This, vp, lplpDirect3DViewport3, Flags);
981 
982     if(!vp)
983     {
984         *lplpDirect3DViewport3 = NULL;
985         return DDERR_INVALIDPARAMS;
986     }
987 
988 
989     EnterCriticalSection(&ddraw_cs);
990     switch (Flags)
991     {
992         case D3DNEXT_NEXT:
993         {
994             res = vp->next;
995         }
996         break;
997         case D3DNEXT_HEAD:
998         {
999             res = This->viewport_list;
1000         }
1001         break;
1002         case D3DNEXT_TAIL:
1003         {
1004             IDirect3DViewportImpl *cur_viewport = This->viewport_list;
1005             if (cur_viewport != NULL)
1006             {
1007                 while (cur_viewport->next != NULL) cur_viewport = cur_viewport->next;
1008             }
1009             res = cur_viewport;
1010         }
1011         break;
1012         default:
1013             *lplpDirect3DViewport3 = NULL;
1014             LeaveCriticalSection(&ddraw_cs);
1015             return DDERR_INVALIDPARAMS;
1016     }
1017 
1018     *lplpDirect3DViewport3 = (IDirect3DViewport3 *)res;
1019     LeaveCriticalSection(&ddraw_cs);
1020     return D3D_OK;
1021 }
1022 
1023 static HRESULT WINAPI
1024 Thunk_IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
1025                                          IDirect3DViewport2 *Viewport2,
1026                                          IDirect3DViewport2 **lplpDirect3DViewport2,
1027                                          DWORD Flags)
1028 {
1029     IDirect3DDeviceImpl *This = device_from_device2(iface);
1030     IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport2;
1031     IDirect3DViewport3 *res;
1032     HRESULT hr;
1033     TRACE_(ddraw_thunk)("(%p)->(%p,%p,%08x) thunking to IDirect3DDevice3 interface.\n", This, vp, lplpDirect3DViewport2, Flags);
1034     hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1035             (IDirect3DViewport3 *)vp, &res, Flags);
1036     *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
1037     return hr;
1038 }
1039 
1040 static HRESULT WINAPI
1041 Thunk_IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
1042                                          IDirect3DViewport *Viewport,
1043                                          IDirect3DViewport **lplpDirect3DViewport,
1044                                          DWORD Flags)
1045 {
1046     IDirect3DDeviceImpl *This = device_from_device1(iface);
1047     IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
1048     IDirect3DViewport3 *res;
1049     HRESULT hr;
1050     TRACE_(ddraw_thunk)("(%p)->(%p,%p,%08x) thunking to IDirect3DDevice3 interface.\n", This, vp, lplpDirect3DViewport, Flags);
1051     hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1052             (IDirect3DViewport3 *)vp, &res, Flags);
1053     *lplpDirect3DViewport = (IDirect3DViewport *)res;
1054     return hr;
1055 }
1056 
1057 /*****************************************************************************
1058  * IDirect3DDevice::Pick
1059  *
1060  * Executes an execute buffer without performing rendering. Instead, a
1061  * list of primitives that intersect with (x1,y1) of the passed rectangle
1062  * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
1063  * this list.
1064  *
1065  * Version 1 only
1066  *
1067  * Params:
1068  *  ExecuteBuffer: Buffer to execute
1069  *  Viewport: Viewport to use for execution
1070  *  Flags: None are defined, according to the SDK
1071  *  Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
1072  *        x2 and y2 are ignored.
1073  *
1074  * Returns:
1075  *  D3D_OK because it's a stub
1076  *
1077  *****************************************************************************/
1078 static HRESULT WINAPI
1079 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
1080                            IDirect3DExecuteBuffer *ExecuteBuffer,
1081                            IDirect3DViewport *Viewport,
1082                            DWORD Flags,
1083                            D3DRECT *Rect)
1084 {
1085     IDirect3DDeviceImpl *This = device_from_device1(iface);
1086     IDirect3DExecuteBufferImpl *execbuf = (IDirect3DExecuteBufferImpl *)ExecuteBuffer;
1087     IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
1088     FIXME("(%p)->(%p,%p,%08x,%p): stub!\n", This, execbuf, vp, Flags, Rect);
1089 
1090     return D3D_OK;
1091 }
1092 
1093 /*****************************************************************************
1094  * IDirect3DDevice::GetPickRecords
1095  *
1096  * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1097  *
1098  * Version 1 only
1099  *
1100  * Params:
1101  *  Count: Pointer to a DWORD containing the numbers of pick records to
1102  *         retrieve
1103  *  D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1104  *
1105  * Returns:
1106  *  D3D_OK, because it's a stub
1107  *
1108  *****************************************************************************/
1109 static HRESULT WINAPI
1110 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1111                                      DWORD *Count,
1112                                      D3DPICKRECORD *D3DPickRec)
1113 {
1114     IDirect3DDeviceImpl *This = device_from_device1(iface);
1115     FIXME("(%p)->(%p,%p): stub!\n", This, Count, D3DPickRec);
1116 
1117     return D3D_OK;
1118 }
1119 
1120 /*****************************************************************************
1121  * IDirect3DDevice7::EnumTextureformats
1122  *
1123  * Enumerates the supported texture formats. It has a list of all possible
1124  * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1125  * WineD3D supports it. If so, then it is passed to the app.
1126  *
1127  * This is for Version 7 and 3, older versions have a different
1128  * callback function and their own implementation
1129  *
1130  * Params:
1131  *  Callback: Callback to call for each enumerated format
1132  *  Arg: Argument to pass to the callback
1133  *
1134  * Returns:
1135  *  D3D_OK on success
1136  *  DDERR_INVALIDPARAMS if Callback == NULL
1137  *
1138  *****************************************************************************/
1139 static HRESULT
1140 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1141                                          LPD3DENUMPIXELFORMATSCALLBACK Callback,
1142                                          void *Arg)
1143 {
1144     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1145     HRESULT hr;
1146     WINED3DDISPLAYMODE mode;
1147     unsigned int i;
1148 
1149     WINED3DFORMAT FormatList[] = {
1150         /* 32 bit */
1151         WINED3DFMT_B8G8R8A8_UNORM,
1152         WINED3DFMT_B8G8R8X8_UNORM,
1153         /* 24 bit */
1154         WINED3DFMT_B8G8R8_UNORM,
1155         /* 16 Bit */
1156         WINED3DFMT_B5G5R5A1_UNORM,
1157         WINED3DFMT_B4G4R4A4_UNORM,
1158         WINED3DFMT_B5G6R5_UNORM,
1159         WINED3DFMT_B5G5R5X1_UNORM,
1160         /* 8 Bit */
1161         WINED3DFMT_B2G3R3_UNORM,
1162         WINED3DFMT_P8_UINT,
1163         /* FOURCC codes */
1164         WINED3DFMT_DXT1,
1165         WINED3DFMT_DXT3,
1166         WINED3DFMT_DXT5,
1167     };
1168 
1169     WINED3DFORMAT BumpFormatList[] = {
1170         WINED3DFMT_R8G8_SNORM,
1171         WINED3DFMT_R5G5_SNORM_L6_UNORM,
1172         WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1173         WINED3DFMT_R8G8B8A8_SNORM,
1174         WINED3DFMT_R16G16_SNORM,
1175         WINED3DFMT_R10G11B11_SNORM,
1176         WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1177     };
1178 
1179     TRACE("(%p)->(%p,%p): Relay\n", This, Callback, Arg);
1180 
1181     if(!Callback)
1182         return DDERR_INVALIDPARAMS;
1183 
1184     EnterCriticalSection(&ddraw_cs);
1185 
1186     memset(&mode, 0, sizeof(mode));
1187     hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1188                                        0,
1189                                        &mode);
1190     if(FAILED(hr)) {
1191         LeaveCriticalSection(&ddraw_cs);
1192         WARN("Cannot get the current adapter format\n");
1193         return hr;
1194     }
1195 
1196     for(i = 0; i < sizeof(FormatList) / sizeof(WINED3DFORMAT); i++)
1197     {
1198         hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1199                                         WINED3DADAPTER_DEFAULT,
1200                                         WINED3DDEVTYPE_HAL,
1201                                         mode.Format,
1202                                         0 /* Usage */,
1203                                         WINED3DRTYPE_TEXTURE,
1204                                         FormatList[i],
1205                                         SURFACE_OPENGL);
1206         if(hr == D3D_OK)
1207         {
1208             DDPIXELFORMAT pformat;
1209 
1210             memset(&pformat, 0, sizeof(pformat));
1211             pformat.dwSize = sizeof(pformat);
1212             PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1213 
1214             TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1215             hr = Callback(&pformat, Arg);
1216             if(hr != DDENUMRET_OK)
1217             {
1218                 TRACE("Format enumeration cancelled by application\n");
1219                 LeaveCriticalSection(&ddraw_cs);
1220                 return D3D_OK;
1221             }
1222         }
1223     }
1224 
1225     for(i = 0; i < sizeof(BumpFormatList) / sizeof(WINED3DFORMAT); i++)
1226     {
1227         hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1228                                         WINED3DADAPTER_DEFAULT,
1229                                         WINED3DDEVTYPE_HAL,
1230                                         mode.Format,
1231                                         WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1232                                         WINED3DRTYPE_TEXTURE,
1233                                         BumpFormatList[i],
1234                                         SURFACE_OPENGL);
1235         if(hr == D3D_OK)
1236         {
1237             DDPIXELFORMAT pformat;
1238 
1239             memset(&pformat, 0, sizeof(pformat));
1240             pformat.dwSize = sizeof(pformat);
1241             PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1242 
1243             TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1244             hr = Callback(&pformat, Arg);
1245             if(hr != DDENUMRET_OK)
1246             {
1247                 TRACE("Format enumeration cancelled by application\n");
1248                 LeaveCriticalSection(&ddraw_cs);
1249                 return D3D_OK;
1250             }
1251         }
1252     }
1253     TRACE("End of enumeration\n");
1254     LeaveCriticalSection(&ddraw_cs);
1255     return D3D_OK;
1256 }
1257 
1258 static HRESULT WINAPI
1259 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1260                                          LPD3DENUMPIXELFORMATSCALLBACK Callback,
1261                                          void *Arg)
1262 {
1263     return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1264 }
1265 
1266 static HRESULT WINAPI
1267 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1268                                          LPD3DENUMPIXELFORMATSCALLBACK Callback,
1269                                          void *Arg)
1270 {
1271     HRESULT hr;
1272     WORD old_fpucw;
1273 
1274     old_fpucw = d3d_fpu_setup();
1275     hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1276     set_fpu_control_word(old_fpucw);
1277 
1278     return hr;
1279 }
1280 
1281 static HRESULT WINAPI
1282 Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1283                                                LPD3DENUMPIXELFORMATSCALLBACK Callback,
1284                                                void *Arg)
1285 {
1286     IDirect3DDeviceImpl *This = device_from_device3(iface);
1287     TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice7 interface.\n", This, Callback, Arg);
1288     return IDirect3DDevice7_EnumTextureFormats((IDirect3DDevice7 *)This, Callback, Arg);
1289 }
1290 
1291 /*****************************************************************************
1292  * IDirect3DDevice2::EnumTextureformats
1293  *
1294  * EnumTextureFormats for Version 1 and 2, see
1295  * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1296  *
1297  * This version has a different callback and does not enumerate FourCC
1298  * formats
1299  *
1300  *****************************************************************************/
1301 static HRESULT WINAPI
1302 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1303                                          LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1304                                          void *Arg)
1305 {
1306     IDirect3DDeviceImpl *This = device_from_device2(iface);
1307     HRESULT hr;
1308     unsigned int i;
1309     WINED3DDISPLAYMODE mode;
1310 
1311     WINED3DFORMAT FormatList[] = {
1312         /* 32 bit */
1313         WINED3DFMT_B8G8R8A8_UNORM,
1314         WINED3DFMT_B8G8R8X8_UNORM,
1315         /* 24 bit */
1316         WINED3DFMT_B8G8R8_UNORM,
1317         /* 16 Bit */
1318         WINED3DFMT_B5G5R5A1_UNORM,
1319         WINED3DFMT_B4G4R4A4_UNORM,
1320         WINED3DFMT_B5G6R5_UNORM,
1321         WINED3DFMT_B5G5R5X1_UNORM,
1322         /* 8 Bit */
1323         WINED3DFMT_B2G3R3_UNORM,
1324         WINED3DFMT_P8_UINT,
1325         /* FOURCC codes - Not in this version*/
1326     };
1327 
1328     TRACE("(%p)->(%p,%p): Relay\n", This, Callback, Arg);
1329 
1330     if(!Callback)
1331         return DDERR_INVALIDPARAMS;
1332 
1333     EnterCriticalSection(&ddraw_cs);
1334 
1335     memset(&mode, 0, sizeof(mode));
1336     hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1337                                        0,
1338                                        &mode);
1339     if(FAILED(hr)) {
1340         LeaveCriticalSection(&ddraw_cs);
1341         WARN("Cannot get the current adapter format\n");
1342         return hr;
1343     }
1344 
1345     for(i = 0; i < sizeof(FormatList) / sizeof(WINED3DFORMAT); i++)
1346     {
1347         hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1348                                         0 /* Adapter */,
1349                                         WINED3DDEVTYPE_HAL,
1350                                         mode.Format,
1351                                         0 /* Usage */,
1352                                         WINED3DRTYPE_TEXTURE,
1353                                         FormatList[i],
1354                                         SURFACE_OPENGL);
1355         if(hr == D3D_OK)
1356         {
1357             DDSURFACEDESC sdesc;
1358 
1359             memset(&sdesc, 0, sizeof(sdesc));
1360             sdesc.dwSize = sizeof(sdesc);
1361             sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1362             sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1363             sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1364             PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1365 
1366             TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1367             hr = Callback(&sdesc, Arg);
1368             if(hr != DDENUMRET_OK)
1369             {
1370                 TRACE("Format enumeration cancelled by application\n");
1371                 LeaveCriticalSection(&ddraw_cs);
1372                 return D3D_OK;
1373             }
1374         }
1375     }
1376     TRACE("End of enumeration\n");
1377     LeaveCriticalSection(&ddraw_cs);
1378     return D3D_OK;
1379 }
1380 
1381 static HRESULT WINAPI
1382 Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1383                                                LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1384                                                void *Arg)
1385 {
1386     IDirect3DDeviceImpl *This = device_from_device1(iface);
1387     TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice2 interface.\n", This, Callback, Arg);
1388     return IDirect3DDevice2_EnumTextureFormats((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, Callback, Arg);
1389 }
1390 
1391 /*****************************************************************************
1392  * IDirect3DDevice::CreateMatrix
1393  *
1394  * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1395  * allocated for the handle.
1396  *
1397  * Version 1 only
1398  *
1399  * Params
1400  *  D3DMatHandle: Address to return the handle at
1401  *
1402  * Returns:
1403  *  D3D_OK on success
1404  *  DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1405  *
1406  *****************************************************************************/
1407 static HRESULT WINAPI
1408 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1409 {
1410     IDirect3DDeviceImpl *This = device_from_device1(iface);
1411     D3DMATRIX *Matrix;
1412     TRACE("(%p)->(%p)\n", This, D3DMatHandle);
1413 
1414     if(!D3DMatHandle)
1415         return DDERR_INVALIDPARAMS;
1416 
1417     Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1418     if(!Matrix)
1419     {
1420         ERR("Out of memory when allocating a D3DMATRIX\n");
1421         return DDERR_OUTOFMEMORY;
1422     }
1423 
1424     EnterCriticalSection(&ddraw_cs);
1425     *D3DMatHandle = IDirect3DDeviceImpl_CreateHandle(This);
1426     if(!(*D3DMatHandle))
1427     {
1428         ERR("Failed to create a matrix handle\n");
1429         HeapFree(GetProcessHeap(), 0, Matrix);
1430         LeaveCriticalSection(&ddraw_cs);
1431         return DDERR_OUTOFMEMORY;
1432     }
1433     This->Handles[*D3DMatHandle - 1].ptr = Matrix;
1434     This->Handles[*D3DMatHandle - 1].type = DDrawHandle_Matrix;
1435     TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1436 
1437     LeaveCriticalSection(&ddraw_cs);
1438     return D3D_OK;
1439 }
1440 
1441 /*****************************************************************************
1442  * IDirect3DDevice::SetMatrix
1443  *
1444  * Sets a matrix for a matrix handle. The matrix is copied into the memory
1445  * allocated for the handle
1446  *
1447  * Version 1 only
1448  *
1449  * Params:
1450  *  D3DMatHandle: Handle to set the matrix to
1451  *  D3DMatrix: Matrix to set
1452  *
1453  * Returns:
1454  *  D3D_OK on success
1455  *  DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1456  *   to set is NULL
1457  *
1458  *****************************************************************************/
1459 static HRESULT WINAPI
1460 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1461                                 D3DMATRIXHANDLE D3DMatHandle,
1462                                 D3DMATRIX *D3DMatrix)
1463 {
1464     IDirect3DDeviceImpl *This = device_from_device1(iface);
1465     TRACE("(%p)->(%08x,%p)\n", This, D3DMatHandle, D3DMatrix);
1466 
1467     if( (!D3DMatHandle) || (!D3DMatrix) )
1468         return DDERR_INVALIDPARAMS;
1469 
1470     EnterCriticalSection(&ddraw_cs);
1471     if(D3DMatHandle > This->numHandles)
1472     {
1473         ERR("Handle %d out of range\n", D3DMatHandle);
1474         LeaveCriticalSection(&ddraw_cs);
1475         return DDERR_INVALIDPARAMS;
1476     }
1477     else if(This->Handles[D3DMatHandle - 1].type != DDrawHandle_Matrix)
1478     {
1479         ERR("Handle %d is not a matrix handle\n", D3DMatHandle);
1480         LeaveCriticalSection(&ddraw_cs);
1481         return DDERR_INVALIDPARAMS;
1482     }
1483 
1484     if (TRACE_ON(d3d7))
1485         dump_D3DMATRIX(D3DMatrix);
1486 
1487     *((D3DMATRIX *) This->Handles[D3DMatHandle - 1].ptr) = *D3DMatrix;
1488 
1489     if(This->world == D3DMatHandle)
1490     {
1491         IWineD3DDevice_SetTransform(This->wineD3DDevice,
1492                                     WINED3DTS_WORLDMATRIX(0),
1493                                     (WINED3DMATRIX *) D3DMatrix);
1494     }
1495     if(This->view == D3DMatHandle)
1496     {
1497         IWineD3DDevice_SetTransform(This->wineD3DDevice,
1498                                     WINED3DTS_VIEW,
1499                                     (WINED3DMATRIX *) D3DMatrix);
1500     }
1501     if(This->proj == D3DMatHandle)
1502     {
1503         IWineD3DDevice_SetTransform(This->wineD3DDevice,
1504                                     WINED3DTS_PROJECTION,
1505                                     (WINED3DMATRIX *) D3DMatrix);
1506     }
1507 
1508     LeaveCriticalSection(&ddraw_cs);
1509     return D3D_OK;
1510 }
1511 
1512 /*****************************************************************************
1513  * IDirect3DDevice::SetMatrix
1514  *
1515  * Returns the content of a D3DMATRIX handle
1516  *
1517  * Version 1 only
1518  *
1519  * Params:
1520  *  D3DMatHandle: Matrix handle to read the content from
1521  *  D3DMatrix: Address to store the content at
1522  *
1523  * Returns:
1524  *  D3D_OK on success
1525  *  DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1526  *
1527  *****************************************************************************/
1528 static HRESULT WINAPI
1529 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1530                                 D3DMATRIXHANDLE D3DMatHandle,
1531                                 D3DMATRIX *D3DMatrix)
1532 {
1533     IDirect3DDeviceImpl *This = device_from_device1(iface);
1534     TRACE("(%p)->(%08x,%p)\n", This, D3DMatHandle, D3DMatrix);
1535 
1536     if(!D3DMatrix)
1537         return DDERR_INVALIDPARAMS;
1538     if(!D3DMatHandle)
1539         return DDERR_INVALIDPARAMS;
1540 
1541     EnterCriticalSection(&ddraw_cs);
1542     if(D3DMatHandle > This->numHandles)
1543     {
1544         ERR("Handle %d out of range\n", D3DMatHandle);
1545         LeaveCriticalSection(&ddraw_cs);
1546         return DDERR_INVALIDPARAMS;
1547     }
1548     else if(This->Handles[D3DMatHandle - 1].type != DDrawHandle_Matrix)
1549     {
1550         ERR("Handle %d is not a matrix handle\n", D3DMatHandle);
1551         LeaveCriticalSection(&ddraw_cs);
1552         return DDERR_INVALIDPARAMS;
1553     }
1554 
1555     /* The handle is simply a pointer to a D3DMATRIX structure */
1556     *D3DMatrix = *((D3DMATRIX *) This->Handles[D3DMatHandle - 1].ptr);
1557 
1558     LeaveCriticalSection(&ddraw_cs);
1559     return D3D_OK;
1560 }
1561 
1562 /*****************************************************************************
1563  * IDirect3DDevice::DeleteMatrix
1564  *
1565  * Destroys a Matrix handle. Frees the memory and unsets the handle data
1566  *
1567  * Version 1 only
1568  *
1569  * Params:
1570  *  D3DMatHandle: Handle to destroy
1571  *
1572  * Returns:
1573  *  D3D_OK on success
1574  *  DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1575  *
1576  *****************************************************************************/
1577 static HRESULT WINAPI
1578 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1579                                    D3DMATRIXHANDLE D3DMatHandle)
1580 {
1581     IDirect3DDeviceImpl *This = device_from_device1(iface);
1582     TRACE("(%p)->(%08x)\n", This, D3DMatHandle);
1583 
1584     if(!D3DMatHandle)
1585         return DDERR_INVALIDPARAMS;
1586 
1587     EnterCriticalSection(&ddraw_cs);
1588     if(D3DMatHandle > This->numHandles)
1589     {
1590         ERR("Handle %d out of range\n", D3DMatHandle);
1591         LeaveCriticalSection(&ddraw_cs);
1592         return DDERR_INVALIDPARAMS;
1593     }
1594     else if(This->Handles[D3DMatHandle - 1].type != DDrawHandle_Matrix)
1595     {
1596         ERR("Handle %d is not a matrix handle\n", D3DMatHandle);
1597         LeaveCriticalSection(&ddraw_cs);
1598         return DDERR_INVALIDPARAMS;
1599     }
1600 
1601     HeapFree(GetProcessHeap(), 0, This->Handles[D3DMatHandle - 1].ptr);
1602     This->Handles[D3DMatHandle - 1].ptr = NULL;
1603     This->Handles[D3DMatHandle - 1].type = DDrawHandle_Unknown;
1604 
1605     LeaveCriticalSection(&ddraw_cs);
1606     return D3D_OK;
1607 }
1608 
1609 /*****************************************************************************
1610  * IDirect3DDevice7::BeginScene
1611  *
1612  * This method must be called before any rendering is performed.
1613  * IDirect3DDevice::EndScene has to be called after the scene is complete
1614  *
1615  * Version 1, 2, 3 and 7
1616  *
1617  * Returns:
1618  *  D3D_OK on success, for details see IWineD3DDevice::BeginScene
1619  *  D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1620  *  started scene).
1621  *
1622  *****************************************************************************/
1623 static HRESULT
1624 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1625 {
1626     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1627     HRESULT hr;
1628     TRACE("(%p): Relay\n", This);
1629 
1630     EnterCriticalSection(&ddraw_cs);
1631     hr = IWineD3DDevice_BeginScene(This->wineD3DDevice);
1632     LeaveCriticalSection(&ddraw_cs);
1633     if(hr == WINED3D_OK) return D3D_OK;
1634     else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1635 }
1636 
1637 static HRESULT WINAPI
1638 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1639 {
1640     return IDirect3DDeviceImpl_7_BeginScene(iface);
1641 }
1642 
1643 static HRESULT WINAPI
1644 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1645 {
1646     HRESULT hr;
1647     WORD old_fpucw;
1648 
1649     old_fpucw = d3d_fpu_setup();
1650     hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1651     set_fpu_control_word(old_fpucw);
1652 
1653     return hr;
1654 }
1655 
1656 static HRESULT WINAPI
1657 Thunk_IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1658 {
1659     IDirect3DDeviceImpl *This = device_from_device3(iface);
1660     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1661     return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)This);
1662 }
1663 
1664 static HRESULT WINAPI
1665 Thunk_IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1666 {
1667     IDirect3DDeviceImpl *This = device_from_device2(iface);
1668     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1669     return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)This);
1670 }
1671 
1672 static HRESULT WINAPI
1673 Thunk_IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1674 {
1675     IDirect3DDeviceImpl *This = device_from_device1(iface);
1676     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1677     return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)This);
1678 }
1679 
1680 /*****************************************************************************
1681  * IDirect3DDevice7::EndScene
1682  *
1683  * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1684  * This method must be called after rendering is finished.
1685  *
1686  * Version 1, 2, 3 and 7
1687  *
1688  * Returns:
1689  *  D3D_OK on success, for details see IWineD3DDevice::EndScene
1690  *  D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1691  *  that only if the scene was already ended.
1692  *
1693  *****************************************************************************/
1694 static HRESULT
1695 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1696 {
1697     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1698     HRESULT hr;
1699     TRACE("(%p): Relay\n", This);
1700 
1701     EnterCriticalSection(&ddraw_cs);
1702     hr = IWineD3DDevice_EndScene(This->wineD3DDevice);
1703     LeaveCriticalSection(&ddraw_cs);
1704     if(hr == WINED3D_OK) return D3D_OK;
1705     else return D3DERR_SCENE_NOT_IN_SCENE;
1706 }
1707 
1708 static HRESULT WINAPI DECLSPEC_HOTPATCH
1709 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1710 {
1711     return IDirect3DDeviceImpl_7_EndScene(iface);
1712 }
1713 
1714 static HRESULT WINAPI DECLSPEC_HOTPATCH
1715 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1716 {
1717     HRESULT hr;
1718     WORD old_fpucw;
1719 
1720     old_fpucw = d3d_fpu_setup();
1721     hr = IDirect3DDeviceImpl_7_EndScene(iface);
1722     set_fpu_control_word(old_fpucw);
1723 
1724     return hr;
1725 }
1726 
1727 static HRESULT WINAPI DECLSPEC_HOTPATCH
1728 Thunk_IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1729 {
1730     IDirect3DDeviceImpl *This = device_from_device3(iface);
1731     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1732     return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)This);
1733 }
1734 
1735 static HRESULT WINAPI DECLSPEC_HOTPATCH
1736 Thunk_IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1737 {
1738     IDirect3DDeviceImpl *This = device_from_device2(iface);
1739     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1740     return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)This);
1741 }
1742 
1743 static HRESULT WINAPI DECLSPEC_HOTPATCH
1744 Thunk_IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1745 {
1746     IDirect3DDeviceImpl *This = device_from_device1(iface);
1747     TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1748     return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)This);
1749 }
1750 
1751 /*****************************************************************************
1752  * IDirect3DDevice7::GetDirect3D
1753  *
1754  * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1755  * this device.
1756  *
1757  * Params:
1758  *  Direct3D7: Address to store the interface pointer at
1759  *
1760  * Returns:
1761  *  D3D_OK on success
1762  *  DDERR_INVALIDPARAMS if Direct3D7 == NULL
1763  *
1764  *****************************************************************************/
1765 static HRESULT WINAPI
1766 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1767                                   IDirect3D7 **Direct3D7)
1768 {
1769     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1770     TRACE("(%p)->(%p)\n", This, Direct3D7);
1771 
1772     if(!Direct3D7)
1773         return DDERR_INVALIDPARAMS;
1774 
1775     *Direct3D7 = (IDirect3D7 *)&This->ddraw->IDirect3D7_vtbl;
1776     IDirect3D7_AddRef(*Direct3D7);
1777 
1778     TRACE(" returning interface %p\n", *Direct3D7);
1779     return D3D_OK;
1780 }
1781 
1782 static HRESULT WINAPI
1783 Thunk_IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1784                                         IDirect3D3 **Direct3D3)
1785 {
1786     IDirect3DDeviceImpl *This = device_from_device3(iface);
1787     HRESULT ret;
1788     IDirect3D7 *ret_ptr;
1789 
1790     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Direct3D3);
1791     ret = IDirect3DDevice7_GetDirect3D((IDirect3DDevice7 *)This, &ret_ptr);
1792     if(ret != D3D_OK)
1793         return ret;
1794     *Direct3D3 = ret_ptr ? (IDirect3D3 *)&ddraw_from_d3d7(ret_ptr)->IDirect3D3_vtbl : NULL;
1795     TRACE(" returning interface %p\n", *Direct3D3);
1796     return D3D_OK;
1797 }
1798 
1799 static HRESULT WINAPI
1800 Thunk_IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1801                                         IDirect3D2 **Direct3D2)
1802 {
1803     IDirect3DDeviceImpl *This = device_from_device2(iface);
1804     HRESULT ret;
1805     IDirect3D7 *ret_ptr;
1806 
1807     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Direct3D2);
1808     ret = IDirect3DDevice7_GetDirect3D((IDirect3DDevice7 *)This, &ret_ptr);
1809     if(ret != D3D_OK)
1810         return ret;
1811     *Direct3D2 = ret_ptr ? (IDirect3D2 *)&ddraw_from_d3d7(ret_ptr)->IDirect3D2_vtbl : NULL;
1812     TRACE(" returning interface %p\n", *Direct3D2);
1813     return D3D_OK;
1814 }
1815 
1816 static HRESULT WINAPI
1817 Thunk_IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1818                                         IDirect3D **Direct3D)
1819 {
1820     IDirect3DDeviceImpl *This = device_from_device1(iface);
1821     HRESULT ret;
1822     IDirect3D7 *ret_ptr;
1823 
1824     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Direct3D);
1825     ret = IDirect3DDevice7_GetDirect3D((IDirect3DDevice7 *)This, &ret_ptr);
1826     if(ret != D3D_OK)
1827         return ret;
1828     *Direct3D = ret_ptr ? (IDirect3D *)&ddraw_from_d3d7(ret_ptr)->IDirect3D_vtbl : NULL;
1829     TRACE(" returning interface %p\n", *Direct3D);
1830     return D3D_OK;
1831 }
1832 
1833 /*****************************************************************************
1834  * IDirect3DDevice3::SetCurrentViewport
1835  *
1836  * Sets a Direct3DViewport as the current viewport.
1837  * For the thunks note that all viewport interface versions are equal
1838  *
1839  * Params:
1840  *  Direct3DViewport3: The viewport to set
1841  *
1842  * Version 2 and 3
1843  *
1844  * Returns:
1845  *  D3D_OK on success
1846  *  (Is a NULL viewport valid?)
1847  *
1848  *****************************************************************************/
1849 static HRESULT WINAPI
1850 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1851                                          IDirect3DViewport3 *Direct3DViewport3)
1852 {
1853     IDirect3DDeviceImpl *This = device_from_device3(iface);
1854     IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport3;
1855     TRACE("(%p)->(%p)\n", This, Direct3DViewport3);
1856 
1857     EnterCriticalSection(&ddraw_cs);
1858     /* Do nothing if the specified viewport is the same as the current one */
1859     if (This->current_viewport == vp )
1860     {
1861         LeaveCriticalSection(&ddraw_cs);
1862         return D3D_OK;
1863     }
1864 
1865     /* Should check if the viewport was added or not */
1866 
1867     /* Release previous viewport and AddRef the new one */
1868     if (This->current_viewport)
1869     {
1870         TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1871                 (IDirect3DViewport3 *)This->current_viewport);
1872         IDirect3DViewport3_Release((IDirect3DViewport3 *)This->current_viewport);
1873     }
1874     IDirect3DViewport3_AddRef(Direct3DViewport3);
1875 
1876     /* Set this viewport as the current viewport */
1877     This->current_viewport = vp;
1878 
1879     /* Activate this viewport */
1880     This->current_viewport->active_device = This;
1881     This->current_viewport->activate(This->current_viewport, FALSE);
1882 
1883     LeaveCriticalSection(&ddraw_cs);
1884     return D3D_OK;
1885 }
1886 
1887 static HRESULT WINAPI
1888 Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1889                                                IDirect3DViewport2 *Direct3DViewport2)
1890 {
1891     IDirect3DDeviceImpl *This = device_from_device2(iface);
1892     IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
1893     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
1894     return IDirect3DDevice3_SetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1895             (IDirect3DViewport3 *)vp);
1896 }
1897 
1898 /*****************************************************************************
1899  * IDirect3DDevice3::GetCurrentViewport
1900  *
1901  * Returns the currently active viewport.
1902  *
1903  * Version 2 and 3
1904  *
1905  * Params:
1906  *  Direct3DViewport3: Address to return the interface pointer at
1907  *
1908  * Returns:
1909  *  D3D_OK on success
1910  *  DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1911  *
1912  *****************************************************************************/
1913 static HRESULT WINAPI
1914 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1915                                          IDirect3DViewport3 **Direct3DViewport3)
1916 {
1917     IDirect3DDeviceImpl *This = device_from_device3(iface);
1918     TRACE("(%p)->(%p)\n", This, Direct3DViewport3);
1919 
1920     if(!Direct3DViewport3)
1921         return DDERR_INVALIDPARAMS;
1922 
1923     EnterCriticalSection(&ddraw_cs);
1924     *Direct3DViewport3 = (IDirect3DViewport3 *)This->current_viewport;
1925 
1926     /* AddRef the returned viewport */
1927     if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1928 
1929     TRACE(" returning interface %p\n", *Direct3DViewport3);
1930 
1931     LeaveCriticalSection(&ddraw_cs);
1932     return D3D_OK;
1933 }
1934 
1935 static HRESULT WINAPI
1936 Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1937                                                IDirect3DViewport2 **Direct3DViewport2)
1938 {
1939     IDirect3DDeviceImpl *This = device_from_device2(iface);
1940     HRESULT hr;
1941     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, Direct3DViewport2);
1942     hr = IDirect3DDevice3_GetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1943             (IDirect3DViewport3 **)Direct3DViewport2);
1944     if(hr != D3D_OK) return hr;
1945     return D3D_OK;
1946 }
1947 
1948 /*****************************************************************************
1949  * IDirect3DDevice7::SetRenderTarget
1950  *
1951  * Sets the render target for the Direct3DDevice.
1952  * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1953  * IDirectDrawSurface3 == IDirectDrawSurface
1954  *
1955  * Version 2, 3 and 7
1956  *
1957  * Params:
1958  *  NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1959  *             render target
1960  *  Flags: Some flags
1961  *
1962  * Returns:
1963  *  D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1964  *
1965  *****************************************************************************/
1966 static HRESULT
1967 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1968                                       IDirectDrawSurface7 *NewTarget,
1969                                       DWORD Flags)
1970 {
1971     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1972     IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewTarget;
1973     HRESULT hr;
1974     TRACE("(%p)->(%p,%08x): Relay\n", This, NewTarget, Flags);
1975 
1976     EnterCriticalSection(&ddraw_cs);
1977     /* Flags: Not used */
1978 
1979     if(This->target == Target)
1980     {
1981         TRACE("No-op SetRenderTarget operation, not doing anything\n");
1982         LeaveCriticalSection(&ddraw_cs);
1983         return D3D_OK;
1984     }
1985 
1986     hr = IWineD3DDevice_SetRenderTarget(This->wineD3DDevice,
1987                                         0,
1988                                         Target ? Target->WineD3DSurface : NULL,
1989                                         FALSE);
1990     if(hr != D3D_OK)
1991     {
1992         LeaveCriticalSection(&ddraw_cs);
1993         return hr;
1994     }
1995     IDirectDrawSurface7_AddRef(NewTarget);
1996     IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->target);
1997     This->target = Target;
1998     IDirect3DDeviceImpl_UpdateDepthStencil(This);
1999     LeaveCriticalSection(&ddraw_cs);
2000     return D3D_OK;
2001 }
2002 
2003 static HRESULT WINAPI
2004 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
2005                                       IDirectDrawSurface7 *NewTarget,
2006                                       DWORD Flags)
2007 {
2008     return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
2009 }
2010 
2011 static HRESULT WINAPI
2012 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
2013                                       IDirectDrawSurface7 *NewTarget,
2014                                       DWORD Flags)
2015 {
2016     HRESULT hr;
2017     WORD old_fpucw;
2018 
2019     old_fpucw = d3d_fpu_setup();
2020     hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
2021     set_fpu_control_word(old_fpucw);
2022 
2023     return hr;
2024 }
2025 
2026 static HRESULT WINAPI
2027 Thunk_IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
2028                                             IDirectDrawSurface4 *NewRenderTarget,
2029                                             DWORD Flags)
2030 {
2031     IDirect3DDeviceImpl *This = device_from_device3(iface);
2032     IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
2033     TRACE_(ddraw_thunk)("(%p)->(%p,%08x) thunking to IDirect3DDevice7 interface.\n", This, Target, Flags);
2034     return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
2035 }
2036 
2037 static HRESULT WINAPI
2038 Thunk_IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
2039                                             IDirectDrawSurface *NewRenderTarget,
2040                                             DWORD Flags)
2041 {
2042     IDirect3DDeviceImpl *This = device_from_device2(iface);
2043     IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
2044     TRACE_(ddraw_thunk)("(%p)->(%p,%08x) thunking to IDirect3DDevice7 interface.\n", This, Target, Flags);
2045     return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
2046 }
2047 
2048 /*****************************************************************************
2049  * IDirect3DDevice7::GetRenderTarget
2050  *
2051  * Returns the current render target.
2052  * This is handled locally, because the WineD3D render target's parent
2053  * is an IParent
2054  *
2055  * Version 2, 3 and 7
2056  *
2057  * Params:
2058  *  RenderTarget: Address to store the surface interface pointer
2059  *
2060  * Returns:
2061  *  D3D_OK on success
2062  *  DDERR_INVALIDPARAMS if RenderTarget == NULL
2063  *
2064  *****************************************************************************/
2065 static HRESULT WINAPI
2066 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
2067                                       IDirectDrawSurface7 **RenderTarget)
2068 {
2069     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2070     TRACE("(%p)->(%p): Relay\n", This, RenderTarget);
2071 
2072     if(!RenderTarget)
2073         return DDERR_INVALIDPARAMS;
2074 
2075     EnterCriticalSection(&ddraw_cs);
2076     *RenderTarget = (IDirectDrawSurface7 *)This->target;
2077     IDirectDrawSurface7_AddRef(*RenderTarget);
2078 
2079     LeaveCriticalSection(&ddraw_cs);
2080     return D3D_OK;
2081 }
2082 
2083 static HRESULT WINAPI
2084 Thunk_IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
2085                                             IDirectDrawSurface4 **RenderTarget)
2086 {
2087     IDirect3DDeviceImpl *This = device_from_device3(iface);
2088     HRESULT hr;
2089     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, RenderTarget);
2090     hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
2091     if(hr != D3D_OK) return hr;
2092     return D3D_OK;
2093 }
2094 
2095 static HRESULT WINAPI
2096 Thunk_IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
2097                                             IDirectDrawSurface **RenderTarget)
2098 {
2099     IDirect3DDeviceImpl *This = device_from_device2(iface);
2100     HRESULT hr;
2101     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, RenderTarget);
2102     hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
2103     if(hr != D3D_OK) return hr;
2104     *RenderTarget = *RenderTarget ?
2105             (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)*RenderTarget)->IDirectDrawSurface3_vtbl : NULL;
2106     return D3D_OK;
2107 }
2108 
2109 /*****************************************************************************
2110  * IDirect3DDevice3::Begin
2111  *
2112  * Begins a description block of vertices. This is similar to glBegin()
2113  * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2114  * described with IDirect3DDevice::Vertex are drawn.
2115  *
2116  * Version 2 and 3
2117  *
2118  * Params:
2119  *  PrimitiveType: The type of primitives to draw
2120  *  VertexTypeDesc: A flexible vertex format description of the vertices
2121  *  Flags: Some flags..
2122  *
2123  * Returns:
2124  *  D3D_OK on success
2125  *
2126  *****************************************************************************/
2127 static HRESULT WINAPI
2128 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2129                             D3DPRIMITIVETYPE PrimitiveType,
2130                             DWORD VertexTypeDesc,
2131                             DWORD Flags)
2132 {
2133     IDirect3DDeviceImpl *This = device_from_device3(iface);
2134     TRACE("(%p)->(%d,%d,%08x)\n", This, PrimitiveType, VertexTypeDesc, Flags);
2135 
2136     EnterCriticalSection(&ddraw_cs);
2137     This->primitive_type = PrimitiveType;
2138     This->vertex_type = VertexTypeDesc;
2139     This->render_flags = Flags;
2140     This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2141     This->nb_vertices = 0;
2142     LeaveCriticalSection(&ddraw_cs);
2143 
2144     return D3D_OK;
2145 }
2146 
2147 static HRESULT WINAPI
2148 Thunk_IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface,
2149                                   D3DPRIMITIVETYPE d3dpt,
2150                                   D3DVERTEXTYPE dwVertexTypeDesc,
2151                                   DWORD dwFlags)
2152 {
2153     DWORD FVF;
2154     IDirect3DDeviceImpl *This = device_from_device2(iface);
2155     TRACE_(ddraw_thunk)("(%p/%p)->(%08x,%08x,%08x): Thunking to IDirect3DDevice3\n", This, iface, d3dpt, dwVertexTypeDesc, dwFlags);
2156 
2157     switch(dwVertexTypeDesc)
2158     {
2159         case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2160         case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2161         case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2162         default:
2163             ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2164             return DDERR_INVALIDPARAMS;  /* Should never happen */
2165     };
2166 
2167     return IDirect3DDevice3_Begin((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, d3dpt, FVF, dwFlags);
2168 }
2169 
2170 /*****************************************************************************
2171  * IDirect3DDevice3::BeginIndexed
2172  *
2173  * Draws primitives based on vertices in a vertex array which are specified
2174  * by indices.
2175  *
2176  * Version 2 and 3
2177  *
2178  * Params:
2179  *  PrimitiveType: Primitive type to draw
2180  *  VertexType: A FVF description of the vertex format
2181  *  Vertices: pointer to an array containing the vertices
2182  *  NumVertices: The number of vertices in the vertex array
2183  *  Flags: Some flags ...
2184  *
2185  * Returns:
2186  *  D3D_OK, because it's a stub
2187  *
2188  *****************************************************************************/
2189 static HRESULT WINAPI
2190 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2191                                    D3DPRIMITIVETYPE PrimitiveType,
2192                                    DWORD VertexType,
2193                                    void *Vertices,
2194                                    DWORD NumVertices,
2195                                    DWORD Flags)
2196 {
2197     IDirect3DDeviceImpl *This = device_from_device3(iface);
2198     FIXME("(%p)->(%08x,%08x,%p,%08x,%08x): stub!\n", This, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2199     return D3D_OK;
2200 }
2201 
2202 
2203 static HRESULT WINAPI
2204 Thunk_IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2205                                          D3DPRIMITIVETYPE d3dptPrimitiveType,
2206                                          D3DVERTEXTYPE d3dvtVertexType,
2207                                          void *lpvVertices,
2208                                          DWORD dwNumVertices,
2209                                          DWORD dwFlags)
2210 {
2211     DWORD FVF;
2212     IDirect3DDeviceImpl *This = device_from_device2(iface);
2213     TRACE_(ddraw_thunk)("(%p/%p)->(%08x,%08x,%p,%08x,%08x): Thunking to IDirect3DDevice3\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2214 
2215     switch(d3dvtVertexType)
2216     {
2217         case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2218         case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2219         case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2220         default:
2221             ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2222             return DDERR_INVALIDPARAMS;  /* Should never happen */
2223     };
2224 
2225     return IDirect3DDevice3_BeginIndexed((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2226             d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2227 }
2228 
2229 /*****************************************************************************
2230  * IDirect3DDevice3::Vertex
2231  *
2232  * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2233  * drawn vertices in a vertex buffer. If the buffer is too small, its
2234  * size is increased.
2235  *
2236  * Version 2 and 3
2237  *
2238  * Params:
2239  *  Vertex: Pointer to the vertex
2240  *
2241  * Returns:
2242  *  D3D_OK, on success
2243  *  DDERR_INVALIDPARAMS if Vertex is NULL
2244  *
2245  *****************************************************************************/
2246 static HRESULT WINAPI
2247 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2248                              void *Vertex)
2249 {
2250     IDirect3DDeviceImpl *This = device_from_device3(iface);
2251     TRACE("(%p)->(%p)\n", This, Vertex);
2252 
2253     if(!Vertex)
2254         return DDERR_INVALIDPARAMS;
2255 
2256     EnterCriticalSection(&ddraw_cs);
2257     if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2258     {
2259         BYTE *old_buffer;
2260         This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2261         old_buffer = This->vertex_buffer;
2262         This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2263         if (old_buffer)
2264         {
2265             CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2266             HeapFree(GetProcessHeap(), 0, old_buffer);
2267         }
2268     }
2269 
2270     CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2271 
2272     LeaveCriticalSection(&ddraw_cs);
2273     return D3D_OK;
2274 }
2275 
2276 static HRESULT WINAPI
2277 Thunk_IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface,
2278                                    void *lpVertexType)
2279 {
2280     IDirect3DDeviceImpl *This = device_from_device2(iface);
2281     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, lpVertexType);
2282     return IDirect3DDevice3_Vertex((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, lpVertexType);
2283 }
2284 
2285 /*****************************************************************************
2286  * IDirect3DDevice3::Index
2287  *
2288  * Specifies an index to a vertex to be drawn. The vertex array has to
2289  * be specified with BeginIndexed first.
2290  *
2291  * Parameters:
2292  *  VertexIndex: The index of the vertex to draw
2293  *
2294  * Returns:
2295  *  D3D_OK because it's a stub
2296  *
2297  *****************************************************************************/
2298 static HRESULT WINAPI
2299 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2300                             WORD VertexIndex)
2301 {
2302     IDirect3DDeviceImpl *This = device_from_device3(iface);
2303     FIXME("(%p)->(%04x): stub!\n", This, VertexIndex);
2304     return D3D_OK;
2305 }
2306 
2307 static HRESULT WINAPI
2308 Thunk_IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface,
2309                                   WORD wVertexIndex)
2310 {
2311     IDirect3DDeviceImpl *This = device_from_device2(iface);
2312     TRACE_(ddraw_thunk)("(%p)->(%04x) thunking to IDirect3DDevice3 interface.\n", This, wVertexIndex);
2313     return IDirect3DDevice3_Index((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, wVertexIndex);
2314 }
2315 
2316 /*****************************************************************************
2317  * IDirect3DDevice3::End
2318  *
2319  * Ends a draw begun with IDirect3DDevice3::Begin or
2320  * IDirect3DDevice::BeginIndexed. The vertices specified with
2321  * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2322  * the IDirect3DDevice7::DrawPrimitive method. So far only
2323  * non-indexed mode is supported
2324  *
2325  * Version 2 and 3
2326  *
2327  * Params:
2328  *  Flags: Some flags, as usual. Don't know which are defined
2329  *
2330  * Returns:
2331  *  The return value of IDirect3DDevice7::DrawPrimitive
2332  *
2333  *****************************************************************************/
2334 static HRESULT WINAPI
2335 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2336                           DWORD Flags)
2337 {
2338     IDirect3DDeviceImpl *This = device_from_device3(iface);
2339     TRACE("(%p)->(%08x)\n", This, Flags);
2340 
2341     return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This, This->primitive_type,
2342             This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2343 }
2344 
2345 static HRESULT WINAPI
2346 Thunk_IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface,
2347                                 DWORD dwFlags)
2348 {
2349     IDirect3DDeviceImpl *This = device_from_device2(iface);
2350     TRACE_(ddraw_thunk)("(%p)->(%08x) thunking to IDirect3DDevice3 interface.\n", This, dwFlags);
2351     return IDirect3DDevice3_End((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, dwFlags);
2352 }
2353 
2354 /*****************************************************************************
2355  * IDirect3DDevice7::GetRenderState
2356  *
2357  * Returns the value of a render state. The possible render states are
2358  * defined in include/d3dtypes.h
2359  *
2360  * Version 2, 3 and 7
2361  *
2362  * Params:
2363  *  RenderStateType: Render state to return the current setting of
2364  *  Value: Address to store the value at
2365  *
2366  * Returns:
2367  *  D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2368  *  DDERR_INVALIDPARAMS if Value == NULL
2369  *
2370  *****************************************************************************/
2371 static HRESULT
2372 IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2373                                      D3DRENDERSTATETYPE RenderStateType,
2374                                      DWORD *Value)
2375 {
2376     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2377     HRESULT hr;
2378     TRACE("(%p)->(%08x,%p): Relay\n", This, RenderStateType, Value);
2379 
2380     if(!Value)
2381         return DDERR_INVALIDPARAMS;
2382 
2383     EnterCriticalSection(&ddraw_cs);
2384     switch(RenderStateType)
2385     {
2386         case D3DRENDERSTATE_TEXTUREMAG:
2387         {
2388             WINED3DTEXTUREFILTERTYPE tex_mag;
2389 
2390             hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2391                                                 0, WINED3DSAMP_MAGFILTER,
2392                                                 &tex_mag);
2393 
2394             switch (tex_mag)
2395             {
2396                 case WINED3DTEXF_POINT:
2397                     *Value = D3DFILTER_NEAREST;
2398                     break;
2399                 case WINED3DTEXF_LINEAR:
2400                     *Value = D3DFILTER_LINEAR;
2401                     break;
2402                 default:
2403                     ERR("Unhandled texture mag %d !\n",tex_mag);
2404                     *Value = 0;
2405             }
2406             break;
2407         }
2408 
2409         case D3DRENDERSTATE_TEXTUREMIN:
2410         {
2411             WINED3DTEXTUREFILTERTYPE tex_min;
2412 
2413             hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2414                                                 0, WINED3DSAMP_MINFILTER,
2415                                                 &tex_min);
2416 
2417             switch (tex_min)
2418             {
2419                 case WINED3DTEXF_POINT:
2420                     *Value = D3DFILTER_NEAREST;
2421                     break;
2422                 case WINED3DTEXF_LINEAR:
2423                     *Value = D3DFILTER_LINEAR;
2424                     break;
2425                 default:
2426                     ERR("Unhandled texture mag %d !\n",tex_min);
2427                     *Value = 0;
2428             }
2429             break;
2430         }
2431 
2432         case D3DRENDERSTATE_TEXTUREADDRESS:
2433         case D3DRENDERSTATE_TEXTUREADDRESSU:
2434             hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2435                                                 0, WINED3DSAMP_ADDRESSU,
2436                                                 Value);
2437             break;
2438         case D3DRENDERSTATE_TEXTUREADDRESSV:
2439             hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2440                                                 0, WINED3DSAMP_ADDRESSV,
2441                                                 Value);
2442             break;
2443 
2444         default:
2445             /* FIXME: Unhandled: D3DRENDERSTATE_STIPPLEPATTERN00 - 31 */
2446             hr = IWineD3DDevice_GetRenderState(This->wineD3DDevice,
2447                                                RenderStateType,
2448                                                Value);
2449     }
2450     LeaveCriticalSection(&ddraw_cs);
2451     return hr;
2452 }
2453 
2454 static HRESULT WINAPI
2455 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2456                                      D3DRENDERSTATETYPE RenderStateType,
2457                                      DWORD *Value)
2458 {
2459     return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2460 }
2461 
2462 static HRESULT WINAPI
2463 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2464                                      D3DRENDERSTATETYPE RenderStateType,
2465                                      DWORD *Value)
2466 {
2467     HRESULT hr;
2468     WORD old_fpucw;
2469 
2470     old_fpucw = d3d_fpu_setup();
2471     hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2472     set_fpu_control_word(old_fpucw);
2473 
2474     return hr;
2475 }
2476 
2477 static HRESULT WINAPI
2478 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2479                                      D3DRENDERSTATETYPE dwRenderStateType,
2480                                      DWORD *lpdwRenderState)
2481 {
2482     IDirect3DDeviceImpl *This = device_from_device3(iface);
2483     HRESULT hr;
2484     TRACE("(%p)->(%08x,%p)\n", This, dwRenderStateType, lpdwRenderState);
2485 
2486     switch(dwRenderStateType)
2487     {
2488         case D3DRENDERSTATE_TEXTUREHANDLE:
2489         {
2490             /* This state is wrapped to SetTexture in SetRenderState, so
2491              * it has to be wrapped to GetTexture here
2492              */
2493             IWineD3DBaseTexture *tex = NULL;
2494             *lpdwRenderState = 0;
2495 
2496             EnterCriticalSection(&ddraw_cs);
2497 
2498             hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2499                                            0,
2500                                            &tex);
2501 
2502             if(hr == WINED3D_OK && tex)
2503             {
2504                 IDirectDrawSurface7 *parent = NULL;
2505                 hr = IWineD3DBaseTexture_GetParent(tex,
2506                                                    (IUnknown **) &parent);
2507                 if(parent)
2508                 {
2509                     /* The parent of the texture is the IDirectDrawSurface7 interface
2510                      * of the ddraw surface
2511                      */
2512                     IDirectDrawSurfaceImpl *texImpl = (IDirectDrawSurfaceImpl *)parent;
2513                     *lpdwRenderState = texImpl->Handle;
2514                     IDirectDrawSurface7_Release(parent);
2515                 }
2516                 IWineD3DBaseTexture_Release(tex);
2517             }
2518 
2519             LeaveCriticalSection(&ddraw_cs);
2520 
2521             return hr;
2522         }
2523 
2524         case D3DRENDERSTATE_TEXTUREMAPBLEND:
2525         {
2526             /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2527                the mapping to get the value. */
2528             DWORD colorop, colorarg1, colorarg2;
2529             DWORD alphaop, alphaarg1, alphaarg2;
2530 
2531             EnterCriticalSection(&ddraw_cs);
2532 
2533             This->legacyTextureBlending = TRUE;
2534 
2535             IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, &colorop);
2536             IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, &colorarg1);
2537             IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, &colorarg2);
2538             IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, &alphaop);
2539             IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2540             IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2541 
2542             if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2543                 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2544             {
2545                 *lpdwRenderState = D3DTBLEND_DECAL;
2546             }
2547             else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2548                 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2549             {
2550                 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2551             }
2552             else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2553                 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2554             {
2555                 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2556             }
2557             else
2558             {
2559                 HRESULT hr;
2560                 BOOL tex_alpha = FALSE;
2561                 IWineD3DBaseTexture *tex = NULL;
2562                 WINED3DSURFACE_DESC desc;
2563                 DDPIXELFORMAT ddfmt;
2564 
2565                 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2566                                             0,
2567                                             &tex);
2568 
2569                 if(hr == WINED3D_OK && tex)
2570                 {
2571                     hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2572                     if (SUCCEEDED(hr))
2573                     {
2574                         ddfmt.dwSize = sizeof(ddfmt);
2575                         PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2576                         if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2577                     }
2578 
2579                     IWineD3DBaseTexture_Release(tex);
2580                 }
2581 
2582                 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2583                       alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == (tex_alpha ? WINED3DTA_TEXTURE : WINED3DTA_CURRENT)))
2584                 {
2585                     ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2586                 }
2587 
2588                 *lpdwRenderState = D3DTBLEND_MODULATE;
2589             }
2590 
2591             LeaveCriticalSection(&ddraw_cs);
2592 
2593             return D3D_OK;
2594         }
2595 
2596         default:
2597             return IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, dwRenderStateType, lpdwRenderState);
2598     }
2599 }
2600 
2601 static HRESULT WINAPI
2602 Thunk_IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2603                                            D3DRENDERSTATETYPE dwRenderStateType,
2604                                            DWORD *lpdwRenderState)
2605 {
2606     IDirect3DDeviceImpl *This = device_from_device2(iface);
2607     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice3 interface.\n", This, dwRenderStateType, lpdwRenderState);
2608     return IDirect3DDevice3_GetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2609             dwRenderStateType, lpdwRenderState);
2610 }
2611 
2612 /*****************************************************************************
2613  * IDirect3DDevice7::SetRenderState
2614  *
2615  * Sets a render state. The possible render states are defined in
2616  * include/d3dtypes.h
2617  *
2618  * Version 2, 3 and 7
2619  *
2620  * Params:
2621  *  RenderStateType: State to set
2622  *  Value: Value to assign to that state
2623  *
2624  * Returns:
2625  *  D3D_OK on success,
2626  *  for details see IWineD3DDevice::SetRenderState
2627  *
2628  *****************************************************************************/
2629 static HRESULT
2630 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2631                                      D3DRENDERSTATETYPE RenderStateType,
2632                                      DWORD Value)
2633 {
2634     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2635     HRESULT hr;
2636     TRACE("(%p)->(%08x,%d): Relay\n", This, RenderStateType, Value);
2637 
2638     EnterCriticalSection(&ddraw_cs);
2639     /* Some render states need special care */
2640     switch(RenderStateType)
2641     {
2642         case D3DRENDERSTATE_TEXTUREMAG:
2643         {
2644             WINED3DTEXTUREFILTERTYPE tex_mag = WINED3DTEXF_POINT;
2645 
2646             switch ((D3DTEXTUREFILTER) Value)
2647             {
2648                 case D3DFILTER_NEAREST:
2649                 case D3DFILTER_LINEARMIPNEAREST:
2650                     tex_mag = WINED3DTEXF_POINT;
2651                     break;
2652                 case D3DFILTER_LINEAR:
2653                 case D3DFILTER_LINEARMIPLINEAR:
2654                     tex_mag = WINED3DTEXF_LINEAR;
2655                     break;
2656                 default:
2657                     ERR("Unhandled texture mag %d !\n",Value);
2658             }
2659 
2660             hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2661                                                 0, WINED3DSAMP_MAGFILTER,
2662                                                 tex_mag);
2663             break;
2664         }
2665 
2666         case D3DRENDERSTATE_TEXTUREMIN:
2667         {
2668             WINED3DTEXTUREFILTERTYPE tex_min = WINED3DTEXF_POINT;
2669             WINED3DTEXTUREFILTERTYPE tex_mip = WINED3DTEXF_NONE;
2670 
2671             switch ((D3DTEXTUREFILTER) Value)
2672             {
2673                 case D3DFILTER_NEAREST:
2674                     tex_min = WINED3DTEXF_POINT;
2675                     break;
2676                 case D3DFILTER_LINEAR:
2677                     tex_min = WINED3DTEXF_LINEAR;
2678                     break;
2679                 case D3DFILTER_MIPNEAREST:
2680                     tex_min = WINED3DTEXF_POINT;
2681                     tex_mip = WINED3DTEXF_POINT;
2682                     break;
2683                 case D3DFILTER_MIPLINEAR:
2684                     tex_min = WINED3DTEXF_POINT;
2685                     tex_mip = WINED3DTEXF_LINEAR;
2686                     break;
2687                 case D3DFILTER_LINEARMIPNEAREST:
2688                     tex_min = WINED3DTEXF_POINT;
2689                     tex_mip = WINED3DTEXF_LINEAR;
2690                     break;
2691                 case D3DFILTER_LINEARMIPLINEAR:
2692                     tex_min = WINED3DTEXF_LINEAR;
2693                     tex_mip = WINED3DTEXF_LINEAR;
2694                     break;
2695 
2696                 default:
2697                     ERR("Unhandled texture min %d !\n",Value);
2698             }
2699 
2700                    IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2701                                                   0, WINED3DSAMP_MIPFILTER,
2702                                                   tex_mip);
2703             hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2704                                                 0, WINED3DSAMP_MINFILTER,
2705                                                 tex_min);
2706             break;
2707         }
2708 
2709         case D3DRENDERSTATE_TEXTUREADDRESS:
2710                    IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2711                                                   0, WINED3DSAMP_ADDRESSV,
2712                                                   Value);
2713             /* Drop through */
2714         case D3DRENDERSTATE_TEXTUREADDRESSU:
2715             hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2716                                                 0, WINED3DSAMP_ADDRESSU,
2717                                                 Value);
2718             break;
2719         case D3DRENDERSTATE_TEXTUREADDRESSV:
2720             hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2721                                                 0, WINED3DSAMP_ADDRESSV,
2722                                                 Value);
2723             break;
2724 
2725         default:
2726 
2727             /* FIXME: Unhandled: D3DRENDERSTATE_STIPPLEPATTERN00 - 31 */
2728 
2729             hr = IWineD3DDevice_SetRenderState(This->wineD3DDevice,
2730                                                RenderStateType,
2731                                                Value);
2732             break;
2733     }
2734     LeaveCriticalSection(&ddraw_cs);
2735     return hr;
2736 }
2737 
2738 static HRESULT WINAPI
2739 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2740                                      D3DRENDERSTATETYPE RenderStateType,
2741                                      DWORD Value)
2742 {
2743     return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2744 }
2745 
2746 static HRESULT WINAPI
2747 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2748                                      D3DRENDERSTATETYPE RenderStateType,
2749                                      DWORD Value)
2750 {
2751     HRESULT hr;
2752     WORD old_fpucw;
2753 
2754     old_fpucw = d3d_fpu_setup();
2755     hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2756     set_fpu_control_word(old_fpucw);
2757 
2758     return hr;
2759 }
2760 
2761 static HRESULT WINAPI
2762 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2763                                      D3DRENDERSTATETYPE RenderStateType,
2764                                      DWORD Value)
2765 {
2766     /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2767     for this state can be directly mapped to texture stage colorop and alphaop, but
2768     D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2769     from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2770     alphaarg when needed.
2771 
2772     Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2773 
2774     Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2775     TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2776     are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2777     requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2778     with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2779     in device - TRUE if the app is using TEXTUREMAPBLEND.
2780 
2781     Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2782     GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2783     unless some broken game will be found that cares. */
2784 
2785     HRESULT hr;
2786     IDirect3DDeviceImpl *This = device_from_device3(iface);
2787     TRACE("(%p)->(%08x,%d)\n", This, RenderStateType, Value);
2788 
2789     EnterCriticalSection(&ddraw_cs);
2790 
2791     switch(RenderStateType)
2792     {
2793         case D3DRENDERSTATE_TEXTUREHANDLE:
2794         {
2795             if(Value == 0)
2796             {
2797                 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
2798                                                0,
2799                                                NULL);
2800                 break;
2801             }
2802 
2803             if(Value > This->numHandles)
2804             {
2805                 FIXME("Specified handle %d out of range\n", Value);
2806                 hr = DDERR_INVALIDPARAMS;
2807                 break;
2808             }
2809             if(This->Handles[Value - 1].type != DDrawHandle_Texture)
2810             {
2811                 FIXME("Handle %d isn't a texture handle\n", Value);
2812                 hr = DDERR_INVALIDPARAMS;
2813                 break;
2814             }
2815             else
2816             {
2817                 IDirectDrawSurfaceImpl *surf = This->Handles[Value - 1].ptr;
2818                 IDirect3DTexture2 *tex = surf ? (IDirect3DTexture2 *)&surf->IDirect3DTexture2_vtbl : NULL;
2819                 hr = IDirect3DDevice3_SetTexture(iface, 0, tex);
2820                 break;
2821             }
2822         }
2823 
2824         case D3DRENDERSTATE_TEXTUREMAPBLEND:
2825         {
2826             This->legacyTextureBlending = TRUE;
2827 
2828             switch ( (D3DTEXTUREBLEND) Value)
2829             {
2830                 case D3DTBLEND_MODULATE:
2831                 {
2832                     BOOL tex_alpha = FALSE;
2833                     IWineD3DBaseTexture *tex = NULL;
2834                     WINED3DSURFACE_DESC desc;
2835                     DDPIXELFORMAT ddfmt;
2836 
2837                     hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2838                                                 0,
2839                                                 &tex);
2840 
2841                     if(hr == WINED3D_OK && tex)
2842                     {
2843                         memset(&desc, 0, sizeof(desc));
2844                         hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2845                         if (SUCCEEDED(hr))
2846                         {
2847                             ddfmt.dwSize = sizeof(ddfmt);
2848                             PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2849                             if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2850                         }
2851 
2852                         IWineD3DBaseTexture_Release(tex);
2853                     }
2854 
2855                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2856                     if (tex_alpha)
2857                     {
2858                         IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2859                     }
2860                     else
2861                     {
2862                         IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_CURRENT);
2863                     }
2864 
2865                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2866                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2867                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2868 
2869                     break;
2870                 }
2871 
2872                 case D3DTBLEND_ADD:
2873                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2874                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2875                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2876                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2877                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2878                     break;
2879 
2880                 case D3DTBLEND_MODULATEALPHA:
2881                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2882                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2883                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2884                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2885                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2886                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2887                     break;
2888 
2889                 case D3DTBLEND_COPY:
2890                 case D3DTBLEND_DECAL:
2891                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2892                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2893                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2894                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2895                     break;
2896 
2897                 case D3DTBLEND_DECALALPHA:
2898                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2899                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2900                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2901                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2902                     IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2903                     break;
2904 
2905                 default:
2906                     ERR("Unhandled texture environment %d !\n",Value);
2907             }
2908 
2909             hr = D3D_OK;
2910             break;
2911         }
2912 
2913         default:
2914             hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, RenderStateType, Value);
2915             break;
2916     }
2917 
2918     LeaveCriticalSection(&ddraw_cs);
2919 
2920     return hr;
2921 }
2922 
2923 static HRESULT WINAPI
2924 Thunk_IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2925                                            D3DRENDERSTATETYPE RenderStateType,
2926                                            DWORD Value)
2927 {
2928     IDirect3DDeviceImpl *This = device_from_device2(iface);
2929     TRACE_(ddraw_thunk)("(%p)->(%08x,%d) thunking to IDirect3DDevice3 interface.\n", This, RenderStateType, Value);
2930     return IDirect3DDevice3_SetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, RenderStateType, Value);
2931 }
2932 
2933 /*****************************************************************************
2934  * Direct3DDevice3::SetLightState
2935  *
2936  * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2937  * light states are forwarded to Direct3DDevice7 render states
2938  *
2939  * Version 2 and 3
2940  *
2941  * Params:
2942  *  LightStateType: The light state to change
2943  *  Value: The value to assign to that light state
2944  *
2945  * Returns:
2946  *  D3D_OK on success
2947  *  DDERR_INVALIDPARAMS if the parameters were incorrect
2948  *  Also check IDirect3DDevice7::SetRenderState
2949  *
2950  *****************************************************************************/
2951 static HRESULT WINAPI
2952 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
2953                                     D3DLIGHTSTATETYPE LightStateType,
2954                                     DWORD Value)
2955 {
2956     IDirect3DDeviceImpl *This = device_from_device3(iface);
2957     HRESULT hr;
2958 
2959     TRACE("(%p)->(%08x,%08x)\n", This, LightStateType, Value);
2960 
2961     if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2962     {
2963         TRACE("Unexpected Light State Type\n");
2964         return DDERR_INVALIDPARAMS;
2965     }
2966 
2967     EnterCriticalSection(&ddraw_cs);
2968     if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
2969     {
2970         IDirect3DMaterialImpl *mat;
2971 
2972         if(Value == 0) mat = NULL;
2973         else if(Value > This->numHandles)
2974         {
2975             ERR("Material handle out of range(%d)\n", Value);
2976             LeaveCriticalSection(&ddraw_cs);
2977             return DDERR_INVALIDPARAMS;
2978         }
2979         else if(This->Handles[Value - 1].type != DDrawHandle_Material)
2980         {
2981             ERR("Invalid handle %d\n", Value);
2982             LeaveCriticalSection(&ddraw_cs);
2983             return DDERR_INVALIDPARAMS;
2984         }
2985         else
2986         {
2987             mat = This->Handles[Value - 1].ptr;
2988         }
2989 
2990         if (mat != NULL)
2991         {
2992             TRACE(" activating material %p.\n", mat);
2993             mat->activate(mat);
2994         }
2995         else
2996         {
2997             FIXME(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
2998         }
2999         This->material = Value;
3000     }
3001     else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3002     {
3003         switch (Value)
3004         {
3005             case D3DCOLOR_MONO:
3006                 ERR("DDCOLOR_MONO should not happen!\n");
3007                 break;
3008             case D3DCOLOR_RGB:
3009                 /* We are already in this mode */
3010                 TRACE("Setting color model to RGB (no-op).\n");
3011                 break;
3012             default:
3013                 ERR("Unknown color model!\n");
3014                 LeaveCriticalSection(&ddraw_cs);
3015                 return DDERR_INVALIDPARAMS;
3016         }
3017     }
3018     else
3019     {
3020         D3DRENDERSTATETYPE rs;
3021         switch (LightStateType)
3022         {
3023             case D3DLIGHTSTATE_AMBIENT:       /* 2 */
3024                 rs = D3DRENDERSTATE_AMBIENT;
3025                 break;          
3026             case D3DLIGHTSTATE_FOGMODE:       /* 4 */
3027                 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3028                 break;
3029             case D3DLIGHTSTATE_FOGSTART:      /* 5 */
3030                 rs = D3DRENDERSTATE_FOGSTART;
3031                 break;
3032             case D3DLIGHTSTATE_FOGEND:        /* 6 */
3033                 rs = D3DRENDERSTATE_FOGEND;
3034                 break;
3035             case D3DLIGHTSTATE_FOGDENSITY:    /* 7 */
3036                 rs = D3DRENDERSTATE_FOGDENSITY;
3037                 break;
3038             case D3DLIGHTSTATE_COLORVERTEX:   /* 8 */
3039                 rs = D3DRENDERSTATE_COLORVERTEX;
3040                 break;
3041             default:
3042                 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3043                 LeaveCriticalSection(&ddraw_cs);
3044                 return DDERR_INVALIDPARAMS;
3045         }
3046 
3047         hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, rs, Value);
3048         LeaveCriticalSection(&ddraw_cs);
3049         return hr;
3050     }
3051 
3052     LeaveCriticalSection(&ddraw_cs);
3053     return D3D_OK;
3054 }
3055 
3056 static HRESULT WINAPI
3057 Thunk_IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3058                                           D3DLIGHTSTATETYPE LightStateType,
3059                                           DWORD Value)
3060 {
3061     IDirect3DDeviceImpl *This = device_from_device2(iface);
3062     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x) thunking to IDirect3DDevice3 interface.\n", This, LightStateType, Value);
3063     return IDirect3DDevice3_SetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3064 }
3065 
3066 /*****************************************************************************
3067  * IDirect3DDevice3::GetLightState
3068  *
3069  * Returns the current setting of a light state. The state is read from
3070  * the Direct3DDevice7 render state.
3071  *
3072  * Version 2 and 3
3073  *
3074  * Params:
3075  *  LightStateType: The light state to return
3076  *  Value: The address to store the light state setting at
3077  *
3078  * Returns:
3079  *  D3D_OK on success
3080  *  DDDERR_INVALIDPARAMS if the parameters were incorrect
3081  *  Also see IDirect3DDevice7::GetRenderState
3082  *
3083  *****************************************************************************/
3084 static HRESULT WINAPI
3085 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3086                                     D3DLIGHTSTATETYPE LightStateType,
3087                                     DWORD *Value)
3088 {
3089     IDirect3DDeviceImpl *This = device_from_device3(iface);
3090     HRESULT hr;
3091 
3092     TRACE("(%p)->(%08x,%p)\n", This, LightStateType, Value);
3093 
3094     if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3095     {
3096         TRACE("Unexpected Light State Type\n");
3097         return DDERR_INVALIDPARAMS;
3098     }
3099 
3100     if(!Value)
3101         return DDERR_INVALIDPARAMS;
3102 
3103     EnterCriticalSection(&ddraw_cs);
3104     if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3105     {
3106         *Value = This->material;
3107     }
3108     else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3109     {
3110         *Value = D3DCOLOR_RGB;
3111     }
3112     else
3113     {
3114         D3DRENDERSTATETYPE rs;
3115         switch (LightStateType)
3116         {
3117             case D3DLIGHTSTATE_AMBIENT:       /* 2 */
3118                 rs = D3DRENDERSTATE_AMBIENT;
3119                 break;          
3120             case D3DLIGHTSTATE_FOGMODE:       /* 4 */
3121                 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3122                 break;
3123             case D3DLIGHTSTATE_FOGSTART:      /* 5 */
3124                 rs = D3DRENDERSTATE_FOGSTART;
3125                 break;
3126             case D3DLIGHTSTATE_FOGEND:        /* 6 */
3127                 rs = D3DRENDERSTATE_FOGEND;
3128                 break;
3129             case D3DLIGHTSTATE_FOGDENSITY:    /* 7 */
3130                 rs = D3DRENDERSTATE_FOGDENSITY;
3131                 break;
3132             case D3DLIGHTSTATE_COLORVERTEX:   /* 8 */
3133                 rs = D3DRENDERSTATE_COLORVERTEX;
3134                 break;
3135             default:
3136                 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3137                 LeaveCriticalSection(&ddraw_cs);
3138                 return DDERR_INVALIDPARAMS;
3139         }
3140 
3141         hr = IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, rs, Value);
3142         LeaveCriticalSection(&ddraw_cs);
3143         return hr;
3144     }
3145 
3146     LeaveCriticalSection(&ddraw_cs);
3147     return D3D_OK;
3148 }
3149 
3150 static HRESULT WINAPI
3151 Thunk_IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3152                                           D3DLIGHTSTATETYPE LightStateType,
3153                                           DWORD *Value)
3154 {
3155     IDirect3DDeviceImpl *This = device_from_device2(iface);
3156     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice3 interface.\n", This, LightStateType, Value);
3157     return IDirect3DDevice3_GetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3158 }
3159 
3160 /*****************************************************************************
3161  * IDirect3DDevice7::SetTransform
3162  *
3163  * Assigns a D3DMATRIX to a transform type. The transform types are defined
3164  * in include/d3dtypes.h.
3165  * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3166  * (=255) for wined3d, because the 1 transform state was removed in d3d8
3167  * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3168  *
3169  * Version 2, 3 and 7
3170  *
3171  * Params:
3172  *  TransformStateType: transform state to set
3173  *  Matrix: Matrix to assign to the state
3174  *
3175  * Returns:
3176  *  D3D_OK on success
3177  *  DDERR_INVALIDPARAMS if Matrix == NULL
3178  *  For details see IWineD3DDevice::SetTransform
3179  *
3180  *****************************************************************************/
3181 static HRESULT
3182 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3183                                    D3DTRANSFORMSTATETYPE TransformStateType,
3184                                    D3DMATRIX *Matrix)
3185 {
3186     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3187     D3DTRANSFORMSTATETYPE type;
3188     HRESULT hr;
3189     TRACE("(%p)->(%08x,%p): Relay\n", This, TransformStateType, Matrix);
3190 
3191     switch(TransformStateType)
3192     {
3193         case D3DTRANSFORMSTATE_WORLD :  type = WINED3DTS_WORLDMATRIX(0); break;
3194         case D3DTRANSFORMSTATE_WORLD1:  type = WINED3DTS_WORLDMATRIX(1); break;
3195         case D3DTRANSFORMSTATE_WORLD2:  type = WINED3DTS_WORLDMATRIX(2); break;
3196         case D3DTRANSFORMSTATE_WORLD3:  type = WINED3DTS_WORLDMATRIX(3); break;
3197         default:                        type = TransformStateType;
3198     }
3199 
3200     if(!Matrix)
3201        return DDERR_INVALIDPARAMS;
3202 
3203     /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3204     EnterCriticalSection(&ddraw_cs);
3205     hr = IWineD3DDevice_SetTransform(This->wineD3DDevice,
3206                                      type,
3207                                      (WINED3DMATRIX*) Matrix);
3208     LeaveCriticalSection(&ddraw_cs);
3209     return hr;
3210 }
3211 
3212 static HRESULT WINAPI
3213 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3214                                    D3DTRANSFORMSTATETYPE TransformStateType,
3215                                    D3DMATRIX *Matrix)
3216 {
3217     return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3218 }
3219 
3220 static HRESULT WINAPI
3221 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3222                                    D3DTRANSFORMSTATETYPE TransformStateType,
3223                                    D3DMATRIX *Matrix)
3224 {
3225     HRESULT hr;
3226     WORD old_fpucw;
3227 
3228     old_fpucw = d3d_fpu_setup();
3229     hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3230     set_fpu_control_word(old_fpucw);
3231 
3232     return hr;
3233 }
3234 
3235 static HRESULT WINAPI
3236 Thunk_IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3237                                          D3DTRANSFORMSTATETYPE TransformStateType,
3238                                          D3DMATRIX *D3DMatrix)
3239 {
3240     IDirect3DDeviceImpl *This = device_from_device3(iface);
3241     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3242     return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3243 }
3244 
3245 static HRESULT WINAPI
3246 Thunk_IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3247                                          D3DTRANSFORMSTATETYPE TransformStateType,
3248                                          D3DMATRIX *D3DMatrix)
3249 {
3250     IDirect3DDeviceImpl *This = device_from_device2(iface);
3251     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3252     return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3253 }
3254 
3255 /*****************************************************************************
3256  * IDirect3DDevice7::GetTransform
3257  *
3258  * Returns the matrix assigned to a transform state
3259  * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3260  * SetTransform
3261  *
3262  * Params:
3263  *  TransformStateType: State to read the matrix from
3264  *  Matrix: Address to store the matrix at
3265  *
3266  * Returns:
3267  *  D3D_OK on success
3268  *  DDERR_INVALIDPARAMS if Matrix == NULL
3269  *  For details, see IWineD3DDevice::GetTransform
3270  *
3271  *****************************************************************************/
3272 static HRESULT
3273 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3274                                    D3DTRANSFORMSTATETYPE TransformStateType,
3275                                    D3DMATRIX *Matrix)
3276 {
3277     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3278     D3DTRANSFORMSTATETYPE type;
3279     HRESULT hr;
3280     TRACE("(%p)->(%08x,%p): Relay\n", This, TransformStateType, Matrix);
3281 
3282     switch(TransformStateType)
3283     {
3284         case D3DTRANSFORMSTATE_WORLD :  type = WINED3DTS_WORLDMATRIX(0); break;
3285         case D3DTRANSFORMSTATE_WORLD1:  type = WINED3DTS_WORLDMATRIX(1); break;
3286         case D3DTRANSFORMSTATE_WORLD2:  type = WINED3DTS_WORLDMATRIX(2); break;
3287         case D3DTRANSFORMSTATE_WORLD3:  type = WINED3DTS_WORLDMATRIX(3); break;
3288         default:                        type = TransformStateType;
3289     }
3290 
3291     if(!Matrix)
3292         return DDERR_INVALIDPARAMS;
3293 
3294     /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3295     EnterCriticalSection(&ddraw_cs);
3296     hr = IWineD3DDevice_GetTransform(This->wineD3DDevice, type, (WINED3DMATRIX*) Matrix);
3297     LeaveCriticalSection(&ddraw_cs);
3298     return hr;
3299 }
3300 
3301 static HRESULT WINAPI
3302 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3303                                    D3DTRANSFORMSTATETYPE TransformStateType,
3304                                    D3DMATRIX *Matrix)
3305 {
3306     return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3307 }
3308 
3309 static HRESULT WINAPI
3310 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3311                                    D3DTRANSFORMSTATETYPE TransformStateType,
3312                                    D3DMATRIX *Matrix)
3313 {
3314     HRESULT hr;
3315     WORD old_fpucw;
3316 
3317     old_fpucw = d3d_fpu_setup();
3318     hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3319     set_fpu_control_word(old_fpucw);
3320 
3321     return hr;
3322 }
3323 
3324 static HRESULT WINAPI
3325 Thunk_IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3326                                          D3DTRANSFORMSTATETYPE TransformStateType,
3327                                          D3DMATRIX *D3DMatrix)
3328 {
3329     IDirect3DDeviceImpl *This = device_from_device3(iface);
3330     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3331     return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3332 }
3333 
3334 static HRESULT WINAPI
3335 Thunk_IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3336                                          D3DTRANSFORMSTATETYPE TransformStateType,
3337                                          D3DMATRIX *D3DMatrix)
3338 {
3339     IDirect3DDeviceImpl *This = device_from_device2(iface);
3340     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3341     return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3342 }
3343 
3344 /*****************************************************************************
3345  * IDirect3DDevice7::MultiplyTransform
3346  *
3347  * Multiplies the already-set transform matrix of a transform state
3348  * with another matrix. For the world matrix, see SetTransform
3349  *
3350  * Version 2, 3 and 7
3351  *
3352  * Params:
3353  *  TransformStateType: Transform state to multiply
3354  *  D3DMatrix Matrix to multiply with.
3355  *
3356  * Returns
3357  *  D3D_OK on success
3358  *  DDERR_INVALIDPARAMS if D3DMatrix is NULL
3359  *  For details, see IWineD3DDevice::MultiplyTransform
3360  *
3361  *****************************************************************************/
3362 static HRESULT
3363 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3364                                         D3DTRANSFORMSTATETYPE TransformStateType,
3365                                         D3DMATRIX *D3DMatrix)
3366 {
3367     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3368     HRESULT hr;
3369     D3DTRANSFORMSTATETYPE type;
3370     TRACE("(%p)->(%08x,%p): Relay\n", This, TransformStateType, D3DMatrix);
3371 
3372     switch(TransformStateType)
3373     {
3374         case D3DTRANSFORMSTATE_WORLD :  type = WINED3DTS_WORLDMATRIX(0); break;
3375         case D3DTRANSFORMSTATE_WORLD1:  type = WINED3DTS_WORLDMATRIX(1); break;
3376         case D3DTRANSFORMSTATE_WORLD2:  type = WINED3DTS_WORLDMATRIX(2); break;
3377         case D3DTRANSFORMSTATE_WORLD3:  type = WINED3DTS_WORLDMATRIX(3); break;
3378         default:                        type = TransformStateType;
3379     }
3380 
3381     /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3382     EnterCriticalSection(&ddraw_cs);
3383     hr = IWineD3DDevice_MultiplyTransform(This->wineD3DDevice,
3384                                           type,
3385                                           (WINED3DMATRIX*) D3DMatrix);
3386     LeaveCriticalSection(&ddraw_cs);
3387     return hr;
3388 }
3389 
3390 static HRESULT WINAPI
3391 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3392                                         D3DTRANSFORMSTATETYPE TransformStateType,
3393                                         D3DMATRIX *D3DMatrix)
3394 {
3395     return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3396 }
3397 
3398 static HRESULT WINAPI
3399 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3400                                         D3DTRANSFORMSTATETYPE TransformStateType,
3401                                         D3DMATRIX *D3DMatrix)
3402 {
3403     HRESULT hr;
3404     WORD old_fpucw;
3405 
3406     old_fpucw = d3d_fpu_setup();
3407     hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3408     set_fpu_control_word(old_fpucw);
3409 
3410     return hr;
3411 }
3412 
3413 static HRESULT WINAPI
3414 Thunk_IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3415                                               D3DTRANSFORMSTATETYPE TransformStateType,
3416                                               D3DMATRIX *D3DMatrix)
3417 {
3418     IDirect3DDeviceImpl *This = device_from_device3(iface);
3419     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3420     return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3421 }
3422 
3423 static HRESULT WINAPI
3424 Thunk_IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3425                                               D3DTRANSFORMSTATETYPE TransformStateType,
3426                                               D3DMATRIX *D3DMatrix)
3427 {
3428     IDirect3DDeviceImpl *This = device_from_device2(iface);
3429     TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3430     return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3431 }
3432 
3433 /*****************************************************************************
3434  * IDirect3DDevice7::DrawPrimitive
3435  *
3436  * Draws primitives based on vertices in an application-provided pointer
3437  *
3438  * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3439  * an FVF format for D3D7
3440  *
3441  * Params:
3442  *  PrimitiveType: The type of the primitives to draw
3443  *  Vertex type: Flexible vertex format vertex description
3444  *  Vertices: Pointer to the vertex array
3445  *  VertexCount: The number of vertices to draw
3446  *  Flags: As usual a few flags
3447  *
3448  * Returns:
3449  *  D3D_OK on success
3450  *  DDERR_INVALIDPARAMS if Vertices is NULL
3451  *  For details, see IWineD3DDevice::DrawPrimitiveUP
3452  *
3453  *****************************************************************************/
3454 static HRESULT
3455 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3456                                     D3DPRIMITIVETYPE PrimitiveType,
3457                                     DWORD VertexType,
3458                                     void *Vertices,
3459                                     DWORD VertexCount,
3460                                     DWORD Flags)
3461 {
3462     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3463     UINT stride;
3464     HRESULT hr;
3465     TRACE("(%p)->(%08x,%08x,%p,%08x,%08x): Relay!\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3466 
3467     if(!Vertices)
3468         return DDERR_INVALIDPARAMS;
3469 
3470     /* Get the stride */
3471     stride = get_flexible_vertex_size(VertexType);
3472 
3473     /* Set the FVF */
3474     EnterCriticalSection(&ddraw_cs);
3475     hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
3476                                              IDirectDrawImpl_FindDecl(This->ddraw, VertexType));
3477     if(hr != D3D_OK)
3478     {
3479         LeaveCriticalSection(&ddraw_cs);
3480         return hr;
3481     }
3482 
3483     /* This method translates to the user pointer draw of WineD3D */
3484     IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3485     hr = IWineD3DDevice_DrawPrimitiveUP(This->wineD3DDevice, VertexCount, Vertices, stride);
3486     LeaveCriticalSection(&ddraw_cs);
3487     return hr;
3488 }
3489 
3490 static HRESULT WINAPI
3491 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3492                                     D3DPRIMITIVETYPE PrimitiveType,
3493                                     DWORD VertexType,
3494                                     void *Vertices,
3495                                     DWORD VertexCount,
3496                                     DWORD Flags)
3497 {
3498     return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3499 }
3500 
3501 static HRESULT WINAPI
3502 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3503                                     D3DPRIMITIVETYPE PrimitiveType,
3504                                     DWORD VertexType,
3505                                     void *Vertices,
3506                                     DWORD VertexCount,
3507                                     DWORD Flags)
3508 {
3509     HRESULT hr;
3510     WORD old_fpucw;
3511 
3512     old_fpucw = d3d_fpu_setup();
3513     hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3514     set_fpu_control_word(old_fpucw);
3515 
3516     return hr;
3517 }
3518 
3519 static HRESULT WINAPI
3520 Thunk_IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3521                                           D3DPRIMITIVETYPE PrimitiveType,
3522                                           DWORD VertexType,
3523                                           void *Vertices,
3524                                           DWORD VertexCount,
3525                                           DWORD Flags)
3526 {
3527     IDirect3DDeviceImpl *This = device_from_device3(iface);
3528     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3529     return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This,
3530             PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3531 }
3532 
3533 static HRESULT WINAPI
3534 Thunk_IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3535                                           D3DPRIMITIVETYPE PrimitiveType,
3536                                           D3DVERTEXTYPE VertexType,
3537                                           void *Vertices,
3538                                           DWORD VertexCount,
3539                                           DWORD Flags)
3540 {
3541     IDirect3DDeviceImpl *This = device_from_device2(iface);
3542     DWORD FVF;
3543     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3544 
3545     switch(VertexType)
3546     {
3547         case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3548         case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3549         case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3550         default:
3551             ERR("Unexpected vertex type %d\n", VertexType);
3552             return DDERR_INVALIDPARAMS;  /* Should never happen */
3553     }
3554 
3555     return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This, PrimitiveType, FVF, Vertices, VertexCount, Flags);
3556 }
3557 
3558 /*****************************************************************************
3559  * IDirect3DDevice7::DrawIndexedPrimitive
3560  *
3561  * Draws vertices from an application-provided pointer, based on the index
3562  * numbers in a WORD array.
3563  *
3564  * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3565  * an FVF format for D3D7
3566  *
3567  * Params:
3568  *  PrimitiveType: The primitive type to draw
3569  *  VertexType: The FVF vertex description
3570  *  Vertices: Pointer to the vertex array
3571  *  VertexCount: ?
3572  *  Indices: Pointer to the index array
3573  *  IndexCount: Number of indices = Number of vertices to draw
3574  *  Flags: As usual, some flags
3575  *
3576  * Returns:
3577  *  D3D_OK on success
3578  *  DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3579  *  For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3580  *
3581  *****************************************************************************/
3582 static HRESULT
3583 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3584                                            D3DPRIMITIVETYPE PrimitiveType,
3585                                            DWORD VertexType,
3586                                            void *Vertices,
3587                                            DWORD VertexCount,
3588                                            WORD *Indices,
3589                                            DWORD IndexCount,
3590                                            DWORD Flags)
3591 {
3592     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3593     HRESULT hr;
3594     TRACE("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x): Relay!\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3595 
3596     /* Set the D3DDevice's FVF */
3597     EnterCriticalSection(&ddraw_cs);
3598     hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
3599                                              IDirectDrawImpl_FindDecl(This->ddraw, VertexType));
3600     if(FAILED(hr))
3601     {
3602         ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3603         LeaveCriticalSection(&ddraw_cs);
3604         return hr;
3605     }
3606 
3607     IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3608     hr = IWineD3DDevice_DrawIndexedPrimitiveUP(This->wineD3DDevice, IndexCount, Indices,
3609             WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3610     LeaveCriticalSection(&ddraw_cs);
3611     return hr;
3612 }
3613 
3614 static HRESULT WINAPI
3615 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3616                                            D3DPRIMITIVETYPE PrimitiveType,
3617                                            DWORD VertexType,
3618                                            void *Vertices,
3619                                            DWORD VertexCount,
3620                                            WORD *Indices,
3621                                            DWORD IndexCount,
3622                                            DWORD Flags)
3623 {
3624     return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3625 }
3626 
3627 static HRESULT WINAPI
3628 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3629                                            D3DPRIMITIVETYPE PrimitiveType,
3630                                            DWORD VertexType,
3631                                            void *Vertices,
3632                                            DWORD VertexCount,
3633                                            WORD *Indices,
3634                                            DWORD IndexCount,
3635                                            DWORD Flags)
3636 {
3637     HRESULT hr;
3638     WORD old_fpucw;
3639 
3640     old_fpucw = d3d_fpu_setup();
3641     hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3642     set_fpu_control_word(old_fpucw);
3643 
3644     return hr;
3645 }
3646 
3647 static HRESULT WINAPI
3648 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3649                                                  D3DPRIMITIVETYPE PrimitiveType,
3650                                                  DWORD VertexType,
3651                                                  void *Vertices,
3652                                                  DWORD VertexCount,
3653                                                  WORD *Indices,
3654                                                  DWORD IndexCount,
3655                                                  DWORD Flags)
3656 {
3657     IDirect3DDeviceImpl *This = device_from_device3(iface);
3658     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3659     return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)This,
3660             PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3661 }
3662 
3663 static HRESULT WINAPI
3664 Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3665                                                  D3DPRIMITIVETYPE PrimitiveType,
3666                                                  D3DVERTEXTYPE VertexType,
3667                                                  void *Vertices,
3668                                                  DWORD VertexCount,
3669                                                  WORD *Indices,
3670                                                  DWORD IndexCount,
3671                                                  DWORD Flags)
3672 {
3673     DWORD FVF;
3674     IDirect3DDeviceImpl *This = device_from_device2(iface);
3675     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3676 
3677     switch(VertexType)
3678     {
3679         case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3680         case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3681         case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3682         default:
3683             ERR("Unexpected vertex type %d\n", VertexType);
3684             return DDERR_INVALIDPARAMS;  /* Should never happen */
3685     }
3686 
3687     return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)This,
3688             PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3689 }
3690 
3691 /*****************************************************************************
3692  * IDirect3DDevice7::SetClipStatus
3693  *
3694  * Sets the clip status. This defines things as clipping conditions and
3695  * the extents of the clipping region.
3696  *
3697  * Version 2, 3 and 7
3698  *
3699  * Params:
3700  *  ClipStatus:
3701  *
3702  * Returns:
3703  *  D3D_OK because it's a stub
3704  *  (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3705  *
3706  *****************************************************************************/
3707 static HRESULT WINAPI
3708 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3709                                     D3DCLIPSTATUS *ClipStatus)
3710 {
3711     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3712     FIXME("(%p)->(%p): Stub!\n", This, ClipStatus);
3713 
3714     /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3715      * Perhaps this needs a new data type and an additional IWineD3DDevice method
3716      */
3717     /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3718     return D3D_OK;
3719 }
3720 
3721 static HRESULT WINAPI
3722 Thunk_IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3723                                           D3DCLIPSTATUS *ClipStatus)
3724 {
3725     IDirect3DDeviceImpl *This = device_from_device3(iface);
3726     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3727     return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)This, ClipStatus);
3728 }
3729 
3730 static HRESULT WINAPI
3731 Thunk_IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3732                                           D3DCLIPSTATUS *ClipStatus)
3733 {
3734     IDirect3DDeviceImpl *This = device_from_device2(iface);
3735     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3736     return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)This, ClipStatus);
3737 }
3738 
3739 /*****************************************************************************
3740  * IDirect3DDevice7::GetClipStatus
3741  *
3742  * Returns the clip status
3743  *
3744  * Params:
3745  *  ClipStatus: Address to write the clip status to
3746  *
3747  * Returns:
3748  *  D3D_OK because it's a stub
3749  *
3750  *****************************************************************************/
3751 static HRESULT WINAPI
3752 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3753                                     D3DCLIPSTATUS *ClipStatus)
3754 {
3755     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3756     FIXME("(%p)->(%p): Stub!\n", This, ClipStatus);
3757 
3758     /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3759     /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3760     return D3D_OK;
3761 }
3762 
3763 static HRESULT WINAPI
3764 Thunk_IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3765                                           D3DCLIPSTATUS *ClipStatus)
3766 {
3767     IDirect3DDeviceImpl *This = device_from_device3(iface);
3768     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3769     return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)This, ClipStatus);
3770 }
3771 
3772 static HRESULT WINAPI
3773 Thunk_IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3774                                           D3DCLIPSTATUS *ClipStatus)
3775 {
3776     IDirect3DDeviceImpl *This = device_from_device2(iface);
3777     TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3778     return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)This, ClipStatus);
3779 }
3780 
3781 /*****************************************************************************
3782  * IDirect3DDevice::DrawPrimitiveStrided
3783  *
3784  * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3785  *
3786  * Version 3 and 7
3787  *
3788  * Params:
3789  *  PrimitiveType: The primitive type to draw
3790  *  VertexType: The FVF description of the vertices to draw (for the stride??)
3791  *  D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3792  *                         the vertex data locations
3793  *  VertexCount: The number of vertices to draw
3794  *  Flags: Some flags
3795  *
3796  * Returns:
3797  *  D3D_OK, because it's a stub
3798  *  (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3799  *  (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3800  *
3801  *****************************************************************************/
3802 static HRESULT
3803 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3804                                            D3DPRIMITIVETYPE PrimitiveType,
3805                                            DWORD VertexType,
3806                                            D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3807                                            DWORD VertexCount,
3808                                            DWORD Flags)
3809 {
3810     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3811     WineDirect3DVertexStridedData WineD3DStrided;
3812     DWORD i;
3813     HRESULT hr;
3814 
3815     TRACE("(%p)->(%08x,%08x,%p,%08x,%08x): stub!\n", This, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3816 
3817     memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3818     /* Get the strided data right. the wined3d structure is a bit bigger
3819      * Watch out: The contents of the strided data are determined by the fvf,
3820      * not by the members set in D3DDrawPrimStrideData. So it's valid
3821      * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3822      * not set in the fvf.
3823      */
3824     if(VertexType & D3DFVF_POSITION_MASK)
3825     {
3826         WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3827         WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3828         WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3829         if (VertexType & D3DFVF_XYZRHW)
3830         {
3831             WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3832             WineD3DStrided.position_transformed = TRUE;
3833         } else
3834             WineD3DStrided.position_transformed = FALSE;
3835     }
3836 
3837     if(VertexType & D3DFVF_NORMAL)
3838     {
3839         WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3840         WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3841         WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3842     }
3843 
3844     if(VertexType & D3DFVF_DIFFUSE)
3845     {
3846         WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3847         WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3848         WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3849     }
3850 
3851     if(VertexType & D3DFVF_SPECULAR)
3852     {
3853         WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3854         WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3855         WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3856     }
3857 
3858     for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3859     {
3860         switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3861         {
3862             case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3863             case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3864             case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3865             case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3866             default: ERR("Unexpected texture coordinate size %d\n",
3867                          GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3868         }
3869         WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3870         WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3871     }
3872 
3873     /* WineD3D doesn't need the FVF here */
3874     EnterCriticalSection(&ddraw_cs);
3875     IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3876     hr = IWineD3DDevice_DrawPrimitiveStrided(This->wineD3DDevice, VertexCount, &WineD3DStrided);
3877     LeaveCriticalSection(&ddraw_cs);
3878     return hr;
3879 }
3880 
3881 static HRESULT WINAPI
3882 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3883                                            D3DPRIMITIVETYPE PrimitiveType,
3884                                            DWORD VertexType,
3885                                            D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3886                                            DWORD VertexCount,
3887                                            DWORD Flags)
3888 {
3889     return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3890 }
3891 
3892 static HRESULT WINAPI
3893 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3894                                            D3DPRIMITIVETYPE PrimitiveType,
3895                                            DWORD VertexType,
3896                                            D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3897                                            DWORD VertexCount,
3898                                            DWORD Flags)
3899 {
3900     HRESULT hr;
3901     WORD old_fpucw;
3902 
3903     old_fpucw = d3d_fpu_setup();
3904     hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3905     set_fpu_control_word(old_fpucw);
3906 
3907     return hr;
3908 }
3909 
3910 static HRESULT WINAPI
3911 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3912                                                  D3DPRIMITIVETYPE PrimitiveType,
3913                                                  DWORD VertexType,
3914                                                  D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3915                                                  DWORD VertexCount,
3916                                                  DWORD Flags)
3917 {
3918     IDirect3DDeviceImpl *This = device_from_device3(iface);
3919     TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3920     return IDirect3DDevice7_DrawPrimitiveStrided((IDirect3DDevice7 *)This,
3921             PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3922 }
3923 
3924 /*****************************************************************************
3925  * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3926  *
3927  * Draws primitives specified by strided data locations based on indices
3928  *
3929  * Version 3 and 7
3930  *
3931  * Params:
3932  *  PrimitiveType:
3933  *
3934  * Returns:
3935  *  D3D_OK, because it's a stub
3936  *  (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3937  *  (DDERR_INVALIDPARAMS if Indices is NULL)
3938  *  (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3939  *
3940  *****************************************************************************/
3941 static HRESULT
3942 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3943                                                   D3DPRIMITIVETYPE PrimitiveType,
3944                                                   DWORD VertexType,
3945                                                   D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3946                                                   DWORD VertexCount,
3947                                                   WORD *Indices,
3948                                                   DWORD IndexCount,
3949                                                   DWORD Flags)
3950 {
3951     IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3952     WineDirect3DVertexStridedData WineD3DStrided;
3953     DWORD i;
3954     HRESULT hr;
3955 
3956     TRACE("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x)\n", This, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3957 
3958     memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3959     /* Get the strided data right. the wined3d structure is a bit bigger
3960      * Watch out: The contents of the strided data are determined by the fvf,
3961      * not by the members set in D3DDrawPrimStrideData. So it's valid
3962      * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3963      * not set in the fvf.
3964      */
3965     if(VertexType & D3DFVF_POSITION_MASK)
3966     {
3967         WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3968         WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3969         WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3970         if (VertexType & D3DFVF_XYZRHW)
3971         {
3972             WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3973             WineD3DStrided.position_transformed = TRUE;
3974         } else
3975             WineD3DStrided.position_transformed = FALSE;
3976     }
3977 
3978     if(VertexType & D3DFVF_NORMAL)
3979     {
3980         WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3981         WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3982         WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3983     }
3984 
3985     if(VertexType & D3DFVF_DIFFUSE)
3986     {
3987         WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3988         WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3989         WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3990     }
3991 
3992     if(VertexType & D3DFVF_SPECULAR)
3993     {
3994         WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3995         WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3996         WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3997     }
3998 
3999     for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
4000     {
4001         switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
4002         {
4003             case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
4004             case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
4005             case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
4006             case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
4007             default: ERR("Unexpected texture coordinate size %d\n",
4008                          GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4009         }
4010         WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4011         WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4012     }
4013 
4014     /* WineD3D doesn't need the FVF here */
4015     EnterCriticalSection(&ddraw_cs);
4016     IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4017     hr = IWineD3DDevice_DrawIndexedPrimitiveStrided(This->wineD3DDevice,
4018             IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
4019     LeaveCriticalSection(&ddraw_cs);
4020     return hr;
4021 }
4022 
4023 static HRESULT WINAPI
4024 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4025                                                   D3DPRIMITIVETYPE PrimitiveType,
4026                                                   DWORD VertexType,
4027                                                   D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4028                                                   DWORD VertexCount,
4029                                                   WORD *Indices,
4030                                                   DWORD IndexCount,
4031                                                   DWORD Flags)
4032 {
4033     return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4034 }
4035 
4036 static HRESULT WINAPI
4037 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4038                                                   D3DPRIMITIVETYPE PrimitiveType,
4039                                                   DWORD VertexType,
4040                                                   D3DDRAWPRIMITIVESTRIDEDDATA