ddraw: Beware of the surface type when checking for format support.
[wine/wine-gecko.git] / dlls / ddraw / device.c
blob94f394951ac8055444e26ea222f29f5757691a6e
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
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.
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.
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
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.
30 #include "config.h"
31 #include "wine/port.h"
33 #include <assert.h>
34 #include <stdarg.h>
35 #include <string.h>
36 #include <stdlib.h>
38 #define COBJMACROS
39 #define NONAMELESSUNION
41 #include "windef.h"
42 #include "winbase.h"
43 #include "winerror.h"
44 #include "wingdi.h"
45 #include "wine/exception.h"
47 #include "ddraw.h"
48 #include "d3d.h"
50 #include "ddraw_private.h"
51 #include "wine/debug.h"
53 WINE_DEFAULT_DEBUG_CHANNEL(d3d7);
54 WINE_DECLARE_DEBUG_CHANNEL(ddraw_thunk);
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 }
64 static inline void set_fpu_control_word(WORD fpucw)
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
73 static inline WORD d3d_fpu_setup(void)
75 WORD oldcw;
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)
85 FIXME("FPUPRESERVE not implemented for this platform / compiler\n");
86 warned = TRUE;
88 #endif
90 set_fpu_control_word(0x37f);
92 return oldcw;
95 /*****************************************************************************
96 * IUnknown Methods. Common for Version 1, 2, 3 and 7
97 *****************************************************************************/
99 /*****************************************************************************
100 * IDirect3DDevice7::QueryInterface
102 * Used to query other interfaces from a Direct3DDevice interface.
103 * It can return interface pointers to all Direct3DDevice versions as well
104 * as IDirectDraw and IDirect3D. For a link to QueryInterface
105 * rules see ddraw.c, IDirectDraw7::QueryInterface
107 * Exists in Version 1, 2, 3 and 7
109 * Params:
110 * refiid: Interface ID queried for
111 * obj: Used to return the interface pointer
113 * Returns:
114 * D3D_OK or E_NOINTERFACE
116 *****************************************************************************/
117 static HRESULT WINAPI
118 IDirect3DDeviceImpl_7_QueryInterface(IDirect3DDevice7 *iface,
119 REFIID refiid,
120 void **obj)
122 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
123 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(refiid), obj);
125 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
126 *obj = NULL;
128 if(!refiid)
129 return DDERR_INVALIDPARAMS;
131 if ( IsEqualGUID( &IID_IUnknown, refiid ) )
133 *obj = ICOM_INTERFACE(This, IDirect3DDevice7);
136 /* Check DirectDraw Interfac\x01s */
137 else if( IsEqualGUID( &IID_IDirectDraw7, refiid ) )
139 *obj = ICOM_INTERFACE(This->ddraw, IDirectDraw7);
140 TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
142 else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
144 *obj = ICOM_INTERFACE(This->ddraw, IDirectDraw4);
145 TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
147 else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
149 *obj = ICOM_INTERFACE(This->ddraw, IDirectDraw2);
150 TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
152 else if( IsEqualGUID( &IID_IDirectDraw, refiid ) )
154 *obj = ICOM_INTERFACE(This->ddraw, IDirectDraw);
155 TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
158 /* Direct3D */
159 else if ( IsEqualGUID( &IID_IDirect3D , refiid ) )
161 *obj = ICOM_INTERFACE(This->ddraw, IDirect3D);
162 TRACE("(%p) Returning IDirect3D interface at %p\n", This, *obj);
164 else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) )
166 *obj = ICOM_INTERFACE(This->ddraw, IDirect3D2);
167 TRACE("(%p) Returning IDirect3D2 interface at %p\n", This, *obj);
169 else if ( IsEqualGUID( &IID_IDirect3D3 , refiid ) )
171 *obj = ICOM_INTERFACE(This->ddraw, IDirect3D3);
172 TRACE("(%p) Returning IDirect3D3 interface at %p\n", This, *obj);
174 else if ( IsEqualGUID( &IID_IDirect3D7 , refiid ) )
176 *obj = ICOM_INTERFACE(This->ddraw, IDirect3D7);
177 TRACE("(%p) Returning IDirect3D7 interface at %p\n", This, *obj);
180 /* Direct3DDevice */
181 else if ( IsEqualGUID( &IID_IDirect3DDevice , refiid ) )
183 *obj = ICOM_INTERFACE(This, IDirect3DDevice);
184 TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
186 else if ( IsEqualGUID( &IID_IDirect3DDevice2 , refiid ) ) {
187 *obj = ICOM_INTERFACE(This, IDirect3DDevice2);
188 TRACE("(%p) Returning IDirect3DDevice2 interface at %p\n", This, *obj);
190 else if ( IsEqualGUID( &IID_IDirect3DDevice3 , refiid ) ) {
191 *obj = ICOM_INTERFACE(This, IDirect3DDevice3);
192 TRACE("(%p) Returning IDirect3DDevice3 interface at %p\n", This, *obj);
194 else if ( IsEqualGUID( &IID_IDirect3DDevice7 , refiid ) ) {
195 *obj = ICOM_INTERFACE(This, IDirect3DDevice7);
196 TRACE("(%p) Returning IDirect3DDevice7 interface at %p\n", This, *obj);
199 /* Unknown interface */
200 else
202 ERR("(%p)->(%s, %p): No interface found\n", This, debugstr_guid(refiid), obj);
203 return E_NOINTERFACE;
206 /* AddRef the returned interface */
207 IUnknown_AddRef( (IUnknown *) *obj);
208 return D3D_OK;
211 static HRESULT WINAPI
212 Thunk_IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface,
213 REFIID riid,
214 void **obj)
216 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
217 TRACE_(ddraw_thunk)("(%p)->(%s,%p) thunking to IDirect3DDevice7 interface.\n", This, debugstr_guid(riid), obj);
218 return IDirect3DDevice7_QueryInterface(ICOM_INTERFACE(This, IDirect3DDevice7),
219 riid,
220 obj);
223 static HRESULT WINAPI
224 Thunk_IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface,
225 REFIID riid,
226 void **obj)
228 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
229 TRACE_(ddraw_thunk)("(%p)->(%s,%p) thunking to IDirect3DDevice7 interface.\n", This, debugstr_guid(riid), obj);
230 return IDirect3DDevice7_QueryInterface(ICOM_INTERFACE(This, IDirect3DDevice7),
231 riid,
232 obj);
235 static HRESULT WINAPI
236 Thunk_IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface,
237 REFIID riid,
238 void **obp)
240 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
241 TRACE_(ddraw_thunk)("(%p)->(%s,%p) thunking to IDirect3DDevice7 interface.\n", This, debugstr_guid(riid), obp);
242 return IDirect3DDevice7_QueryInterface(ICOM_INTERFACE(This, IDirect3DDevice7),
243 riid,
244 obp);
247 /*****************************************************************************
248 * IDirect3DDevice7::AddRef
250 * Increases the refcount....
251 * The most exciting Method, definitely
253 * Exists in Version 1, 2, 3 and 7
255 * Returns:
256 * The new refcount
258 *****************************************************************************/
259 static ULONG WINAPI
260 IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
262 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
263 ULONG ref = InterlockedIncrement(&This->ref);
265 TRACE("(%p) : incrementing from %u.\n", This, ref -1);
267 return ref;
270 static ULONG WINAPI
271 Thunk_IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
273 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
274 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
275 return IDirect3DDevice7_AddRef(ICOM_INTERFACE(This, IDirect3DDevice7));
278 static ULONG WINAPI
279 Thunk_IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
281 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
282 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
283 return IDirect3DDevice7_AddRef(ICOM_INTERFACE(This, IDirect3DDevice7));
286 static ULONG WINAPI
287 Thunk_IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
289 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", iface);
290 return IDirect3DDevice7_AddRef(COM_INTERFACE_CAST(IDirect3DDeviceImpl, IDirect3DDevice, IDirect3DDevice7, iface));
293 /*****************************************************************************
294 * IDirect3DDevice7::Release
296 * Decreases the refcount of the interface
297 * When the refcount is reduced to 0, the object is destroyed.
299 * Exists in Version 1, 2, 3 and 7
301 * Returns:d
302 * The new refcount
304 *****************************************************************************/
305 static ULONG WINAPI
306 IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
308 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
309 ULONG ref = InterlockedDecrement(&This->ref);
311 TRACE("(%p)->() decrementing from %u.\n", This, ref +1);
313 /* This method doesn't destroy the WineD3DDevice, because it's still in use for
314 * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
315 * when the render target is released
317 if (ref == 0)
319 IParent *IndexBufferParent;
320 DWORD i;
322 EnterCriticalSection(&ddraw_cs);
323 /* Free the index buffer. */
324 IWineD3DDevice_SetIndices(This->wineD3DDevice, NULL);
325 IWineD3DIndexBuffer_GetParent(This->indexbuffer,
326 (IUnknown **) &IndexBufferParent);
327 IParent_Release(IndexBufferParent); /* Once for the getParent */
328 if( IParent_Release(IndexBufferParent) != 0) /* And now to destroy it */
330 ERR(" (%p) Something is still holding the index buffer parent %p\n", This, IndexBufferParent);
333 /* There is no need to unset the vertex buffer here, IWineD3DDevice_Uninit3D will do that when
334 * destroying the primary stateblock. If a vertex buffer is destroyed while it is bound
335 * IDirect3DVertexBuffer::Release will unset it.
338 /* Restore the render targets */
339 if(This->OffScreenTarget)
341 WINED3DVIEWPORT vp;
343 vp.X = 0;
344 vp.Y = 0;
345 vp.Width = This->ddraw->d3d_target->surface_desc.dwWidth;
346 vp.Height = This->ddraw->d3d_target->surface_desc.dwHeight;
347 vp.MinZ = 0.0;
348 vp.MaxZ = 1.0;
349 IWineD3DDevice_SetViewport(This->wineD3DDevice,
350 &vp);
352 /* Set the device up to render to the front buffer since the back buffer will
353 * vanish soon.
355 IWineD3DDevice_SetRenderTarget(This->wineD3DDevice, 0,
356 This->ddraw->d3d_target->WineD3DSurface);
357 /* This->target is the offscreen target.
358 * This->ddraw->d3d_target is the target used by DDraw
360 TRACE("(%p) Release: Using %p as front buffer, %p as back buffer\n", This, This->ddraw->d3d_target, NULL);
361 IWineD3DDevice_SetFrontBackBuffers(This->wineD3DDevice,
362 This->ddraw->d3d_target->WineD3DSurface,
363 NULL);
366 /* Release the WineD3DDevice. This won't destroy it */
367 if(IWineD3DDevice_Release(This->wineD3DDevice) <= 0)
369 ERR(" (%p) The wineD3D device %p was destroyed unexpectedly. Prepare for trouble\n", This, This->wineD3DDevice);
372 /* The texture handles should be unset by now, but there might be some bits
373 * missing in our reference counting(needs test). Do a sanity check
375 for(i = 0; i < This->numHandles; i++)
377 if(This->Handles[i].ptr)
379 switch(This->Handles[i].type)
381 case DDrawHandle_Texture:
383 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *) This->Handles[i].ptr;
384 FIXME("Texture Handle %d not unset properly\n", i + 1);
385 surf->Handle = 0;
387 break;
389 case DDrawHandle_Material:
391 IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) This->Handles[i].ptr;
392 FIXME("Material handle %d not unset properly\n", i + 1);
393 mat->Handle = 0;
395 break;
397 case DDrawHandle_Matrix:
399 /* No fixme here because this might happen because of sloppy apps */
400 WARN("Leftover matrix handle %d, deleting\n", i + 1);
401 IDirect3DDevice_DeleteMatrix(ICOM_INTERFACE(This, IDirect3DDevice),
402 i + 1);
404 break;
406 case DDrawHandle_StateBlock:
408 /* No fixme here because this might happen because of sloppy apps */
409 WARN("Leftover stateblock handle %d, deleting\n", i + 1);
410 IDirect3DDevice7_DeleteStateBlock(ICOM_INTERFACE(This, IDirect3DDevice7),
411 i + 1);
413 break;
415 default:
416 FIXME("Unknown handle %d not unset properly\n", i + 1);
421 HeapFree(GetProcessHeap(), 0, This->Handles);
423 TRACE("Releasing target %p %p\n", This->target, This->ddraw->d3d_target);
424 /* Release the render target and the WineD3D render target
425 * (See IDirect3D7::CreateDevice for more comments on this)
427 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->target, IDirectDrawSurface7));
428 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->ddraw->d3d_target,IDirectDrawSurface7));
429 TRACE("Target release done\n");
431 This->ddraw->d3ddevice = NULL;
433 /* Now free the structure */
434 HeapFree(GetProcessHeap(), 0, This);
435 LeaveCriticalSection(&ddraw_cs);
438 TRACE("Done\n");
439 return ref;
442 static ULONG WINAPI
443 Thunk_IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
445 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
446 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
447 return IDirect3DDevice7_Release(ICOM_INTERFACE(This, IDirect3DDevice7));
450 static ULONG WINAPI
451 Thunk_IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
453 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
454 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
455 return IDirect3DDevice7_Release(ICOM_INTERFACE(This, IDirect3DDevice7));
458 static ULONG WINAPI
459 Thunk_IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
461 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
462 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
463 return IDirect3DDevice7_Release(ICOM_INTERFACE(This, IDirect3DDevice7));
466 /*****************************************************************************
467 * IDirect3DDevice Methods
468 *****************************************************************************/
470 /*****************************************************************************
471 * IDirect3DDevice::Initialize
473 * Initializes a Direct3DDevice. This implementation is a no-op, as all
474 * initialization is done at create time.
476 * Exists in Version 1
478 * Parameters:
479 * No idea what they mean, as the MSDN page is gone
481 * Returns: DD_OK
483 *****************************************************************************/
484 static HRESULT WINAPI
485 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
486 IDirect3D *Direct3D, GUID *guid,
487 D3DDEVICEDESC *Desc)
489 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
491 /* It shouldn't be crucial, but print a FIXME, I'm interested if
492 * any game calls it and when
494 FIXME("(%p)->(%p,%p,%p): No-op!\n", This, Direct3D, guid, Desc);
496 return D3D_OK;
499 /*****************************************************************************
500 * IDirect3DDevice7::GetCaps
502 * Retrieves the device's capabilities
504 * This implementation is used for Version 7 only, the older versions have
505 * their own implementation.
507 * Parameters:
508 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
510 * Returns:
511 * D3D_OK on success
512 * D3DERR_* if a problem occurs. See WineD3D
514 *****************************************************************************/
515 static HRESULT
516 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
517 D3DDEVICEDESC7 *Desc)
519 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
520 D3DDEVICEDESC OldDesc;
521 TRACE("(%p)->(%p)\n", This, Desc);
523 /* Call the same function used by IDirect3D, this saves code */
524 return IDirect3DImpl_GetCaps(This->ddraw->wineD3D, &OldDesc, Desc);
527 static HRESULT WINAPI
528 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
529 D3DDEVICEDESC7 *Desc)
531 return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
534 static HRESULT WINAPI
535 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
536 D3DDEVICEDESC7 *Desc)
538 HRESULT hr;
539 WORD old_fpucw;
541 old_fpucw = d3d_fpu_setup();
542 hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
543 set_fpu_control_word(old_fpucw);
545 return hr;
547 /*****************************************************************************
548 * IDirect3DDevice3::GetCaps
550 * Retrieves the capabilities of the hardware device and the emulation
551 * device. For Wine, hardware and emulation are the same (it's all HW).
553 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
555 * Parameters:
556 * HWDesc: Structure to fill with the HW caps
557 * HelDesc: Structure to fill with the hardware emulation caps
559 * Returns:
560 * D3D_OK on success
561 * D3DERR_* if a problem occurs. See WineD3D
563 *****************************************************************************/
564 static HRESULT WINAPI
565 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
566 D3DDEVICEDESC *HWDesc,
567 D3DDEVICEDESC *HelDesc)
569 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
570 D3DDEVICEDESC7 newDesc;
571 HRESULT hr;
572 TRACE("(%p)->(%p,%p)\n", iface, HWDesc, HelDesc);
574 hr = IDirect3DImpl_GetCaps(This->ddraw->wineD3D, HWDesc, &newDesc);
575 if(hr != D3D_OK) return hr;
577 *HelDesc = *HWDesc;
578 return D3D_OK;
581 static HRESULT WINAPI
582 Thunk_IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
583 D3DDEVICEDESC *D3DHWDevDesc,
584 D3DDEVICEDESC *D3DHELDevDesc)
586 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
587 TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice3 interface.\n", This, D3DHWDevDesc, D3DHELDevDesc);
588 return IDirect3DDevice3_GetCaps(ICOM_INTERFACE(This, IDirect3DDevice3),
589 D3DHWDevDesc,
590 D3DHELDevDesc);
593 static HRESULT WINAPI
594 Thunk_IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
595 D3DDEVICEDESC *D3DHWDevDesc,
596 D3DDEVICEDESC *D3DHELDevDesc)
598 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
599 TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice3 interface.\n", This, D3DHWDevDesc, D3DHELDevDesc);
600 return IDirect3DDevice3_GetCaps(ICOM_INTERFACE(This, IDirect3DDevice3),
601 D3DHWDevDesc,
602 D3DHELDevDesc);
605 /*****************************************************************************
606 * IDirect3DDevice2::SwapTextureHandles
608 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
610 * Parameters:
611 * Tex1, Tex2: The 2 Textures to swap
613 * Returns:
614 * D3D_OK
616 *****************************************************************************/
617 static HRESULT WINAPI
618 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
619 IDirect3DTexture2 *Tex1,
620 IDirect3DTexture2 *Tex2)
622 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
623 DWORD swap;
624 IDirectDrawSurfaceImpl *surf1 = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture2, Tex1);
625 IDirectDrawSurfaceImpl *surf2 = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture2, Tex2);
626 TRACE("(%p)->(%p,%p)\n", This, surf1, surf2);
628 EnterCriticalSection(&ddraw_cs);
629 This->Handles[surf1->Handle - 1].ptr = surf2;
630 This->Handles[surf2->Handle - 1].ptr = surf1;
632 swap = surf2->Handle;
633 surf2->Handle = surf1->Handle;
634 surf1->Handle = swap;
635 LeaveCriticalSection(&ddraw_cs);
637 return D3D_OK;
640 static HRESULT WINAPI
641 Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
642 IDirect3DTexture *D3DTex1,
643 IDirect3DTexture *D3DTex2)
645 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
646 IDirectDrawSurfaceImpl *surf1 = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture, D3DTex1);
647 IDirectDrawSurfaceImpl *surf2 = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture, D3DTex2);
648 TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice2 interface.\n", This, surf1, surf2);
649 return IDirect3DDevice2_SwapTextureHandles(ICOM_INTERFACE(This, IDirect3DDevice2),
650 ICOM_INTERFACE(surf1, IDirect3DTexture2),
651 ICOM_INTERFACE(surf2, IDirect3DTexture2));
654 /*****************************************************************************
655 * IDirect3DDevice3::GetStats
657 * This method seems to retrieve some stats from the device.
658 * The MSDN documentation doesn't exist any more, but the D3DSTATS
659 * structure suggests that the amount of drawn primitives and processed
660 * vertices is returned.
662 * Exists in Version 1, 2 and 3
664 * Parameters:
665 * Stats: Pointer to a D3DSTATS structure to be filled
667 * Returns:
668 * D3D_OK on success
669 * DDERR_INVALIDPARAMS if Stats == NULL
671 *****************************************************************************/
672 static HRESULT WINAPI
673 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
674 D3DSTATS *Stats)
676 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
677 FIXME("(%p)->(%p): Stub!\n", This, Stats);
679 if(!Stats)
680 return DDERR_INVALIDPARAMS;
682 /* Fill the Stats with 0 */
683 Stats->dwTrianglesDrawn = 0;
684 Stats->dwLinesDrawn = 0;
685 Stats->dwPointsDrawn = 0;
686 Stats->dwSpansDrawn = 0;
687 Stats->dwVerticesProcessed = 0;
689 return D3D_OK;
692 static HRESULT WINAPI
693 Thunk_IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface,
694 D3DSTATS *Stats)
696 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
697 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, Stats);
698 return IDirect3DDevice3_GetStats(ICOM_INTERFACE(This, IDirect3DDevice3),
699 Stats);
702 static HRESULT WINAPI
703 Thunk_IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface,
704 D3DSTATS *Stats)
706 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
707 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, Stats);
708 return IDirect3DDevice3_GetStats(ICOM_INTERFACE(This, IDirect3DDevice3),
709 Stats);
712 /*****************************************************************************
713 * IDirect3DDevice::CreateExecuteBuffer
715 * Creates an IDirect3DExecuteBuffer, used for rendering with a
716 * Direct3DDevice.
718 * Version 1 only.
720 * Params:
721 * Desc: Buffer description
722 * ExecuteBuffer: Address to return the Interface pointer at
723 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
724 * support
726 * Returns:
727 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
728 * DDERR_OUTOFMEMORY if we ran out of memory
729 * D3D_OK on success
731 *****************************************************************************/
732 static HRESULT WINAPI
733 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
734 D3DEXECUTEBUFFERDESC *Desc,
735 IDirect3DExecuteBuffer **ExecuteBuffer,
736 IUnknown *UnkOuter)
738 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
739 IDirect3DExecuteBufferImpl* object;
740 TRACE("(%p)->(%p,%p,%p)!\n", This, Desc, ExecuteBuffer, UnkOuter);
742 if(UnkOuter)
743 return CLASS_E_NOAGGREGATION;
745 /* Allocate the new Execute Buffer */
746 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
747 if(!object)
749 ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
750 return DDERR_OUTOFMEMORY;
753 ICOM_INIT_INTERFACE(object, IDirect3DExecuteBuffer, IDirect3DExecuteBuffer_Vtbl);
755 object->ref = 1;
756 object->d3ddev = This;
758 /* Initializes memory */
759 memcpy(&object->desc, Desc, Desc->dwSize);
761 /* No buffer given */
762 if ((object->desc.dwFlags & D3DDEB_LPDATA) == 0)
763 object->desc.lpData = NULL;
765 /* No buffer size given */
766 if ((object->desc.dwFlags & D3DDEB_BUFSIZE) == 0)
767 object->desc.dwBufferSize = 0;
769 /* Create buffer if asked */
770 if ((object->desc.lpData == NULL) && (object->desc.dwBufferSize > 0))
772 object->need_free = TRUE;
773 object->desc.lpData = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,object->desc.dwBufferSize);
774 if(!object->desc.lpData)
776 ERR("Out of memory when allocating the execute buffer data\n");
777 HeapFree(GetProcessHeap(), 0, object);
778 return DDERR_OUTOFMEMORY;
781 else
783 object->need_free = FALSE;
786 /* No vertices for the moment */
787 object->vertex_data = NULL;
789 object->desc.dwFlags |= D3DDEB_LPDATA;
791 object->indices = NULL;
792 object->nb_indices = 0;
794 *ExecuteBuffer = ICOM_INTERFACE(object, IDirect3DExecuteBuffer);
796 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
798 return D3D_OK;
801 /*****************************************************************************
802 * IDirect3DDevice::Execute
804 * Executes all the stuff in an execute buffer.
806 * Params:
807 * ExecuteBuffer: The buffer to execute
808 * Viewport: The viewport used for rendering
809 * Flags: Some flags
811 * Returns:
812 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
813 * D3D_OK on success
815 *****************************************************************************/
816 static HRESULT WINAPI
817 IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
818 IDirect3DExecuteBuffer *ExecuteBuffer,
819 IDirect3DViewport *Viewport,
820 DWORD Flags)
822 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
823 IDirect3DExecuteBufferImpl *Direct3DExecuteBufferImpl = ICOM_OBJECT(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, ExecuteBuffer);
824 IDirect3DViewportImpl *Direct3DViewportImpl = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Viewport);
826 TRACE("(%p)->(%p,%p,%08x)\n", This, Direct3DExecuteBufferImpl, Direct3DViewportImpl, Flags);
828 if(!Direct3DExecuteBufferImpl)
829 return DDERR_INVALIDPARAMS;
831 /* Execute... */
832 EnterCriticalSection(&ddraw_cs);
833 IDirect3DExecuteBufferImpl_Execute(Direct3DExecuteBufferImpl, This, Direct3DViewportImpl);
834 LeaveCriticalSection(&ddraw_cs);
836 return D3D_OK;
839 /*****************************************************************************
840 * IDirect3DDevice3::AddViewport
842 * Add a Direct3DViewport to the device's viewport list. These viewports
843 * are wrapped to IDirect3DDevice7 viewports in viewport.c
845 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
846 * are the same interfaces.
848 * Params:
849 * Viewport: The viewport to add
851 * Returns:
852 * DDERR_INVALIDPARAMS if Viewport == NULL
853 * D3D_OK on success
855 *****************************************************************************/
856 static HRESULT WINAPI
857 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
858 IDirect3DViewport3 *Viewport)
860 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
861 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Viewport);
863 TRACE("(%p)->(%p)\n", This, vp);
865 /* Sanity check */
866 if(!vp)
867 return DDERR_INVALIDPARAMS;
869 EnterCriticalSection(&ddraw_cs);
870 vp->next = This->viewport_list;
871 This->viewport_list = vp;
872 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
873 so set active_device here. */
874 LeaveCriticalSection(&ddraw_cs);
876 return D3D_OK;
879 static HRESULT WINAPI
880 Thunk_IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
881 IDirect3DViewport2 *Direct3DViewport2)
883 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
884 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Direct3DViewport2);
885 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
886 return IDirect3DDevice3_AddViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
887 ICOM_INTERFACE(vp, IDirect3DViewport3));
890 static HRESULT WINAPI
891 Thunk_IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
892 IDirect3DViewport *Direct3DViewport)
894 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
895 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Direct3DViewport);
896 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
897 return IDirect3DDevice3_AddViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
898 ICOM_INTERFACE(vp, IDirect3DViewport3));
901 /*****************************************************************************
902 * IDirect3DDevice3::DeleteViewport
904 * Deletes a Direct3DViewport from the device's viewport list.
906 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
907 * are equal.
909 * Params:
910 * Viewport: The viewport to delete
912 * Returns:
913 * D3D_OK on success
914 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
916 *****************************************************************************/
917 static HRESULT WINAPI
918 IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface,
919 IDirect3DViewport3 *Viewport)
921 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
922 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *) Viewport;
923 IDirect3DViewportImpl *cur_viewport, *prev_viewport = NULL;
925 TRACE("(%p)->(%p)\n", This, vp);
927 EnterCriticalSection(&ddraw_cs);
928 cur_viewport = This->viewport_list;
929 while (cur_viewport != NULL)
931 if (cur_viewport == vp)
933 if (prev_viewport == NULL) This->viewport_list = cur_viewport->next;
934 else prev_viewport->next = cur_viewport->next;
935 /* TODO : add desactivate of the viewport and all associated lights... */
936 LeaveCriticalSection(&ddraw_cs);
937 return D3D_OK;
939 prev_viewport = cur_viewport;
940 cur_viewport = cur_viewport->next;
943 LeaveCriticalSection(&ddraw_cs);
944 return DDERR_INVALIDPARAMS;
947 static HRESULT WINAPI
948 Thunk_IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
949 IDirect3DViewport2 *Direct3DViewport2)
951 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
952 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Direct3DViewport2);
953 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
954 return IDirect3DDevice3_DeleteViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
955 ICOM_INTERFACE(vp, IDirect3DViewport3));
958 static HRESULT WINAPI
959 Thunk_IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
960 IDirect3DViewport *Direct3DViewport)
962 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
963 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Direct3DViewport);
964 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
965 return IDirect3DDevice3_DeleteViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
966 ICOM_INTERFACE(vp, IDirect3DViewport3));
969 /*****************************************************************************
970 * IDirect3DDevice3::NextViewport
972 * Returns a viewport from the viewport list, depending on the
973 * passed viewport and the flags.
975 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
976 * are equal.
978 * Params:
979 * Viewport: Viewport to use for beginning the search
980 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
982 * Returns:
983 * D3D_OK on success
984 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
986 *****************************************************************************/
987 static HRESULT WINAPI
988 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
989 IDirect3DViewport3 *Viewport3,
990 IDirect3DViewport3 **lplpDirect3DViewport3,
991 DWORD Flags)
993 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
994 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Viewport3);
995 IDirect3DViewportImpl *res = NULL;
997 TRACE("(%p)->(%p,%p,%08x)\n", This, vp, lplpDirect3DViewport3, Flags);
999 if(!vp)
1001 *lplpDirect3DViewport3 = NULL;
1002 return DDERR_INVALIDPARAMS;
1006 EnterCriticalSection(&ddraw_cs);
1007 switch (Flags)
1009 case D3DNEXT_NEXT:
1011 res = vp->next;
1013 break;
1014 case D3DNEXT_HEAD:
1016 res = This->viewport_list;
1018 break;
1019 case D3DNEXT_TAIL:
1021 IDirect3DViewportImpl *cur_viewport = This->viewport_list;
1022 if (cur_viewport != NULL)
1024 while (cur_viewport->next != NULL) cur_viewport = cur_viewport->next;
1026 res = cur_viewport;
1028 break;
1029 default:
1030 *lplpDirect3DViewport3 = NULL;
1031 LeaveCriticalSection(&ddraw_cs);
1032 return DDERR_INVALIDPARAMS;
1035 *lplpDirect3DViewport3 = ICOM_INTERFACE(res, IDirect3DViewport3);
1036 LeaveCriticalSection(&ddraw_cs);
1037 return D3D_OK;
1040 static HRESULT WINAPI
1041 Thunk_IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
1042 IDirect3DViewport2 *Viewport2,
1043 IDirect3DViewport2 **lplpDirect3DViewport2,
1044 DWORD Flags)
1046 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1047 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Viewport2);
1048 IDirect3DViewport3 *res;
1049 HRESULT hr;
1050 TRACE_(ddraw_thunk)("(%p)->(%p,%p,%08x) thunking to IDirect3DDevice3 interface.\n", This, vp, lplpDirect3DViewport2, Flags);
1051 hr = IDirect3DDevice3_NextViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
1052 ICOM_INTERFACE(vp, IDirect3DViewport3),
1053 &res,
1054 Flags);
1055 *lplpDirect3DViewport2 = (IDirect3DViewport2 *) COM_INTERFACE_CAST(IDirect3DViewportImpl, IDirect3DViewport3, IDirect3DViewport3, res);
1056 return hr;
1059 static HRESULT WINAPI
1060 Thunk_IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
1061 IDirect3DViewport *Viewport,
1062 IDirect3DViewport **lplpDirect3DViewport,
1063 DWORD Flags)
1065 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1066 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Viewport);
1067 IDirect3DViewport3 *res;
1068 HRESULT hr;
1069 TRACE_(ddraw_thunk)("(%p)->(%p,%p,%08x) thunking to IDirect3DDevice3 interface.\n", This, vp, lplpDirect3DViewport, Flags);
1070 hr = IDirect3DDevice3_NextViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
1071 ICOM_INTERFACE(vp, IDirect3DViewport3),
1072 &res,
1073 Flags);
1074 *lplpDirect3DViewport = (IDirect3DViewport *) COM_INTERFACE_CAST(IDirect3DViewportImpl, IDirect3DViewport3, IDirect3DViewport3, res);
1075 return hr;
1078 /*****************************************************************************
1079 * IDirect3DDevice::Pick
1081 * Executes an execute buffer without performing rendering. Instead, a
1082 * list of primitives that intersect with (x1,y1) of the passed rectangle
1083 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
1084 * this list.
1086 * Version 1 only
1088 * Params:
1089 * ExecuteBuffer: Buffer to execute
1090 * Viewport: Viewport to use for execution
1091 * Flags: None are defined, according to the SDK
1092 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
1093 * x2 and y2 are ignored.
1095 * Returns:
1096 * D3D_OK because it's a stub
1098 *****************************************************************************/
1099 static HRESULT WINAPI
1100 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
1101 IDirect3DExecuteBuffer *ExecuteBuffer,
1102 IDirect3DViewport *Viewport,
1103 DWORD Flags,
1104 D3DRECT *Rect)
1106 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1107 IDirect3DExecuteBufferImpl *execbuf = ICOM_OBJECT(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, ExecuteBuffer);
1108 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Viewport);
1109 FIXME("(%p)->(%p,%p,%08x,%p): stub!\n", This, execbuf, vp, Flags, Rect);
1111 return D3D_OK;
1114 /*****************************************************************************
1115 * IDirect3DDevice::GetPickRecords
1117 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1119 * Version 1 only
1121 * Params:
1122 * Count: Pointer to a DWORD containing the numbers of pick records to
1123 * retrieve
1124 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1126 * Returns:
1127 * D3D_OK, because it's a stub
1129 *****************************************************************************/
1130 static HRESULT WINAPI
1131 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1132 DWORD *Count,
1133 D3DPICKRECORD *D3DPickRec)
1135 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1136 FIXME("(%p)->(%p,%p): stub!\n", This, Count, D3DPickRec);
1138 return D3D_OK;
1141 /*****************************************************************************
1142 * IDirect3DDevice7::EnumTextureformats
1144 * Enumerates the supported texture formats. It has a list of all possible
1145 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1146 * WineD3D supports it. If so, then it is passed to the app.
1148 * This is for Version 7 and 3, older versions have a different
1149 * callback function and their own implementation
1151 * Params:
1152 * Callback: Callback to call for each enumerated format
1153 * Arg: Argument to pass to the callback
1155 * Returns:
1156 * D3D_OK on success
1157 * DDERR_INVALIDPARAMS if Callback == NULL
1159 *****************************************************************************/
1160 static HRESULT
1161 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1162 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1163 void *Arg)
1165 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1166 HRESULT hr;
1167 int i;
1169 WINED3DFORMAT FormatList[] = {
1170 /* 32 bit */
1171 WINED3DFMT_A8R8G8B8,
1172 WINED3DFMT_X8R8G8B8,
1173 /* 24 bit */
1174 WINED3DFMT_R8G8B8,
1175 /* 16 Bit */
1176 WINED3DFMT_A1R5G5B5,
1177 WINED3DFMT_A4R4G4B4,
1178 WINED3DFMT_R5G6B5,
1179 WINED3DFMT_X1R5G5B5,
1180 /* 8 Bit */
1181 WINED3DFMT_R3G3B2,
1182 WINED3DFMT_P8,
1183 /* FOURCC codes */
1184 WINED3DFMT_DXT1,
1185 WINED3DFMT_DXT3,
1186 WINED3DFMT_DXT5,
1189 WINED3DFORMAT BumpFormatList[] = {
1190 WINED3DFMT_V8U8,
1191 WINED3DFMT_L6V5U5,
1192 WINED3DFMT_X8L8V8U8,
1193 WINED3DFMT_Q8W8V8U8,
1194 WINED3DFMT_V16U16,
1195 WINED3DFMT_W11V11U10,
1196 WINED3DFMT_A2W10V10U10
1199 TRACE("(%p)->(%p,%p): Relay\n", This, Callback, Arg);
1201 if(!Callback)
1202 return DDERR_INVALIDPARAMS;
1204 EnterCriticalSection(&ddraw_cs);
1205 for(i = 0; i < sizeof(FormatList) / sizeof(WINED3DFORMAT); i++)
1207 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1208 0 /* Adapter */,
1209 0 /* DeviceType */,
1210 0 /* AdapterFormat */,
1211 0 /* Usage */,
1212 0 /* ResourceType */,
1213 FormatList[i],
1214 SURFACE_OPENGL);
1215 if(hr == D3D_OK)
1217 DDPIXELFORMAT pformat;
1219 memset(&pformat, 0, sizeof(pformat));
1220 pformat.dwSize = sizeof(pformat);
1221 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1223 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1224 hr = Callback(&pformat, Arg);
1225 if(hr != DDENUMRET_OK)
1227 TRACE("Format enumeration cancelled by application\n");
1228 LeaveCriticalSection(&ddraw_cs);
1229 return D3D_OK;
1234 for(i = 0; i < sizeof(BumpFormatList) / sizeof(WINED3DFORMAT); i++)
1236 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1237 0 /* Adapter */,
1238 0 /* DeviceType */,
1239 0 /* AdapterFormat */,
1240 WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1241 0 /* ResourceType */,
1242 BumpFormatList[i],
1243 SURFACE_OPENGL);
1244 if(hr == D3D_OK)
1246 DDPIXELFORMAT pformat;
1248 memset(&pformat, 0, sizeof(pformat));
1249 pformat.dwSize = sizeof(pformat);
1250 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1252 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1253 hr = Callback(&pformat, Arg);
1254 if(hr != DDENUMRET_OK)
1256 TRACE("Format enumeration cancelled by application\n");
1257 LeaveCriticalSection(&ddraw_cs);
1258 return D3D_OK;
1262 TRACE("End of enumeration\n");
1263 LeaveCriticalSection(&ddraw_cs);
1264 return D3D_OK;
1267 static HRESULT WINAPI
1268 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1269 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1270 void *Arg)
1272 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1275 static HRESULT WINAPI
1276 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1277 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1278 void *Arg)
1280 HRESULT hr;
1281 WORD old_fpucw;
1283 old_fpucw = d3d_fpu_setup();
1284 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1285 set_fpu_control_word(old_fpucw);
1287 return hr;
1290 static HRESULT WINAPI
1291 Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1292 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1293 void *Arg)
1295 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1296 TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice7 interface.\n", This, Callback, Arg);
1297 return IDirect3DDevice7_EnumTextureFormats(ICOM_INTERFACE(This, IDirect3DDevice7),
1298 Callback,
1299 Arg);
1302 /*****************************************************************************
1303 * IDirect3DDevice2::EnumTextureformats
1305 * EnumTextureFormats for Version 1 and 2, see
1306 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1308 * This version has a different callback and does not enumerate FourCC
1309 * formats
1311 *****************************************************************************/
1312 static HRESULT WINAPI
1313 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1314 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1315 void *Arg)
1317 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1318 HRESULT hr;
1319 int i;
1321 WINED3DFORMAT FormatList[] = {
1322 /* 32 bit */
1323 WINED3DFMT_A8R8G8B8,
1324 WINED3DFMT_X8R8G8B8,
1325 /* 24 bit */
1326 WINED3DFMT_R8G8B8,
1327 /* 16 Bit */
1328 WINED3DFMT_A1R5G5B5,
1329 WINED3DFMT_A4R4G4B4,
1330 WINED3DFMT_R5G6B5,
1331 WINED3DFMT_X1R5G5B5,
1332 /* 8 Bit */
1333 WINED3DFMT_R3G3B2,
1334 WINED3DFMT_P8,
1335 /* FOURCC codes - Not in this version*/
1338 TRACE("(%p)->(%p,%p): Relay\n", This, Callback, Arg);
1340 if(!Callback)
1341 return DDERR_INVALIDPARAMS;
1343 EnterCriticalSection(&ddraw_cs);
1344 for(i = 0; i < sizeof(FormatList) / sizeof(WINED3DFORMAT); i++)
1346 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1347 0 /* Adapter */,
1348 0 /* DeviceType */,
1349 0 /* AdapterFormat */,
1350 0 /* Usage */,
1351 0 /* ResourceType */,
1352 FormatList[i],
1353 SURFACE_OPENGL);
1354 if(hr == D3D_OK)
1356 DDSURFACEDESC sdesc;
1358 memset(&sdesc, 0, sizeof(sdesc));
1359 sdesc.dwSize = sizeof(sdesc);
1360 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1361 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1362 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1363 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1365 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1366 hr = Callback(&sdesc, Arg);
1367 if(hr != DDENUMRET_OK)
1369 TRACE("Format enumeration cancelled by application\n");
1370 LeaveCriticalSection(&ddraw_cs);
1371 return D3D_OK;
1375 TRACE("End of enumeration\n");
1376 LeaveCriticalSection(&ddraw_cs);
1377 return D3D_OK;
1380 static HRESULT WINAPI
1381 Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1382 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1383 void *Arg)
1385 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1386 TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice2 interface.\n", This, Callback, Arg);
1387 return IDirect3DDevice2_EnumTextureFormats(ICOM_INTERFACE(This, IDirect3DDevice2),
1388 Callback,
1389 Arg);
1392 /*****************************************************************************
1393 * IDirect3DDevice::CreateMatrix
1395 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1396 * allocated for the handle.
1398 * Version 1 only
1400 * Params
1401 * D3DMatHandle: Address to return the handle at
1403 * Returns:
1404 * D3D_OK on success
1405 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1407 *****************************************************************************/
1408 static HRESULT WINAPI
1409 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1411 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1412 D3DMATRIX *Matrix;
1413 TRACE("(%p)->(%p)\n", This, D3DMatHandle);
1415 if(!D3DMatHandle)
1416 return DDERR_INVALIDPARAMS;
1418 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1419 if(!Matrix)
1421 ERR("Out of memory when allocating a D3DMATRIX\n");
1422 return DDERR_OUTOFMEMORY;
1425 EnterCriticalSection(&ddraw_cs);
1426 *D3DMatHandle = IDirect3DDeviceImpl_CreateHandle(This);
1427 if(!(*D3DMatHandle))
1429 ERR("Failed to create a matrix handle\n");
1430 HeapFree(GetProcessHeap(), 0, Matrix);
1431 LeaveCriticalSection(&ddraw_cs);
1432 return DDERR_OUTOFMEMORY;
1434 This->Handles[*D3DMatHandle - 1].ptr = Matrix;
1435 This->Handles[*D3DMatHandle - 1].type = DDrawHandle_Matrix;
1436 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1438 LeaveCriticalSection(&ddraw_cs);
1439 return D3D_OK;
1442 /*****************************************************************************
1443 * IDirect3DDevice::SetMatrix
1445 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1446 * allocated for the handle
1448 * Version 1 only
1450 * Params:
1451 * D3DMatHandle: Handle to set the matrix to
1452 * D3DMatrix: Matrix to set
1454 * Returns:
1455 * D3D_OK on success
1456 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1457 * to set is NULL
1459 *****************************************************************************/
1460 static HRESULT WINAPI
1461 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1462 D3DMATRIXHANDLE D3DMatHandle,
1463 D3DMATRIX *D3DMatrix)
1465 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1466 TRACE("(%p)->(%08x,%p)\n", This, D3DMatHandle, D3DMatrix);
1468 if( (!D3DMatHandle) || (!D3DMatrix) )
1469 return DDERR_INVALIDPARAMS;
1471 EnterCriticalSection(&ddraw_cs);
1472 if(D3DMatHandle > This->numHandles)
1474 ERR("Handle %d out of range\n", D3DMatHandle);
1475 LeaveCriticalSection(&ddraw_cs);
1476 return DDERR_INVALIDPARAMS;
1478 else if(This->Handles[D3DMatHandle - 1].type != DDrawHandle_Matrix)
1480 ERR("Handle %d is not a matrix handle\n", D3DMatHandle);
1481 LeaveCriticalSection(&ddraw_cs);
1482 return DDERR_INVALIDPARAMS;
1485 if (TRACE_ON(d3d7))
1486 dump_D3DMATRIX(D3DMatrix);
1488 *((D3DMATRIX *) This->Handles[D3DMatHandle - 1].ptr) = *D3DMatrix;
1490 if(This->world == D3DMatHandle)
1492 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1493 WINED3DTS_WORLDMATRIX(0),
1494 (WINED3DMATRIX *) D3DMatrix);
1496 if(This->view == D3DMatHandle)
1498 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1499 WINED3DTS_VIEW,
1500 (WINED3DMATRIX *) D3DMatrix);
1502 if(This->proj == D3DMatHandle)
1504 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1505 WINED3DTS_PROJECTION,
1506 (WINED3DMATRIX *) D3DMatrix);
1509 LeaveCriticalSection(&ddraw_cs);
1510 return D3D_OK;
1513 /*****************************************************************************
1514 * IDirect3DDevice::SetMatrix
1516 * Returns the content of a D3DMATRIX handle
1518 * Version 1 only
1520 * Params:
1521 * D3DMatHandle: Matrix handle to read the content from
1522 * D3DMatrix: Address to store the content at
1524 * Returns:
1525 * D3D_OK on success
1526 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1528 *****************************************************************************/
1529 static HRESULT WINAPI
1530 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1531 D3DMATRIXHANDLE D3DMatHandle,
1532 D3DMATRIX *D3DMatrix)
1534 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1535 TRACE("(%p)->(%08x,%p)\n", This, D3DMatHandle, D3DMatrix);
1537 if(!D3DMatrix)
1538 return DDERR_INVALIDPARAMS;
1539 if(!D3DMatHandle)
1540 return DDERR_INVALIDPARAMS;
1542 EnterCriticalSection(&ddraw_cs);
1543 if(D3DMatHandle > This->numHandles)
1545 ERR("Handle %d out of range\n", D3DMatHandle);
1546 LeaveCriticalSection(&ddraw_cs);
1547 return DDERR_INVALIDPARAMS;
1549 else if(This->Handles[D3DMatHandle - 1].type != DDrawHandle_Matrix)
1551 ERR("Handle %d is not a matrix handle\n", D3DMatHandle);
1552 LeaveCriticalSection(&ddraw_cs);
1553 return DDERR_INVALIDPARAMS;
1556 /* The handle is simply a pointer to a D3DMATRIX structure */
1557 *D3DMatrix = *((D3DMATRIX *) This->Handles[D3DMatHandle - 1].ptr);
1559 LeaveCriticalSection(&ddraw_cs);
1560 return D3D_OK;
1563 /*****************************************************************************
1564 * IDirect3DDevice::DeleteMatrix
1566 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1568 * Version 1 only
1570 * Params:
1571 * D3DMatHandle: Handle to destroy
1573 * Returns:
1574 * D3D_OK on success
1575 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1577 *****************************************************************************/
1578 static HRESULT WINAPI
1579 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1580 D3DMATRIXHANDLE D3DMatHandle)
1582 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1583 TRACE("(%p)->(%08x)\n", This, D3DMatHandle);
1585 if(!D3DMatHandle)
1586 return DDERR_INVALIDPARAMS;
1588 EnterCriticalSection(&ddraw_cs);
1589 if(D3DMatHandle > This->numHandles)
1591 ERR("Handle %d out of range\n", D3DMatHandle);
1592 LeaveCriticalSection(&ddraw_cs);
1593 return DDERR_INVALIDPARAMS;
1595 else if(This->Handles[D3DMatHandle - 1].type != DDrawHandle_Matrix)
1597 ERR("Handle %d is not a matrix handle\n", D3DMatHandle);
1598 LeaveCriticalSection(&ddraw_cs);
1599 return DDERR_INVALIDPARAMS;
1602 HeapFree(GetProcessHeap(), 0, This->Handles[D3DMatHandle - 1].ptr);
1603 This->Handles[D3DMatHandle - 1].ptr = NULL;
1604 This->Handles[D3DMatHandle - 1].type = DDrawHandle_Unknown;
1606 LeaveCriticalSection(&ddraw_cs);
1607 return D3D_OK;
1610 /*****************************************************************************
1611 * IDirect3DDevice7::BeginScene
1613 * This method must be called before any rendering is performed.
1614 * IDirect3DDevice::EndScene has to be called after the scene is complete
1616 * Version 1, 2, 3 and 7
1618 * Returns:
1619 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1620 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1621 * started scene).
1623 *****************************************************************************/
1624 static HRESULT
1625 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1627 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1628 HRESULT hr;
1629 TRACE("(%p): Relay\n", This);
1631 EnterCriticalSection(&ddraw_cs);
1632 hr = IWineD3DDevice_BeginScene(This->wineD3DDevice);
1633 LeaveCriticalSection(&ddraw_cs);
1634 if(hr == WINED3D_OK) return D3D_OK;
1635 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1638 static HRESULT WINAPI
1639 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1641 return IDirect3DDeviceImpl_7_BeginScene(iface);
1644 static HRESULT WINAPI
1645 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1647 HRESULT hr;
1648 WORD old_fpucw;
1650 old_fpucw = d3d_fpu_setup();
1651 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1652 set_fpu_control_word(old_fpucw);
1654 return hr;
1657 static HRESULT WINAPI
1658 Thunk_IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1660 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1661 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1662 return IDirect3DDevice7_BeginScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1665 static HRESULT WINAPI
1666 Thunk_IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1668 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1669 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1670 return IDirect3DDevice7_BeginScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1673 static HRESULT WINAPI
1674 Thunk_IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1676 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1677 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1678 return IDirect3DDevice7_BeginScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1681 /*****************************************************************************
1682 * IDirect3DDevice7::EndScene
1684 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1685 * This method must be called after rendering is finished.
1687 * Version 1, 2, 3 and 7
1689 * Returns:
1690 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1691 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1692 * that only if the scene was already ended.
1694 *****************************************************************************/
1695 static HRESULT
1696 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1698 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1699 HRESULT hr;
1700 TRACE("(%p): Relay\n", This);
1702 EnterCriticalSection(&ddraw_cs);
1703 hr = IWineD3DDevice_EndScene(This->wineD3DDevice);
1704 LeaveCriticalSection(&ddraw_cs);
1705 if(hr == WINED3D_OK) return D3D_OK;
1706 else return D3DERR_SCENE_NOT_IN_SCENE;
1709 static HRESULT WINAPI
1710 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1712 return IDirect3DDeviceImpl_7_EndScene(iface);
1715 static HRESULT WINAPI
1716 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1718 HRESULT hr;
1719 WORD old_fpucw;
1721 old_fpucw = d3d_fpu_setup();
1722 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1723 set_fpu_control_word(old_fpucw);
1725 return hr;
1728 static HRESULT WINAPI
1729 Thunk_IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1731 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1732 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1733 return IDirect3DDevice7_EndScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1736 static HRESULT WINAPI
1737 Thunk_IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1739 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1740 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1741 return IDirect3DDevice7_EndScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1744 static HRESULT WINAPI
1745 Thunk_IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1747 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1748 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1749 return IDirect3DDevice7_EndScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1752 /*****************************************************************************
1753 * IDirect3DDevice7::GetDirect3D
1755 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1756 * this device.
1758 * Params:
1759 * Direct3D7: Address to store the interface pointer at
1761 * Returns:
1762 * D3D_OK on success
1763 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1765 *****************************************************************************/
1766 static HRESULT WINAPI
1767 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1768 IDirect3D7 **Direct3D7)
1770 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1771 TRACE("(%p)->(%p)\n", This, Direct3D7);
1773 if(!Direct3D7)
1774 return DDERR_INVALIDPARAMS;
1776 *Direct3D7 = ICOM_INTERFACE(This->ddraw, IDirect3D7);
1777 IDirect3D7_AddRef(*Direct3D7);
1779 TRACE(" returning interface %p\n", *Direct3D7);
1780 return D3D_OK;
1783 static HRESULT WINAPI
1784 Thunk_IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1785 IDirect3D3 **Direct3D3)
1787 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1788 HRESULT ret;
1789 IDirect3D7 *ret_ptr;
1791 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Direct3D3);
1792 ret = IDirect3DDevice7_GetDirect3D(ICOM_INTERFACE(This, IDirect3DDevice7),
1793 &ret_ptr);
1794 if(ret != D3D_OK)
1795 return ret;
1796 *Direct3D3 = COM_INTERFACE_CAST(IDirectDrawImpl, IDirect3D7, IDirect3D3, ret_ptr);
1797 TRACE(" returning interface %p\n", *Direct3D3);
1798 return D3D_OK;
1801 static HRESULT WINAPI
1802 Thunk_IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1803 IDirect3D2 **Direct3D2)
1805 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1806 HRESULT ret;
1807 IDirect3D7 *ret_ptr;
1809 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Direct3D2);
1810 ret = IDirect3DDevice7_GetDirect3D(ICOM_INTERFACE(This, IDirect3DDevice7),
1811 &ret_ptr);
1812 if(ret != D3D_OK)
1813 return ret;
1814 *Direct3D2 = COM_INTERFACE_CAST(IDirectDrawImpl, IDirect3D7, IDirect3D2, ret_ptr);
1815 TRACE(" returning interface %p\n", *Direct3D2);
1816 return D3D_OK;
1819 static HRESULT WINAPI
1820 Thunk_IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1821 IDirect3D **Direct3D)
1823 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1824 HRESULT ret;
1825 IDirect3D7 *ret_ptr;
1827 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Direct3D);
1828 ret = IDirect3DDevice7_GetDirect3D(ICOM_INTERFACE(This, IDirect3DDevice7),
1829 &ret_ptr);
1830 if(ret != D3D_OK)
1831 return ret;
1832 *Direct3D = COM_INTERFACE_CAST(IDirectDrawImpl, IDirect3D7, IDirect3D, ret_ptr);
1833 TRACE(" returning interface %p\n", *Direct3D);
1834 return D3D_OK;
1837 /*****************************************************************************
1838 * IDirect3DDevice3::SetCurrentViewport
1840 * Sets a Direct3DViewport as the current viewport.
1841 * For the thunks note that all viewport interface versions are equal
1843 * Params:
1844 * Direct3DViewport3: The viewport to set
1846 * Version 2 and 3
1848 * Returns:
1849 * D3D_OK on success
1850 * (Is a NULL viewport valid?)
1852 *****************************************************************************/
1853 static HRESULT WINAPI
1854 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1855 IDirect3DViewport3 *Direct3DViewport3)
1857 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1858 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Direct3DViewport3);
1859 TRACE("(%p)->(%p)\n", This, Direct3DViewport3);
1861 EnterCriticalSection(&ddraw_cs);
1862 /* Do nothing if the specified viewport is the same as the current one */
1863 if (This->current_viewport == vp )
1865 LeaveCriticalSection(&ddraw_cs);
1866 return D3D_OK;
1869 /* Should check if the viewport was added or not */
1871 /* Release previous viewport and AddRef the new one */
1872 if (This->current_viewport)
1874 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport, ICOM_INTERFACE(This->current_viewport, IDirect3DViewport3));
1875 IDirect3DViewport3_Release( ICOM_INTERFACE(This->current_viewport, IDirect3DViewport3) );
1877 IDirect3DViewport3_AddRef(Direct3DViewport3);
1879 /* Set this viewport as the current viewport */
1880 This->current_viewport = vp;
1882 /* Activate this viewport */
1883 This->current_viewport->active_device = This;
1884 This->current_viewport->activate(This->current_viewport, FALSE);
1886 LeaveCriticalSection(&ddraw_cs);
1887 return D3D_OK;
1890 static HRESULT WINAPI
1891 Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1892 IDirect3DViewport2 *Direct3DViewport2)
1894 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1895 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Direct3DViewport2);
1896 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
1897 return IDirect3DDevice3_SetCurrentViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
1898 ICOM_INTERFACE(vp, IDirect3DViewport3));
1901 /*****************************************************************************
1902 * IDirect3DDevice3::GetCurrentViewport
1904 * Returns the currently active viewport.
1906 * Version 2 and 3
1908 * Params:
1909 * Direct3DViewport3: Address to return the interface pointer at
1911 * Returns:
1912 * D3D_OK on success
1913 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1915 *****************************************************************************/
1916 static HRESULT WINAPI
1917 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1918 IDirect3DViewport3 **Direct3DViewport3)
1920 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1921 TRACE("(%p)->(%p)\n", This, Direct3DViewport3);
1923 if(!Direct3DViewport3)
1924 return DDERR_INVALIDPARAMS;
1926 EnterCriticalSection(&ddraw_cs);
1927 *Direct3DViewport3 = ICOM_INTERFACE(This->current_viewport, IDirect3DViewport3);
1929 /* AddRef the returned viewport */
1930 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1932 TRACE(" returning interface %p\n", *Direct3DViewport3);
1934 LeaveCriticalSection(&ddraw_cs);
1935 return D3D_OK;
1938 static HRESULT WINAPI
1939 Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1940 IDirect3DViewport2 **Direct3DViewport2)
1942 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1943 HRESULT hr;
1944 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, Direct3DViewport2);
1945 hr = IDirect3DDevice3_GetCurrentViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
1946 (IDirect3DViewport3 **) Direct3DViewport2);
1947 if(hr != D3D_OK) return hr;
1948 *Direct3DViewport2 = (IDirect3DViewport2 *) COM_INTERFACE_CAST(IDirect3DViewportImpl, IDirect3DViewport3, IDirect3DViewport3, *Direct3DViewport2);
1949 return D3D_OK;
1952 /*****************************************************************************
1953 * IDirect3DDevice7::SetRenderTarget
1955 * Sets the render target for the Direct3DDevice.
1956 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1957 * IDirectDrawSurface3 == IDirectDrawSurface
1959 * Version 2, 3 and 7
1961 * Params:
1962 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1963 * render target
1964 * Flags: Some flags
1966 * Returns:
1967 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1969 *****************************************************************************/
1970 static HRESULT
1971 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1972 IDirectDrawSurface7 *NewTarget,
1973 DWORD Flags)
1975 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1976 IDirectDrawSurfaceImpl *Target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, NewTarget);
1977 HRESULT hr;
1978 TRACE("(%p)->(%p,%08x): Relay\n", This, NewTarget, Flags);
1980 EnterCriticalSection(&ddraw_cs);
1981 /* Flags: Not used */
1983 if(This->target == Target)
1985 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1986 LeaveCriticalSection(&ddraw_cs);
1987 return D3D_OK;
1990 hr = IWineD3DDevice_SetRenderTarget(This->wineD3DDevice,
1992 Target ? Target->WineD3DSurface : NULL);
1993 if(hr != D3D_OK)
1995 LeaveCriticalSection(&ddraw_cs);
1996 return hr;
1998 IDirectDrawSurface7_AddRef(NewTarget);
1999 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->target, IDirectDrawSurface7));
2000 This->target = Target;
2001 IDirect3DDeviceImpl_UpdateDepthStencil(This);
2002 LeaveCriticalSection(&ddraw_cs);
2003 return D3D_OK;
2006 static HRESULT WINAPI
2007 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
2008 IDirectDrawSurface7 *NewTarget,
2009 DWORD Flags)
2011 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
2014 static HRESULT WINAPI
2015 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
2016 IDirectDrawSurface7 *NewTarget,
2017 DWORD Flags)
2019 HRESULT hr;
2020 WORD old_fpucw;
2022 old_fpucw = d3d_fpu_setup();
2023 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
2024 set_fpu_control_word(old_fpucw);
2026 return hr;
2029 static HRESULT WINAPI
2030 Thunk_IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
2031 IDirectDrawSurface4 *NewRenderTarget,
2032 DWORD Flags)
2034 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2035 IDirectDrawSurfaceImpl *Target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, NewRenderTarget);
2036 TRACE_(ddraw_thunk)("(%p)->(%p,%08x) thunking to IDirect3DDevice7 interface.\n", This, Target, Flags);
2037 return IDirect3DDevice7_SetRenderTarget(ICOM_INTERFACE(This, IDirect3DDevice7),
2038 ICOM_INTERFACE(Target, IDirectDrawSurface7),
2039 Flags);
2042 static HRESULT WINAPI
2043 Thunk_IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
2044 IDirectDrawSurface *NewRenderTarget,
2045 DWORD Flags)
2047 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2048 IDirectDrawSurfaceImpl *Target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface3, NewRenderTarget);
2049 TRACE_(ddraw_thunk)("(%p)->(%p,%08x) thunking to IDirect3DDevice7 interface.\n", This, Target, Flags);
2050 return IDirect3DDevice7_SetRenderTarget(ICOM_INTERFACE(This, IDirect3DDevice7),
2051 ICOM_INTERFACE(Target, IDirectDrawSurface7),
2052 Flags);
2055 /*****************************************************************************
2056 * IDirect3DDevice7::GetRenderTarget
2058 * Returns the current render target.
2059 * This is handled locally, because the WineD3D render target's parent
2060 * is an IParent
2062 * Version 2, 3 and 7
2064 * Params:
2065 * RenderTarget: Address to store the surface interface pointer
2067 * Returns:
2068 * D3D_OK on success
2069 * DDERR_INVALIDPARAMS if RenderTarget == NULL
2071 *****************************************************************************/
2072 static HRESULT WINAPI
2073 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
2074 IDirectDrawSurface7 **RenderTarget)
2076 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2077 TRACE("(%p)->(%p): Relay\n", This, RenderTarget);
2079 if(!RenderTarget)
2080 return DDERR_INVALIDPARAMS;
2082 EnterCriticalSection(&ddraw_cs);
2083 *RenderTarget = ICOM_INTERFACE(This->target, IDirectDrawSurface7);
2084 IDirectDrawSurface7_AddRef(*RenderTarget);
2086 LeaveCriticalSection(&ddraw_cs);
2087 return D3D_OK;
2090 static HRESULT WINAPI
2091 Thunk_IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
2092 IDirectDrawSurface4 **RenderTarget)
2094 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2095 HRESULT hr;
2096 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, RenderTarget);
2097 hr = IDirect3DDevice7_GetRenderTarget(ICOM_INTERFACE(This, IDirect3DDevice7),
2098 (IDirectDrawSurface7 **) RenderTarget);
2099 if(hr != D3D_OK) return hr;
2100 *RenderTarget = (IDirectDrawSurface4 *) COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirectDrawSurface7, IDirectDrawSurface7, *RenderTarget);
2101 return D3D_OK;
2104 static HRESULT WINAPI
2105 Thunk_IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
2106 IDirectDrawSurface **RenderTarget)
2108 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2109 HRESULT hr;
2110 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, RenderTarget);
2111 hr = IDirect3DDevice7_GetRenderTarget(ICOM_INTERFACE(This, IDirect3DDevice7),
2112 (IDirectDrawSurface7 **) RenderTarget);
2113 if(hr != D3D_OK) return hr;
2114 *RenderTarget = (IDirectDrawSurface *) COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirectDrawSurface7, IDirectDrawSurface3, *RenderTarget);
2115 return D3D_OK;
2118 /*****************************************************************************
2119 * IDirect3DDevice3::Begin
2121 * Begins a description block of vertices. This is similar to glBegin()
2122 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2123 * described with IDirect3DDevice::Vertex are drawn.
2125 * Version 2 and 3
2127 * Params:
2128 * PrimitiveType: The type of primitives to draw
2129 * VertexTypeDesc: A flexible vertex format description of the vertices
2130 * Flags: Some flags..
2132 * Returns:
2133 * D3D_OK on success
2135 *****************************************************************************/
2136 static HRESULT WINAPI
2137 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2138 D3DPRIMITIVETYPE PrimitiveType,
2139 DWORD VertexTypeDesc,
2140 DWORD Flags)
2142 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2143 TRACE("(%p)->(%d,%d,%08x)\n", This, PrimitiveType, VertexTypeDesc, Flags);
2145 EnterCriticalSection(&ddraw_cs);
2146 This->primitive_type = PrimitiveType;
2147 This->vertex_type = VertexTypeDesc;
2148 This->render_flags = Flags;
2149 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2150 This->nb_vertices = 0;
2151 LeaveCriticalSection(&ddraw_cs);
2153 return D3D_OK;
2156 static HRESULT WINAPI
2157 Thunk_IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface,
2158 D3DPRIMITIVETYPE d3dpt,
2159 D3DVERTEXTYPE dwVertexTypeDesc,
2160 DWORD dwFlags)
2162 DWORD FVF;
2163 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2164 TRACE_(ddraw_thunk)("(%p/%p)->(%08x,%08x,%08x): Thunking to IDirect3DDevice3\n", This, iface, d3dpt, dwVertexTypeDesc, dwFlags);
2166 switch(dwVertexTypeDesc)
2168 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2169 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2170 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2171 default:
2172 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2173 return DDERR_INVALIDPARAMS; /* Should never happen */
2176 return IDirect3DDevice3_Begin(ICOM_INTERFACE(This, IDirect3DDevice3),
2177 d3dpt,
2178 FVF,
2179 dwFlags);
2182 /*****************************************************************************
2183 * IDirect3DDevice3::BeginIndexed
2185 * Draws primitives based on vertices in a vertex array which are specified
2186 * by indices.
2188 * Version 2 and 3
2190 * Params:
2191 * PrimitiveType: Primitive type to draw
2192 * VertexType: A FVF description of the vertex format
2193 * Vertices: pointer to an array containing the vertices
2194 * NumVertices: The number of vertices in the vertex array
2195 * Flags: Some flags ...
2197 * Returns:
2198 * D3D_OK, because it's a stub
2200 *****************************************************************************/
2201 static HRESULT WINAPI
2202 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2203 D3DPRIMITIVETYPE PrimitiveType,
2204 DWORD VertexType,
2205 void *Vertices,
2206 DWORD NumVertices,
2207 DWORD Flags)
2209 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2210 FIXME("(%p)->(%08x,%08x,%p,%08x,%08x): stub!\n", This, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2211 return D3D_OK;
2215 static HRESULT WINAPI
2216 Thunk_IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2217 D3DPRIMITIVETYPE d3dptPrimitiveType,
2218 D3DVERTEXTYPE d3dvtVertexType,
2219 void *lpvVertices,
2220 DWORD dwNumVertices,
2221 DWORD dwFlags)
2223 DWORD FVF;
2224 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2225 TRACE_(ddraw_thunk)("(%p/%p)->(%08x,%08x,%p,%08x,%08x): Thunking to IDirect3DDevice3\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2227 switch(d3dvtVertexType)
2229 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2230 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2231 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2232 default:
2233 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2234 return DDERR_INVALIDPARAMS; /* Should never happen */
2237 return IDirect3DDevice3_BeginIndexed(ICOM_INTERFACE(This,IDirect3DDevice3),
2238 d3dptPrimitiveType,
2239 FVF,
2240 lpvVertices,
2241 dwNumVertices,
2242 dwFlags);
2245 /*****************************************************************************
2246 * IDirect3DDevice3::Vertex
2248 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2249 * drawn vertices in a vertex buffer. If the buffer is too small, its
2250 * size is increased.
2252 * Version 2 and 3
2254 * Params:
2255 * Vertex: Pointer to the vertex
2257 * Returns:
2258 * D3D_OK, on success
2259 * DDERR_INVALIDPARAMS if Vertex is NULL
2261 *****************************************************************************/
2262 static HRESULT WINAPI
2263 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2264 void *Vertex)
2266 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2267 TRACE("(%p)->(%p)\n", This, Vertex);
2269 if(!Vertex)
2270 return DDERR_INVALIDPARAMS;
2272 EnterCriticalSection(&ddraw_cs);
2273 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2275 BYTE *old_buffer;
2276 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2277 old_buffer = This->vertex_buffer;
2278 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2279 if (old_buffer)
2281 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2282 HeapFree(GetProcessHeap(), 0, old_buffer);
2286 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2288 LeaveCriticalSection(&ddraw_cs);
2289 return D3D_OK;
2292 static HRESULT WINAPI
2293 Thunk_IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface,
2294 void *lpVertexType)
2296 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2297 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, lpVertexType);
2298 return IDirect3DDevice3_Vertex(ICOM_INTERFACE(This, IDirect3DDevice3),
2299 lpVertexType);
2302 /*****************************************************************************
2303 * IDirect3DDevice3::Index
2305 * Specifies an index to a vertex to be drawn. The vertex array has to
2306 * be specified with BeginIndexed first.
2308 * Parameters:
2309 * VertexIndex: The index of the vertex to draw
2311 * Returns:
2312 * D3D_OK because it's a stub
2314 *****************************************************************************/
2315 static HRESULT WINAPI
2316 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2317 WORD VertexIndex)
2319 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2320 FIXME("(%p)->(%04x): stub!\n", This, VertexIndex);
2321 return D3D_OK;
2324 static HRESULT WINAPI
2325 Thunk_IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface,
2326 WORD wVertexIndex)
2328 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2329 TRACE_(ddraw_thunk)("(%p)->(%04x) thunking to IDirect3DDevice3 interface.\n", This, wVertexIndex);
2330 return IDirect3DDevice3_Index(ICOM_INTERFACE(This, IDirect3DDevice3),
2331 wVertexIndex);
2334 /*****************************************************************************
2335 * IDirect3DDevice3::End
2337 * Ends a draw begun with IDirect3DDevice3::Begin or
2338 * IDirect3DDevice::BeginIndexed. The vertices specified with
2339 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2340 * the IDirect3DDevice7::DrawPrimitive method. So far only
2341 * non-indexed mode is supported
2343 * Version 2 and 3
2345 * Params:
2346 * Flags: Some flags, as usual. Don't know which are defined
2348 * Returns:
2349 * The return value of IDirect3DDevice7::DrawPrimitive
2351 *****************************************************************************/
2352 static HRESULT WINAPI
2353 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2354 DWORD Flags)
2356 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2357 TRACE("(%p)->(%08x)\n", This, Flags);
2359 return IDirect3DDevice7_DrawPrimitive(ICOM_INTERFACE(This, IDirect3DDevice7),
2360 This->primitive_type, This->vertex_type,
2361 This->vertex_buffer, This->nb_vertices,
2362 This->render_flags);
2365 static HRESULT WINAPI
2366 Thunk_IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface,
2367 DWORD dwFlags)
2369 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2370 TRACE_(ddraw_thunk)("(%p)->(%08x) thunking to IDirect3DDevice3 interface.\n", This, dwFlags);
2371 return IDirect3DDevice3_End(ICOM_INTERFACE(This, IDirect3DDevice3),
2372 dwFlags);
2375 /*****************************************************************************
2376 * IDirect3DDevice7::GetRenderState
2378 * Returns the value of a render state. The possible render states are
2379 * defined in include/d3dtypes.h
2381 * Version 2, 3 and 7
2383 * Params:
2384 * RenderStateType: Render state to return the current setting of
2385 * Value: Address to store the value at
2387 * Returns:
2388 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2389 * DDERR_INVALIDPARAMS if Value == NULL
2391 *****************************************************************************/
2392 static HRESULT
2393 IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2394 D3DRENDERSTATETYPE RenderStateType,
2395 DWORD *Value)
2397 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2398 HRESULT hr;
2399 TRACE("(%p)->(%08x,%p): Relay\n", This, RenderStateType, Value);
2401 if(!Value)
2402 return DDERR_INVALIDPARAMS;
2404 EnterCriticalSection(&ddraw_cs);
2405 switch(RenderStateType)
2407 case D3DRENDERSTATE_TEXTUREMAG:
2409 WINED3DTEXTUREFILTERTYPE tex_mag;
2411 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2412 0, WINED3DSAMP_MAGFILTER,
2413 &tex_mag);
2415 switch (tex_mag)
2417 case WINED3DTEXF_POINT:
2418 *Value = D3DFILTER_NEAREST;
2419 break;
2420 case WINED3DTEXF_LINEAR:
2421 *Value = D3DFILTER_LINEAR;
2422 break;
2423 default:
2424 ERR("Unhandled texture mag %d !\n",tex_mag);
2425 *Value = 0;
2427 break;
2430 case D3DRENDERSTATE_TEXTUREMIN:
2432 WINED3DTEXTUREFILTERTYPE tex_min;
2434 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2435 0, WINED3DSAMP_MINFILTER,
2436 &tex_min);
2438 switch (tex_min)
2440 case WINED3DTEXF_POINT:
2441 *Value = D3DFILTER_NEAREST;
2442 break;
2443 case WINED3DTEXF_LINEAR:
2444 *Value = D3DFILTER_LINEAR;
2445 break;
2446 default:
2447 ERR("Unhandled texture mag %d !\n",tex_min);
2448 *Value = 0;
2450 break;
2453 case D3DRENDERSTATE_TEXTUREADDRESS:
2454 case D3DRENDERSTATE_TEXTUREADDRESSU:
2455 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2456 0, WINED3DSAMP_ADDRESSU,
2457 Value);
2458 break;
2459 case D3DRENDERSTATE_TEXTUREADDRESSV:
2460 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2461 0, WINED3DSAMP_ADDRESSV,
2462 Value);
2463 break;
2465 default:
2466 /* FIXME: Unhandled: D3DRENDERSTATE_STIPPLEPATTERN00 - 31 */
2467 hr = IWineD3DDevice_GetRenderState(This->wineD3DDevice,
2468 RenderStateType,
2469 Value);
2471 LeaveCriticalSection(&ddraw_cs);
2472 return hr;
2475 static HRESULT WINAPI
2476 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2477 D3DRENDERSTATETYPE RenderStateType,
2478 DWORD *Value)
2480 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2483 static HRESULT WINAPI
2484 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2485 D3DRENDERSTATETYPE RenderStateType,
2486 DWORD *Value)
2488 HRESULT hr;
2489 WORD old_fpucw;
2491 old_fpucw = d3d_fpu_setup();
2492 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2493 set_fpu_control_word(old_fpucw);
2495 return hr;
2498 static HRESULT WINAPI
2499 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2500 D3DRENDERSTATETYPE dwRenderStateType,
2501 DWORD *lpdwRenderState)
2503 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2504 HRESULT hr;
2505 TRACE("(%p)->(%08x,%p)\n", This, dwRenderStateType, lpdwRenderState);
2507 switch(dwRenderStateType)
2509 case D3DRENDERSTATE_TEXTUREHANDLE:
2511 /* This state is wrapped to SetTexture in SetRenderState, so
2512 * it has to be wrapped to GetTexture here
2514 IWineD3DBaseTexture *tex = NULL;
2515 *lpdwRenderState = 0;
2517 EnterCriticalSection(&ddraw_cs);
2519 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2521 &tex);
2523 if(hr == WINED3D_OK && tex)
2525 IDirectDrawSurface7 *parent = NULL;
2526 hr = IWineD3DBaseTexture_GetParent(tex,
2527 (IUnknown **) &parent);
2528 if(parent)
2530 /* The parent of the texture is the IDirectDrawSurface7 interface
2531 * of the ddraw surface
2533 IDirectDrawSurfaceImpl *texImpl = ICOM_OBJECT(IDirectDrawSurfaceImpl,
2534 IDirectDrawSurface7,
2535 parent);
2536 *lpdwRenderState = texImpl->Handle;
2537 IDirectDrawSurface7_Release(parent);
2539 IWineD3DBaseTexture_Release(tex);
2542 LeaveCriticalSection(&ddraw_cs);
2544 return hr;
2547 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2549 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2550 the mapping to get the value. */
2551 DWORD colorop, colorarg1, colorarg2;
2552 DWORD alphaop, alphaarg1, alphaarg2;
2554 EnterCriticalSection(&ddraw_cs);
2556 This->legacyTextureBlending = TRUE;
2558 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, &colorop);
2559 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, &colorarg1);
2560 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, &colorarg2);
2561 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, &alphaop);
2562 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2563 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2565 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2566 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2568 *lpdwRenderState = D3DTBLEND_DECAL;
2570 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2571 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2573 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2575 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2576 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2578 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2580 else
2582 HRESULT hr;
2583 BOOL tex_alpha = FALSE;
2584 IWineD3DBaseTexture *tex = NULL;
2585 WINED3DSURFACE_DESC desc;
2586 WINED3DFORMAT fmt;
2587 DDPIXELFORMAT ddfmt;
2589 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2591 &tex);
2593 if(hr == WINED3D_OK && tex)
2595 memset(&desc, 0, sizeof(desc));
2596 desc.Format = &fmt;
2597 hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2598 if (SUCCEEDED(hr))
2600 ddfmt.dwSize = sizeof(ddfmt);
2601 PixelFormat_WineD3DtoDD(&ddfmt, fmt);
2602 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2605 IWineD3DBaseTexture_Release(tex);
2608 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2609 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == (tex_alpha ? WINED3DTA_TEXTURE : WINED3DTA_CURRENT)))
2611 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2614 *lpdwRenderState = D3DTBLEND_MODULATE;
2617 LeaveCriticalSection(&ddraw_cs);
2619 return D3D_OK;
2622 default:
2623 return IDirect3DDevice7_GetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
2624 dwRenderStateType,
2625 lpdwRenderState);
2629 static HRESULT WINAPI
2630 Thunk_IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2631 D3DRENDERSTATETYPE dwRenderStateType,
2632 DWORD *lpdwRenderState)
2634 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2635 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice3 interface.\n", This, dwRenderStateType, lpdwRenderState);
2636 return IDirect3DDevice3_GetRenderState(ICOM_INTERFACE(This, IDirect3DDevice3),
2637 dwRenderStateType,
2638 lpdwRenderState);
2641 /*****************************************************************************
2642 * IDirect3DDevice7::SetRenderState
2644 * Sets a render state. The possible render states are defined in
2645 * include/d3dtypes.h
2647 * Version 2, 3 and 7
2649 * Params:
2650 * RenderStateType: State to set
2651 * Value: Value to assign to that state
2653 * Returns:
2654 * D3D_OK on success,
2655 * for details see IWineD3DDevice::SetRenderState
2657 *****************************************************************************/
2658 static HRESULT
2659 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2660 D3DRENDERSTATETYPE RenderStateType,
2661 DWORD Value)
2663 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2664 HRESULT hr;
2665 TRACE("(%p)->(%08x,%d): Relay\n", This, RenderStateType, Value);
2667 EnterCriticalSection(&ddraw_cs);
2668 /* Some render states need special care */
2669 switch(RenderStateType)
2671 case D3DRENDERSTATE_TEXTUREMAG:
2673 WINED3DTEXTUREFILTERTYPE tex_mag = WINED3DTEXF_NONE;
2675 switch ((D3DTEXTUREFILTER) Value)
2677 case D3DFILTER_NEAREST:
2678 case D3DFILTER_LINEARMIPNEAREST:
2679 tex_mag = WINED3DTEXF_POINT;
2680 break;
2681 case D3DFILTER_LINEAR:
2682 case D3DFILTER_LINEARMIPLINEAR:
2683 tex_mag = WINED3DTEXF_LINEAR;
2684 break;
2685 default:
2686 ERR("Unhandled texture mag %d !\n",Value);
2689 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2690 0, WINED3DSAMP_MAGFILTER,
2691 tex_mag);
2692 break;
2695 case D3DRENDERSTATE_TEXTUREMIN:
2697 WINED3DTEXTUREFILTERTYPE tex_min = WINED3DTEXF_NONE;
2698 WINED3DTEXTUREFILTERTYPE tex_mip = WINED3DTEXF_NONE;
2700 switch ((D3DTEXTUREFILTER) Value)
2702 case D3DFILTER_NEAREST:
2703 tex_min = WINED3DTEXF_POINT;
2704 break;
2705 case D3DFILTER_LINEAR:
2706 tex_min = WINED3DTEXF_LINEAR;
2707 break;
2708 case D3DFILTER_MIPNEAREST:
2709 tex_min = WINED3DTEXF_NONE;
2710 tex_mip = WINED3DTEXF_POINT;
2711 break;
2712 case D3DFILTER_MIPLINEAR:
2713 tex_min = WINED3DTEXF_NONE;
2714 tex_mip = WINED3DTEXF_LINEAR;
2715 break;
2716 case D3DFILTER_LINEARMIPNEAREST:
2717 tex_min = WINED3DTEXF_POINT;
2718 tex_mip = WINED3DTEXF_LINEAR;
2719 break;
2720 case D3DFILTER_LINEARMIPLINEAR:
2721 tex_min = WINED3DTEXF_LINEAR;
2722 tex_mip = WINED3DTEXF_LINEAR;
2723 break;
2725 default:
2726 ERR("Unhandled texture min %d !\n",Value);
2729 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2730 0, WINED3DSAMP_MIPFILTER,
2731 tex_mip);
2732 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2733 0, WINED3DSAMP_MINFILTER,
2734 tex_min);
2735 break;
2738 case D3DRENDERSTATE_TEXTUREADDRESS:
2739 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2740 0, WINED3DSAMP_ADDRESSV,
2741 Value);
2742 /* Drop through */
2743 case D3DRENDERSTATE_TEXTUREADDRESSU:
2744 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2745 0, WINED3DSAMP_ADDRESSU,
2746 Value);
2747 break;
2748 case D3DRENDERSTATE_TEXTUREADDRESSV:
2749 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2750 0, WINED3DSAMP_ADDRESSV,
2751 Value);
2752 break;
2754 default:
2756 /* FIXME: Unhandled: D3DRENDERSTATE_STIPPLEPATTERN00 - 31 */
2758 hr = IWineD3DDevice_SetRenderState(This->wineD3DDevice,
2759 RenderStateType,
2760 Value);
2761 break;
2763 LeaveCriticalSection(&ddraw_cs);
2764 return hr;
2767 static HRESULT WINAPI
2768 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2769 D3DRENDERSTATETYPE RenderStateType,
2770 DWORD Value)
2772 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2775 static HRESULT WINAPI
2776 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2777 D3DRENDERSTATETYPE RenderStateType,
2778 DWORD Value)
2780 HRESULT hr;
2781 WORD old_fpucw;
2783 old_fpucw = d3d_fpu_setup();
2784 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2785 set_fpu_control_word(old_fpucw);
2787 return hr;
2790 static HRESULT WINAPI
2791 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2792 D3DRENDERSTATETYPE RenderStateType,
2793 DWORD Value)
2795 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2796 for this state can be directly mapped to texture stage colorop and alphaop, but
2797 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2798 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2799 alphaarg when needed.
2801 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2803 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2804 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2805 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2806 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2807 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2808 in device - TRUE if the app is using TEXTUREMAPBLEND.
2810 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2811 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2812 unless some broken game will be found that cares. */
2814 HRESULT hr;
2815 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2816 TRACE("(%p)->(%08x,%d)\n", This, RenderStateType, Value);
2818 EnterCriticalSection(&ddraw_cs);
2820 switch(RenderStateType)
2822 case D3DRENDERSTATE_TEXTUREHANDLE:
2824 if(Value == 0)
2826 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
2828 NULL);
2829 break;
2832 if(Value > This->numHandles)
2834 FIXME("Specified handle %d out of range\n", Value);
2835 hr = DDERR_INVALIDPARAMS;
2836 break;
2838 if(This->Handles[Value - 1].type != DDrawHandle_Texture)
2840 FIXME("Handle %d isn't a texture handle\n", Value);
2841 hr = DDERR_INVALIDPARAMS;
2842 break;
2844 else
2846 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *) This->Handles[Value - 1].ptr;
2847 hr = IDirect3DDevice3_SetTexture(iface, 0, ICOM_INTERFACE(surf, IDirect3DTexture2));
2848 break;
2852 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2854 This->legacyTextureBlending = TRUE;
2856 switch ( (D3DTEXTUREBLEND) Value)
2858 case D3DTBLEND_MODULATE:
2860 BOOL tex_alpha = FALSE;
2861 IWineD3DBaseTexture *tex = NULL;
2862 WINED3DSURFACE_DESC desc;
2863 WINED3DFORMAT fmt;
2864 DDPIXELFORMAT ddfmt;
2866 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2868 &tex);
2870 if(hr == WINED3D_OK && tex)
2872 memset(&desc, 0, sizeof(desc));
2873 desc.Format = &fmt;
2874 hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2875 if (SUCCEEDED(hr))
2877 ddfmt.dwSize = sizeof(ddfmt);
2878 PixelFormat_WineD3DtoDD(&ddfmt, fmt);
2879 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2882 IWineD3DBaseTexture_Release(tex);
2885 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2886 if (tex_alpha)
2888 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2890 else
2892 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_CURRENT);
2895 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2896 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2897 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2899 break;
2902 case D3DTBLEND_ADD:
2903 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2904 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2905 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2906 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2907 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2908 break;
2910 case D3DTBLEND_MODULATEALPHA:
2911 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2912 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2913 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2914 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2915 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2916 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2917 break;
2919 case D3DTBLEND_COPY:
2920 case D3DTBLEND_DECAL:
2921 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2922 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2923 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2924 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2925 break;
2927 case D3DTBLEND_DECALALPHA:
2928 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2929 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2930 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2931 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2932 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2933 break;
2935 default:
2936 ERR("Unhandled texture environment %d !\n",Value);
2939 hr = D3D_OK;
2940 break;
2943 default:
2944 hr = IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
2945 RenderStateType,
2946 Value);
2947 break;
2950 LeaveCriticalSection(&ddraw_cs);
2952 return hr;
2955 static HRESULT WINAPI
2956 Thunk_IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2957 D3DRENDERSTATETYPE RenderStateType,
2958 DWORD Value)
2960 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2961 TRACE_(ddraw_thunk)("(%p)->(%08x,%d) thunking to IDirect3DDevice3 interface.\n", This, RenderStateType, Value);
2962 return IDirect3DDevice3_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice3), RenderStateType, Value);
2965 /*****************************************************************************
2966 * Direct3DDevice3::SetLightState
2968 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2969 * light states are forwarded to Direct3DDevice7 render states
2971 * Version 2 and 3
2973 * Params:
2974 * LightStateType: The light state to change
2975 * Value: The value to assign to that light state
2977 * Returns:
2978 * D3D_OK on success
2979 * DDERR_INVALIDPARAMS if the parameters were incorrect
2980 * Also check IDirect3DDevice7::SetRenderState
2982 *****************************************************************************/
2983 static HRESULT WINAPI
2984 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
2985 D3DLIGHTSTATETYPE LightStateType,
2986 DWORD Value)
2988 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2989 HRESULT hr;
2991 TRACE("(%p)->(%08x,%08x)\n", This, LightStateType, Value);
2993 if (!LightStateType && (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2995 TRACE("Unexpected Light State Type\n");
2996 return DDERR_INVALIDPARAMS;
2999 EnterCriticalSection(&ddraw_cs);
3000 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3002 IDirect3DMaterialImpl *mat;
3004 if(Value == 0) mat = NULL;
3005 else if(Value > This->numHandles)
3007 ERR("Material handle out of range(%d)\n", Value);
3008 LeaveCriticalSection(&ddraw_cs);
3009 return DDERR_INVALIDPARAMS;
3011 else if(This->Handles[Value - 1].type != DDrawHandle_Material)
3013 ERR("Invalid handle %d\n", Value);
3014 LeaveCriticalSection(&ddraw_cs);
3015 return DDERR_INVALIDPARAMS;
3017 else
3019 mat = (IDirect3DMaterialImpl *) This->Handles[Value - 1].ptr;
3022 if (mat != NULL)
3024 TRACE(" activating material %p.\n", mat);
3025 mat->activate(mat);
3027 else
3029 FIXME(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
3031 This->material = Value;
3033 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3035 switch (Value)
3037 case D3DCOLOR_MONO:
3038 ERR("DDCOLOR_MONO should not happen!\n");
3039 break;
3040 case D3DCOLOR_RGB:
3041 /* We are already in this mode */
3042 TRACE("Setting color model to RGB (no-op).\n");
3043 break;
3044 default:
3045 ERR("Unknown color model!\n");
3046 LeaveCriticalSection(&ddraw_cs);
3047 return DDERR_INVALIDPARAMS;
3050 else
3052 D3DRENDERSTATETYPE rs;
3053 switch (LightStateType)
3055 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3056 rs = D3DRENDERSTATE_AMBIENT;
3057 break;
3058 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3059 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3060 break;
3061 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3062 rs = D3DRENDERSTATE_FOGSTART;
3063 break;
3064 case D3DLIGHTSTATE_FOGEND: /* 6 */
3065 rs = D3DRENDERSTATE_FOGEND;
3066 break;
3067 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3068 rs = D3DRENDERSTATE_FOGDENSITY;
3069 break;
3070 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3071 rs = D3DRENDERSTATE_COLORVERTEX;
3072 break;
3073 default:
3074 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3075 LeaveCriticalSection(&ddraw_cs);
3076 return DDERR_INVALIDPARAMS;
3079 hr = IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
3081 Value);
3082 LeaveCriticalSection(&ddraw_cs);
3083 return hr;
3086 LeaveCriticalSection(&ddraw_cs);
3087 return D3D_OK;
3090 static HRESULT WINAPI
3091 Thunk_IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3092 D3DLIGHTSTATETYPE LightStateType,
3093 DWORD Value)
3095 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3096 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x) thunking to IDirect3DDevice3 interface.\n", This, LightStateType, Value);
3097 return IDirect3DDevice3_SetLightState(ICOM_INTERFACE(This, IDirect3DDevice3),
3098 LightStateType,
3099 Value);
3102 /*****************************************************************************
3103 * IDirect3DDevice3::GetLightState
3105 * Returns the current setting of a light state. The state is read from
3106 * the Direct3DDevice7 render state.
3108 * Version 2 and 3
3110 * Params:
3111 * LightStateType: The light state to return
3112 * Value: The address to store the light state setting at
3114 * Returns:
3115 * D3D_OK on success
3116 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3117 * Also see IDirect3DDevice7::GetRenderState
3119 *****************************************************************************/
3120 static HRESULT WINAPI
3121 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3122 D3DLIGHTSTATETYPE LightStateType,
3123 DWORD *Value)
3125 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3126 HRESULT hr;
3128 TRACE("(%p)->(%08x,%p)\n", This, LightStateType, Value);
3130 if (!LightStateType && (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3132 TRACE("Unexpected Light State Type\n");
3133 return DDERR_INVALIDPARAMS;
3136 if(!Value)
3137 return DDERR_INVALIDPARAMS;
3139 EnterCriticalSection(&ddraw_cs);
3140 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3142 *Value = This->material;
3144 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3146 *Value = D3DCOLOR_RGB;
3148 else
3150 D3DRENDERSTATETYPE rs;
3151 switch (LightStateType)
3153 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3154 rs = D3DRENDERSTATE_AMBIENT;
3155 break;
3156 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3157 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3158 break;
3159 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3160 rs = D3DRENDERSTATE_FOGSTART;
3161 break;
3162 case D3DLIGHTSTATE_FOGEND: /* 6 */
3163 rs = D3DRENDERSTATE_FOGEND;
3164 break;
3165 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3166 rs = D3DRENDERSTATE_FOGDENSITY;
3167 break;
3168 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3169 rs = D3DRENDERSTATE_COLORVERTEX;
3170 break;
3171 default:
3172 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3173 LeaveCriticalSection(&ddraw_cs);
3174 return DDERR_INVALIDPARAMS;
3177 hr = IDirect3DDevice7_GetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
3179 Value);
3180 LeaveCriticalSection(&ddraw_cs);
3181 return hr;
3184 LeaveCriticalSection(&ddraw_cs);
3185 return D3D_OK;
3188 static HRESULT WINAPI
3189 Thunk_IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3190 D3DLIGHTSTATETYPE LightStateType,
3191 DWORD *Value)
3193 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3194 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice3 interface.\n", This, LightStateType, Value);
3195 return IDirect3DDevice3_GetLightState(ICOM_INTERFACE(This, IDirect3DDevice3),
3196 LightStateType,
3197 Value);
3200 /*****************************************************************************
3201 * IDirect3DDevice7::SetTransform
3203 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3204 * in include/d3dtypes.h.
3205 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3206 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3207 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3209 * Version 2, 3 and 7
3211 * Params:
3212 * TransformStateType: transform state to set
3213 * Matrix: Matrix to assign to the state
3215 * Returns:
3216 * D3D_OK on success
3217 * DDERR_INVALIDPARAMS if Matrix == NULL
3218 * For details see IWineD3DDevice::SetTransform
3220 *****************************************************************************/
3221 static HRESULT
3222 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3223 D3DTRANSFORMSTATETYPE TransformStateType,
3224 D3DMATRIX *Matrix)
3226 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3227 D3DTRANSFORMSTATETYPE type = TransformStateType;
3228 HRESULT hr;
3229 TRACE("(%p)->(%08x,%p): Relay\n", This, TransformStateType, Matrix);
3231 switch(TransformStateType)
3233 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3234 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3235 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3236 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3237 default: type = TransformStateType;
3240 if(!Matrix)
3241 return DDERR_INVALIDPARAMS;
3243 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3244 EnterCriticalSection(&ddraw_cs);
3245 hr = IWineD3DDevice_SetTransform(This->wineD3DDevice,
3246 type,
3247 (WINED3DMATRIX*) Matrix);
3248 LeaveCriticalSection(&ddraw_cs);
3249 return hr;
3252 static HRESULT WINAPI
3253 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3254 D3DTRANSFORMSTATETYPE TransformStateType,
3255 D3DMATRIX *Matrix)
3257 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3260 static HRESULT WINAPI
3261 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3262 D3DTRANSFORMSTATETYPE TransformStateType,
3263 D3DMATRIX *Matrix)
3265 HRESULT hr;
3266 WORD old_fpucw;
3268 old_fpucw = d3d_fpu_setup();
3269 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3270 set_fpu_control_word(old_fpucw);
3272 return hr;
3275 static HRESULT WINAPI
3276 Thunk_IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3277 D3DTRANSFORMSTATETYPE TransformStateType,
3278 D3DMATRIX *D3DMatrix)
3280 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3281 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3282 return IDirect3DDevice7_SetTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
3283 TransformStateType,
3284 D3DMatrix);
3287 static HRESULT WINAPI
3288 Thunk_IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3289 D3DTRANSFORMSTATETYPE TransformStateType,
3290 D3DMATRIX *D3DMatrix)
3292 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3293 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3294 return IDirect3DDevice7_SetTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
3295 TransformStateType,
3296 D3DMatrix);
3299 /*****************************************************************************
3300 * IDirect3DDevice7::GetTransform
3302 * Returns the matrix assigned to a transform state
3303 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3304 * SetTransform
3306 * Params:
3307 * TransformStateType: State to read the matrix from
3308 * Matrix: Address to store the matrix at
3310 * Returns:
3311 * D3D_OK on success
3312 * DDERR_INVALIDPARAMS if Matrix == NULL
3313 * For details, see IWineD3DDevice::GetTransform
3315 *****************************************************************************/
3316 static HRESULT
3317 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3318 D3DTRANSFORMSTATETYPE TransformStateType,
3319 D3DMATRIX *Matrix)
3321 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3322 D3DTRANSFORMSTATETYPE type = TransformStateType;
3323 HRESULT hr;
3324 TRACE("(%p)->(%08x,%p): Relay\n", This, TransformStateType, Matrix);
3326 switch(TransformStateType)
3328 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3329 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3330 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3331 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3332 default: type = TransformStateType;
3335 if(!Matrix)
3336 return DDERR_INVALIDPARAMS;
3338 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3339 EnterCriticalSection(&ddraw_cs);
3340 hr = IWineD3DDevice_GetTransform(This->wineD3DDevice, type, (WINED3DMATRIX*) Matrix);
3341 LeaveCriticalSection(&ddraw_cs);
3342 return hr;
3345 static HRESULT WINAPI
3346 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3347 D3DTRANSFORMSTATETYPE TransformStateType,
3348 D3DMATRIX *Matrix)
3350 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3353 static HRESULT WINAPI
3354 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3355 D3DTRANSFORMSTATETYPE TransformStateType,
3356 D3DMATRIX *Matrix)
3358 HRESULT hr;
3359 WORD old_fpucw;
3361 old_fpucw = d3d_fpu_setup();
3362 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3363 set_fpu_control_word(old_fpucw);
3365 return hr;
3368 static HRESULT WINAPI
3369 Thunk_IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3370 D3DTRANSFORMSTATETYPE TransformStateType,
3371 D3DMATRIX *D3DMatrix)
3373 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3374 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3375 return IDirect3DDevice7_GetTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
3376 TransformStateType,
3377 D3DMatrix);
3380 static HRESULT WINAPI
3381 Thunk_IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3382 D3DTRANSFORMSTATETYPE TransformStateType,
3383 D3DMATRIX *D3DMatrix)
3385 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3386 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3387 return IDirect3DDevice7_GetTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
3388 TransformStateType,
3389 D3DMatrix);
3392 /*****************************************************************************
3393 * IDirect3DDevice7::MultiplyTransform
3395 * Multiplies the already-set transform matrix of a transform state
3396 * with another matrix. For the world matrix, see SetTransform
3398 * Version 2, 3 and 7
3400 * Params:
3401 * TransformStateType: Transform state to multiply
3402 * D3DMatrix Matrix to multiply with.
3404 * Returns
3405 * D3D_OK on success
3406 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3407 * For details, see IWineD3DDevice::MultiplyTransform
3409 *****************************************************************************/
3410 static HRESULT
3411 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3412 D3DTRANSFORMSTATETYPE TransformStateType,
3413 D3DMATRIX *D3DMatrix)
3415 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3416 HRESULT hr;
3417 D3DTRANSFORMSTATETYPE type;
3418 TRACE("(%p)->(%08x,%p): Relay\n", This, TransformStateType, D3DMatrix);
3420 switch(TransformStateType)
3422 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3423 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3424 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3425 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3426 default: type = TransformStateType;
3429 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3430 EnterCriticalSection(&ddraw_cs);
3431 hr = IWineD3DDevice_MultiplyTransform(This->wineD3DDevice,
3432 type,
3433 (WINED3DMATRIX*) D3DMatrix);
3434 LeaveCriticalSection(&ddraw_cs);
3435 return hr;
3438 static HRESULT WINAPI
3439 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3440 D3DTRANSFORMSTATETYPE TransformStateType,
3441 D3DMATRIX *D3DMatrix)
3443 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3446 static HRESULT WINAPI
3447 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3448 D3DTRANSFORMSTATETYPE TransformStateType,
3449 D3DMATRIX *D3DMatrix)
3451 HRESULT hr;
3452 WORD old_fpucw;
3454 old_fpucw = d3d_fpu_setup();
3455 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3456 set_fpu_control_word(old_fpucw);
3458 return hr;
3461 static HRESULT WINAPI
3462 Thunk_IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3463 D3DTRANSFORMSTATETYPE TransformStateType,
3464 D3DMATRIX *D3DMatrix)
3466 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3467 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3468 return IDirect3DDevice7_MultiplyTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
3469 TransformStateType,
3470 D3DMatrix);
3473 static HRESULT WINAPI
3474 Thunk_IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3475 D3DTRANSFORMSTATETYPE TransformStateType,
3476 D3DMATRIX *D3DMatrix)
3478 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3479 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3480 return IDirect3DDevice7_MultiplyTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
3481 TransformStateType,
3482 D3DMatrix);
3485 /*****************************************************************************
3486 * IDirect3DDevice7::DrawPrimitive
3488 * Draws primitives based on vertices in an application-provided pointer
3490 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3491 * an FVF format for D3D7
3493 * Params:
3494 * PrimitiveType: The type of the primitives to draw
3495 * Vertex type: Flexible vertex format vertex description
3496 * Vertices: Pointer to the vertex array
3497 * VertexCount: The number of vertices to draw
3498 * Flags: As usual a few flags
3500 * Returns:
3501 * D3D_OK on success
3502 * DDERR_INVALIDPARAMS if Vertices is NULL
3503 * For details, see IWineD3DDevice::DrawPrimitiveUP
3505 *****************************************************************************/
3506 static HRESULT
3507 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3508 D3DPRIMITIVETYPE PrimitiveType,
3509 DWORD VertexType,
3510 void *Vertices,
3511 DWORD VertexCount,
3512 DWORD Flags)
3514 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3515 UINT PrimitiveCount, stride;
3516 HRESULT hr;
3517 TRACE("(%p)->(%08x,%08x,%p,%08x,%08x): Relay!\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3519 if(!Vertices)
3520 return DDERR_INVALIDPARAMS;
3522 /* Get the vertex count */
3523 switch(PrimitiveType)
3525 case D3DPT_POINTLIST:
3526 PrimitiveCount = VertexCount;
3527 break;
3529 case D3DPT_LINELIST:
3530 PrimitiveCount = VertexCount / 2;
3531 break;
3533 case D3DPT_LINESTRIP:
3534 PrimitiveCount = VertexCount - 1;
3535 break;
3537 case D3DPT_TRIANGLELIST:
3538 PrimitiveCount = VertexCount / 3;
3539 break;
3541 case D3DPT_TRIANGLESTRIP:
3542 PrimitiveCount = VertexCount - 2;
3543 break;
3545 case D3DPT_TRIANGLEFAN:
3546 PrimitiveCount = VertexCount - 2;
3547 break;
3549 default:
3550 return DDERR_INVALIDPARAMS;
3553 /* Get the stride */
3554 stride = get_flexible_vertex_size(VertexType);
3556 /* Set the FVF */
3557 EnterCriticalSection(&ddraw_cs);
3558 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
3559 IDirectDrawImpl_FindDecl(This->ddraw, VertexType));
3560 if(hr != D3D_OK)
3562 LeaveCriticalSection(&ddraw_cs);
3563 return hr;
3566 /* This method translates to the user pointer draw of WineD3D */
3567 hr = IWineD3DDevice_DrawPrimitiveUP(This->wineD3DDevice,
3568 PrimitiveType,
3569 PrimitiveCount,
3570 Vertices,
3571 stride);
3572 LeaveCriticalSection(&ddraw_cs);
3573 return hr;
3576 static HRESULT WINAPI
3577 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3578 D3DPRIMITIVETYPE PrimitiveType,
3579 DWORD VertexType,
3580 void *Vertices,
3581 DWORD VertexCount,
3582 DWORD Flags)
3584 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3587 static HRESULT WINAPI
3588 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3589 D3DPRIMITIVETYPE PrimitiveType,
3590 DWORD VertexType,
3591 void *Vertices,
3592 DWORD VertexCount,
3593 DWORD Flags)
3595 HRESULT hr;
3596 WORD old_fpucw;
3598 old_fpucw = d3d_fpu_setup();
3599 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3600 set_fpu_control_word(old_fpucw);
3602 return hr;
3605 static HRESULT WINAPI
3606 Thunk_IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3607 D3DPRIMITIVETYPE PrimitiveType,
3608 DWORD VertexType,
3609 void *Vertices,
3610 DWORD VertexCount,
3611 DWORD Flags)
3613 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3614 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3615 return IDirect3DDevice7_DrawPrimitive(ICOM_INTERFACE(This, IDirect3DDevice7),
3616 PrimitiveType,
3617 VertexType,
3618 Vertices,
3619 VertexCount,
3620 Flags);
3623 static HRESULT WINAPI
3624 Thunk_IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3625 D3DPRIMITIVETYPE PrimitiveType,
3626 D3DVERTEXTYPE VertexType,
3627 void *Vertices,
3628 DWORD VertexCount,
3629 DWORD Flags)
3631 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3632 DWORD FVF;
3633 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3635 switch(VertexType)
3637 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3638 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3639 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3640 default:
3641 ERR("Unexpected vertex type %d\n", VertexType);
3642 return DDERR_INVALIDPARAMS; /* Should never happen */
3645 return IDirect3DDevice7_DrawPrimitive(ICOM_INTERFACE(This, IDirect3DDevice7),
3646 PrimitiveType,
3647 FVF,
3648 Vertices,
3649 VertexCount,
3650 Flags);
3653 /*****************************************************************************
3654 * IDirect3DDevice7::DrawIndexedPrimitive
3656 * Draws vertices from an application-provided pointer, based on the index
3657 * numbers in a WORD array.
3659 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3660 * an FVF format for D3D7
3662 * Params:
3663 * PrimitiveType: The primitive type to draw
3664 * VertexType: The FVF vertex description
3665 * Vertices: Pointer to the vertex array
3666 * VertexCount: ?
3667 * Indices: Pointer to the index array
3668 * IndexCount: Number of indices = Number of vertices to draw
3669 * Flags: As usual, some flags
3671 * Returns:
3672 * D3D_OK on success
3673 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3674 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3676 *****************************************************************************/
3677 static HRESULT
3678 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3679 D3DPRIMITIVETYPE PrimitiveType,
3680 DWORD VertexType,
3681 void *Vertices,
3682 DWORD VertexCount,
3683 WORD *Indices,
3684 DWORD IndexCount,
3685 DWORD Flags)
3687 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3688 UINT PrimitiveCount = 0;
3689 HRESULT hr;
3690 TRACE("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x): Relay!\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3692 /* Get the primitive number */
3693 switch(PrimitiveType)
3695 case D3DPT_POINTLIST:
3696 PrimitiveCount = IndexCount;
3697 break;
3699 case D3DPT_LINELIST:
3700 PrimitiveCount = IndexCount / 2;
3701 break;
3703 case D3DPT_LINESTRIP:
3704 PrimitiveCount = IndexCount - 1;
3705 break;
3707 case D3DPT_TRIANGLELIST:
3708 PrimitiveCount = IndexCount / 3;
3709 break;
3711 case D3DPT_TRIANGLESTRIP:
3712 PrimitiveCount = IndexCount - 2;
3713 break;
3715 case D3DPT_TRIANGLEFAN:
3716 PrimitiveCount = IndexCount - 2;
3717 break;
3719 default:
3720 return DDERR_INVALIDPARAMS;
3723 /* Set the D3DDevice's FVF */
3724 EnterCriticalSection(&ddraw_cs);
3725 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
3726 IDirectDrawImpl_FindDecl(This->ddraw, VertexType));
3727 if(FAILED(hr))
3729 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3730 LeaveCriticalSection(&ddraw_cs);
3731 return hr;
3734 hr = IWineD3DDevice_DrawIndexedPrimitiveUP(This->wineD3DDevice,
3735 PrimitiveType,
3736 0 /* MinVertexIndex */,
3737 VertexCount /* UINT NumVertexIndex */,
3738 PrimitiveCount,
3739 Indices,
3740 WINED3DFMT_INDEX16,
3741 Vertices,
3742 get_flexible_vertex_size(VertexType));
3743 LeaveCriticalSection(&ddraw_cs);
3744 return hr;
3747 static HRESULT WINAPI
3748 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3749 D3DPRIMITIVETYPE PrimitiveType,
3750 DWORD VertexType,
3751 void *Vertices,
3752 DWORD VertexCount,
3753 WORD *Indices,
3754 DWORD IndexCount,
3755 DWORD Flags)
3757 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3760 static HRESULT WINAPI
3761 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3762 D3DPRIMITIVETYPE PrimitiveType,
3763 DWORD VertexType,
3764 void *Vertices,
3765 DWORD VertexCount,
3766 WORD *Indices,
3767 DWORD IndexCount,
3768 DWORD Flags)
3770 HRESULT hr;
3771 WORD old_fpucw;
3773 old_fpucw = d3d_fpu_setup();
3774 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3775 set_fpu_control_word(old_fpucw);
3777 return hr;
3780 static HRESULT WINAPI
3781 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3782 D3DPRIMITIVETYPE PrimitiveType,
3783 DWORD VertexType,
3784 void *Vertices,
3785 DWORD VertexCount,
3786 WORD *Indices,
3787 DWORD IndexCount,
3788 DWORD Flags)
3790 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3791 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3792 return IDirect3DDevice7_DrawIndexedPrimitive(ICOM_INTERFACE(This, IDirect3DDevice7),
3793 PrimitiveType,
3794 VertexType,
3795 Vertices,
3796 VertexCount,
3797 Indices,
3798 IndexCount,
3799 Flags);
3802 static HRESULT WINAPI
3803 Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3804 D3DPRIMITIVETYPE PrimitiveType,
3805 D3DVERTEXTYPE VertexType,
3806 void *Vertices,
3807 DWORD VertexCount,
3808 WORD *Indices,
3809 DWORD IndexCount,
3810 DWORD Flags)
3812 DWORD FVF;
3813 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3814 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3816 switch(VertexType)
3818 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3819 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3820 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3821 default:
3822 ERR("Unexpected vertex type %d\n", VertexType);
3823 return DDERR_INVALIDPARAMS; /* Should never happen */
3826 return IDirect3DDevice7_DrawIndexedPrimitive(ICOM_INTERFACE(This, IDirect3DDevice7),
3827 PrimitiveType,
3828 FVF,
3829 Vertices,
3830 VertexCount,
3831 Indices,
3832 IndexCount,
3833 Flags);
3836 /*****************************************************************************
3837 * IDirect3DDevice7::SetClipStatus
3839 * Sets the clip status. This defines things as clipping conditions and
3840 * the extents of the clipping region.
3842 * Version 2, 3 and 7
3844 * Params:
3845 * ClipStatus:
3847 * Returns:
3848 * D3D_OK because it's a stub
3849 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3851 *****************************************************************************/
3852 static HRESULT WINAPI
3853 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3854 D3DCLIPSTATUS *ClipStatus)
3856 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3857 FIXME("(%p)->(%p): Stub!\n", This, ClipStatus);
3859 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3860 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3862 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3863 return D3D_OK;
3866 static HRESULT WINAPI
3867 Thunk_IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3868 D3DCLIPSTATUS *ClipStatus)
3870 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3871 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3872 return IDirect3DDevice7_SetClipStatus(ICOM_INTERFACE(This, IDirect3DDevice7),
3873 ClipStatus);
3876 static HRESULT WINAPI
3877 Thunk_IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3878 D3DCLIPSTATUS *ClipStatus)
3880 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3881 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3882 return IDirect3DDevice7_SetClipStatus(ICOM_INTERFACE(This, IDirect3DDevice7),
3883 ClipStatus);
3886 /*****************************************************************************
3887 * IDirect3DDevice7::GetClipStatus
3889 * Returns the clip status
3891 * Params:
3892 * ClipStatus: Address to write the clip status to
3894 * Returns:
3895 * D3D_OK because it's a stub
3897 *****************************************************************************/
3898 static HRESULT WINAPI
3899 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3900 D3DCLIPSTATUS *ClipStatus)
3902 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3903 FIXME("(%p)->(%p): Stub!\n", This, ClipStatus);
3905 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3906 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3907 return D3D_OK;
3910 static HRESULT WINAPI
3911 Thunk_IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3912 D3DCLIPSTATUS *ClipStatus)
3914 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3915 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3916 return IDirect3DDevice7_GetClipStatus(ICOM_INTERFACE(This, IDirect3DDevice7),
3917 ClipStatus);
3920 static HRESULT WINAPI
3921 Thunk_IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3922 D3DCLIPSTATUS *ClipStatus)
3924 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3925 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3926 return IDirect3DDevice7_GetClipStatus(ICOM_INTERFACE(This, IDirect3DDevice7),
3927 ClipStatus);
3930 /*****************************************************************************
3931 * IDirect3DDevice::DrawPrimitiveStrided
3933 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3935 * Version 3 and 7
3937 * Params:
3938 * PrimitiveType: The primitive type to draw
3939 * VertexType: The FVF description of the vertices to draw (for the stride??)
3940 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3941 * the vertex data locations
3942 * VertexCount: The number of vertices to draw
3943 * Flags: Some flags
3945 * Returns:
3946 * D3D_OK, because it's a stub
3947 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3948 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3950 *****************************************************************************/
3951 static HRESULT
3952 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3953 D3DPRIMITIVETYPE PrimitiveType,
3954 DWORD VertexType,
3955 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3956 DWORD VertexCount,
3957 DWORD Flags)
3959 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3960 WineDirect3DVertexStridedData WineD3DStrided;
3961 int i;
3962 UINT PrimitiveCount;
3963 HRESULT hr;
3965 TRACE("(%p)->(%08x,%08x,%p,%08x,%08x): stub!\n", This, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3967 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3968 /* Get the strided data right. the wined3d structure is a bit bigger
3969 * Watch out: The contents of the strided data are determined by the fvf,
3970 * not by the members set in D3DDrawPrimStrideData. So it's valid
3971 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3972 * not set in the fvf.
3974 if(VertexType & D3DFVF_POSITION_MASK)
3976 WineD3DStrided.u.s.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3977 WineD3DStrided.u.s.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3978 WineD3DStrided.u.s.position.dwType = WINED3DDECLTYPE_FLOAT3;
3979 if (VertexType & D3DFVF_XYZRHW)
3981 WineD3DStrided.u.s.position.dwType = WINED3DDECLTYPE_FLOAT4;
3982 WineD3DStrided.u.s.position_transformed = TRUE;
3983 } else
3984 WineD3DStrided.u.s.position_transformed = FALSE;
3987 if(VertexType & D3DFVF_NORMAL)
3989 WineD3DStrided.u.s.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3990 WineD3DStrided.u.s.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3991 WineD3DStrided.u.s.normal.dwType = WINED3DDECLTYPE_FLOAT3;
3994 if(VertexType & D3DFVF_DIFFUSE)
3996 WineD3DStrided.u.s.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3997 WineD3DStrided.u.s.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3998 WineD3DStrided.u.s.diffuse.dwType = WINED3DDECLTYPE_D3DCOLOR;
4001 if(VertexType & D3DFVF_SPECULAR)
4003 WineD3DStrided.u.s.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
4004 WineD3DStrided.u.s.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
4005 WineD3DStrided.u.s.specular.dwType = WINED3DDECLTYPE_D3DCOLOR;
4008 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
4010 WineD3DStrided.u.s.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4011 WineD3DStrided.u.s.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4012 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
4014 case 1: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT1; break;
4015 case 2: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT2; break;
4016 case 3: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT3; break;
4017 case 4: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT4; break;
4018 default: ERR("Unexpected texture coordinate size %d\n",
4019 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4023 /* Get the primitive count */
4024 switch(PrimitiveType)
4026 case D3DPT_POINTLIST:
4027 PrimitiveCount = VertexCount;
4028 break;
4030 case D3DPT_LINELIST:
4031 PrimitiveCount = VertexCount / 2;
4032 break;
4034 case D3DPT_LINESTRIP:
4035 PrimitiveCount = VertexCount - 1;
4036 break;
4038 case D3DPT_TRIANGLELIST:
4039 PrimitiveCount = VertexCount / 3;
4040 break;
4042 case D3DPT_TRIANGLESTRIP:
4043 PrimitiveCount = VertexCount - 2;
4044 break;
4046 case D3DPT_TRIANGLEFAN:
4047 PrimitiveCount = VertexCount - 2;
4048 break;
4050 default: return DDERR_INVALIDPARAMS;
4053 /* WineD3D doesn't need the FVF here */
4054 EnterCriticalSection(&ddraw_cs);
4055 hr = IWineD3DDevice_DrawPrimitiveStrided(This->wineD3DDevice,
4056 PrimitiveType,
4057 PrimitiveCount,
4058 &WineD3DStrided);
4059 LeaveCriticalSection(&ddraw_cs);
4060 return hr;
4063 static HRESULT WINAPI
4064 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4065 D3DPRIMITIVETYPE PrimitiveType,
4066 DWORD VertexType,
4067 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4068 DWORD VertexCount,
4069 DWORD Flags)
4071 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4074 static HRESULT WINAPI
4075 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4076 D3DPRIMITIVETYPE PrimitiveType,
4077 DWORD VertexType,
4078 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4079 DWORD VertexCount,
4080 DWORD Flags)
4082 HRESULT hr;
4083 WORD old_fpucw;
4085 old_fpucw = d3d_fpu_setup();
4086 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4087 set_fpu_control_word(old_fpucw);
4089 return hr;
4092 static HRESULT WINAPI
4093 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
4094 D3DPRIMITIVETYPE PrimitiveType,
4095 DWORD VertexType,
4096 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4097 DWORD VertexCount,
4098 DWORD Flags)
4100 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4101 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4102 return IDirect3DDevice7_DrawPrimitiveStrided(ICOM_INTERFACE(This, IDirect3DDevice7),
4103 PrimitiveType,
4104 VertexType,
4105 D3DDrawPrimStrideData,
4106 VertexCount,
4107 Flags);
4110 /*****************************************************************************
4111 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
4113 * Draws primitives specified by strided data locations based on indices
4115 * Version 3 and 7
4117 * Params:
4118 * PrimitiveType:
4120 * Returns:
4121 * D3D_OK, because it's a stub
4122 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
4123 * (DDERR_INVALIDPARAMS if Indices is NULL)
4124 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
4126 *****************************************************************************/
4127 static HRESULT
4128 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
4129 D3DPRIMITIVETYPE PrimitiveType,
4130 DWORD VertexType,
4131 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4132 DWORD VertexCount,
4133 WORD *Indices,
4134 DWORD IndexCount,
4135 DWORD Flags)
4137 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4138 WineDirect3DVertexStridedData WineD3DStrided;
4139 int i;
4140 UINT PrimitiveCount;
4141 HRESULT hr;
4143 TRACE("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x)\n", This, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4145 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
4146 /* Get the strided data right. the wined3d structure is a bit bigger
4147 * Watch out: The contents of the strided data are determined by the fvf,
4148 * not by the members set in D3DDrawPrimStrideData. So it's valid
4149 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
4150 * not set in the fvf.
4152 if(VertexType & D3DFVF_POSITION_MASK)
4154 WineD3DStrided.u.s.position.lpData = D3DDrawPrimStrideData->position.lpvData;
4155 WineD3DStrided.u.s.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
4156 WineD3DStrided.u.s.position.dwType = WINED3DDECLTYPE_FLOAT3;
4157 if (VertexType & D3DFVF_XYZRHW)
4159 WineD3DStrided.u.s.position.dwType = WINED3DDECLTYPE_FLOAT4;
4160 WineD3DStrided.u.s.position_transformed = TRUE;
4161 } else
4162 WineD3DStrided.u.s.position_transformed = FALSE;
4165 if(VertexType & D3DFVF_NORMAL)
4167 WineD3DStrided.u.s.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
4168 WineD3DStrided.u.s.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
4169 WineD3DStrided.u.s.normal.dwType = WINED3DDECLTYPE_FLOAT3;
4172 if(VertexType & D3DFVF_DIFFUSE)
4174 WineD3DStrided.u.s.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
4175 WineD3DStrided.u.s.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
4176 WineD3DStrided.u.s.diffuse.dwType = WINED3DDECLTYPE_D3DCOLOR;
4179 if(VertexType & D3DFVF_SPECULAR)
4181 WineD3DStrided.u.s.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
4182 WineD3DStrided.u.s.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
4183 WineD3DStrided.u.s.specular.dwType = WINED3DDECLTYPE_D3DCOLOR;
4186 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
4188 WineD3DStrided.u.s.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4189 WineD3DStrided.u.s.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4190 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
4192 case 1: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT1; break;
4193 case 2: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT2; break;
4194 case 3: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT3; break;
4195 case 4: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT4; break;
4196 default: ERR("Unexpected texture coordinate size %d\n",
4197 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4201 /* Get the primitive count */
4202 switch(PrimitiveType)
4204 case D3DPT_POINTLIST:
4205 PrimitiveCount = IndexCount;
4206 break;
4208 case D3DPT_LINELIST:
4209 PrimitiveCount = IndexCount / 2;
4210 break;
4212 case D3DPT_LINESTRIP:
4213 PrimitiveCount = IndexCount - 1;
4214 break;
4216 case D3DPT_TRIANGLELIST:
4217 PrimitiveCount = IndexCount / 3;
4218 break;
4220 case D3DPT_TRIANGLESTRIP:
4221 PrimitiveCount = IndexCount - 2;
4222 break;
4224 case D3DPT_TRIANGLEFAN:
4225 PrimitiveCount = IndexCount - 2;
4226 break;
4228 default: return DDERR_INVALIDPARAMS;
4231 /* WineD3D doesn't need the FVF here */
4232 EnterCriticalSection(&ddraw_cs);
4233 hr = IWineD3DDevice_DrawIndexedPrimitiveStrided(This->wineD3DDevice,
4234 PrimitiveType,
4235 PrimitiveCount,
4236 &WineD3DStrided,
4237 VertexCount,
4238 Indices,
4239 WINED3DFMT_INDEX16);
4240 LeaveCriticalSection(&ddraw_cs);
4241 return hr;
4244 static HRESULT WINAPI
4245 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4246 D3DPRIMITIVETYPE PrimitiveType,
4247 DWORD VertexType,
4248 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4249 DWORD VertexCount,
4250 WORD *Indices,
4251 DWORD IndexCount,
4252 DWORD Flags)
4254 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4257 static HRESULT WINAPI
4258 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4259 D3DPRIMITIVETYPE PrimitiveType,
4260 DWORD VertexType,
4261 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4262 DWORD VertexCount,
4263 WORD *Indices,
4264 DWORD IndexCount,
4265 DWORD Flags)
4267 HRESULT hr;
4268 WORD old_fpucw;
4270 old_fpucw = d3d_fpu_setup();
4271 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4272 set_fpu_control_word(old_fpucw);
4274 return hr;
4277 static HRESULT WINAPI
4278 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4279 D3DPRIMITIVETYPE PrimitiveType,
4280 DWORD VertexType,
4281 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4282 DWORD VertexCount,
4283 WORD *Indices,
4284 DWORD IndexCount,
4285 DWORD Flags)
4287 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4288 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4289 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(ICOM_INTERFACE(This, IDirect3DDevice7),
4290 PrimitiveType,
4291 VertexType,
4292 D3DDrawPrimStrideData,
4293 VertexCount,
4294 Indices,
4295 IndexCount,
4296 Flags);
4299 /*****************************************************************************
4300 * IDirect3DDevice7::DrawPrimitiveVB
4302 * Draws primitives from a vertex buffer to the screen.
4304 * Version 3 and 7
4306 * Params:
4307 * PrimitiveType: Type of primitive to be rendered.
4308 * D3DVertexBuf: Source Vertex Buffer
4309 * StartVertex: Index of the first vertex from the buffer to be rendered
4310 * NumVertices: Number of vertices to be rendered
4311 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4313 * Return values
4314 * D3D_OK on success
4315 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4317 *****************************************************************************/
4318 static HRESULT
4319 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4320 D3DPRIMITIVETYPE PrimitiveType,
4321 IDirect3DVertexBuffer7 *D3DVertexBuf,
4322 DWORD StartVertex,
4323 DWORD NumVertices,
4324 DWORD Flags)
4326 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4327 IDirect3DVertexBufferImpl *vb = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, D3DVertexBuf);
4328 UINT PrimitiveCount;
4329 HRESULT hr;
4330 DWORD stride;
4331 WINED3DVERTEXBUFFER_DESC Desc;
4333 TRACE("(%p)->(%08x,%p,%08x,%08x,%08x)\n", This, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4335 /* Sanity checks */
4336 if(!vb)
4338 ERR("(%p) No Vertex buffer specified\n", This);
4339 return DDERR_INVALIDPARAMS;
4342 /* Get the primitive count */
4343 switch(PrimitiveType)
4345 case D3DPT_POINTLIST:
4346 PrimitiveCount = NumVertices;
4347 break;
4349 case D3DPT_LINELIST:
4350 PrimitiveCount = NumVertices / 2;
4351 break;
4353 case D3DPT_LINESTRIP:
4354 PrimitiveCount = NumVertices - 1;
4355 break;
4357 case D3DPT_TRIANGLELIST:
4358 PrimitiveCount = NumVertices / 3;
4359 break;
4361 case D3DPT_TRIANGLESTRIP:
4362 PrimitiveCount = NumVertices - 2;
4363 break;
4365 case D3DPT_TRIANGLEFAN:
4366 PrimitiveCount = NumVertices - 2;
4367 break;
4369 default:
4370 return DDERR_INVALIDPARAMS;
4373 /* Get the FVF of the vertex buffer, and its stride */
4374 EnterCriticalSection(&ddraw_cs);
4375 hr = IWineD3DVertexBuffer_GetDesc(vb->wineD3DVertexBuffer,
4376 &Desc);
4377 if(hr != D3D_OK)
4379 ERR("(%p) IWineD3DVertexBuffer::GetDesc failed with hr = %08x\n", This, hr);
4380 LeaveCriticalSection(&ddraw_cs);
4381 return hr;
4383 stride = get_flexible_vertex_size(Desc.FVF);
4385 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4386 vb->wineD3DVertexDeclaration);
4387 if(FAILED(hr))
4389 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4390 LeaveCriticalSection(&ddraw_cs);
4391 return hr;
4394 /* Set the vertex stream source */
4395 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4396 0 /* StreamNumber */,
4397 vb->wineD3DVertexBuffer,
4398 0 /* StartVertex - we pass this to DrawPrimitive */,
4399 stride);
4400 if(hr != D3D_OK)
4402 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4403 LeaveCriticalSection(&ddraw_cs);
4404 return hr;
4407 /* Now draw the primitives */
4408 hr = IWineD3DDevice_DrawPrimitive(This->wineD3DDevice,
4409 PrimitiveType,
4410 StartVertex,
4411 PrimitiveCount);
4412 LeaveCriticalSection(&ddraw_cs);
4413 return hr;
4416 static HRESULT WINAPI
4417 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4418 D3DPRIMITIVETYPE PrimitiveType,
4419 IDirect3DVertexBuffer7 *D3DVertexBuf,
4420 DWORD StartVertex,
4421 DWORD NumVertices,
4422 DWORD Flags)
4424 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4427 static HRESULT WINAPI
4428 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4429 D3DPRIMITIVETYPE PrimitiveType,
4430 IDirect3DVertexBuffer7 *D3DVertexBuf,
4431 DWORD StartVertex,
4432 DWORD NumVertices,
4433 DWORD Flags)
4435 HRESULT hr;
4436 WORD old_fpucw;
4438 old_fpucw = d3d_fpu_setup();
4439 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4440 set_fpu_control_word(old_fpucw);
4442 return hr;
4445 static HRESULT WINAPI
4446 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4447 D3DPRIMITIVETYPE PrimitiveType,
4448 IDirect3DVertexBuffer *D3DVertexBuf,
4449 DWORD StartVertex,
4450 DWORD NumVertices,
4451 DWORD Flags)
4453 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4454 IDirect3DVertexBufferImpl *vb = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, D3DVertexBuf);
4455 TRACE_(ddraw_thunk)("(%p)->(%08x,%p,%08x,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, vb, StartVertex, NumVertices, Flags);
4456 return IDirect3DDevice7_DrawPrimitiveVB(ICOM_INTERFACE(This, IDirect3DDevice7),
4457 PrimitiveType,
4458 ICOM_INTERFACE(vb, IDirect3DVertexBuffer7),
4459 StartVertex,
4460 NumVertices,
4461 Flags);
4465 /*****************************************************************************
4466 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4468 * Draws primitives from a vertex buffer to the screen
4470 * Params:
4471 * PrimitiveType: Type of primitive to be rendered.
4472 * D3DVertexBuf: Source Vertex Buffer
4473 * StartVertex: Index of the first vertex from the buffer to be rendered
4474 * NumVertices: Number of vertices to be rendered
4475 * Indices: Array of DWORDs used to index into the Vertices
4476 * IndexCount: Number of indices in Indices
4477 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4479 * Return values
4481 *****************************************************************************/
4482 static HRESULT
4483 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4484 D3DPRIMITIVETYPE PrimitiveType,
4485 IDirect3DVertexBuffer7 *D3DVertexBuf,
4486 DWORD StartVertex,
4487 DWORD NumVertices,
4488 WORD *Indices,
4489 DWORD IndexCount,
4490 DWORD Flags)
4492 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4493 IDirect3DVertexBufferImpl *vb = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, D3DVertexBuf);
4494 DWORD stride;
4495 UINT PrimitiveCount;
4496 WORD *LockedIndices;
4497 HRESULT hr;
4498 WINED3DVERTEXBUFFER_DESC Desc;
4500 TRACE("(%p)->(%08x,%p,%d,%d,%p,%d,%08x)\n", This, PrimitiveType, vb, StartVertex, NumVertices, Indices, IndexCount, Flags);
4502 /* Steps:
4503 * 1) Calculate some things: Vertex count -> Primitive count, stride, ...
4504 * 2) Upload the Indices to the index buffer
4505 * 3) Set the index source
4506 * 4) Set the Vertex Buffer as the Stream source
4507 * 5) Call IWineD3DDevice::DrawIndexedPrimitive
4510 /* Get the primitive count */
4511 switch(PrimitiveType)
4513 case D3DPT_POINTLIST:
4514 PrimitiveCount = IndexCount;
4515 break;
4517 case D3DPT_LINELIST:
4518 PrimitiveCount = IndexCount / 2;
4519 break;
4521 case D3DPT_LINESTRIP:
4522 PrimitiveCount = IndexCount - 1;
4523 break;
4525 case D3DPT_TRIANGLELIST:
4526 PrimitiveCount = IndexCount / 3;
4527 break;
4529 case D3DPT_TRIANGLESTRIP:
4530 PrimitiveCount = IndexCount - 2;
4531 break;
4533 case D3DPT_TRIANGLEFAN:
4534 PrimitiveCount = IndexCount - 2;
4535 break;
4537 default: return DDERR_INVALIDPARAMS;
4540 EnterCriticalSection(&ddraw_cs);
4541 /* Get the FVF of the vertex buffer, and its stride */
4542 hr = IWineD3DVertexBuffer_GetDesc(vb->wineD3DVertexBuffer,
4543 &Desc);
4544 if(hr != D3D_OK)
4546 ERR("(%p) IWineD3DVertexBuffer::GetDesc failed with hr = %08x\n", This, hr);
4547 LeaveCriticalSection(&ddraw_cs);
4548 return hr;
4550 stride = get_flexible_vertex_size(Desc.FVF);
4551 TRACE("Vertex buffer FVF = %08x, stride=%d\n", Desc.FVF, stride);
4553 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4554 vb->wineD3DVertexDeclaration);
4555 if(FAILED(hr))
4557 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4558 LeaveCriticalSection(&ddraw_cs);
4559 return hr;
4562 /* copy the index stream into the index buffer.
4563 * A new IWineD3DDevice method could be created
4564 * which takes an user pointer containing the indices
4565 * or a SetData-Method for the index buffer, which
4566 * overrides the index buffer data with our pointer.
4568 hr = IWineD3DIndexBuffer_Lock(This->indexbuffer,
4569 0 /* OffSetToLock */,
4570 IndexCount * sizeof(WORD),
4571 (BYTE **) &LockedIndices,
4572 0 /* Flags */);
4573 assert(IndexCount < 0x100000);
4574 if(hr != D3D_OK)
4576 ERR("(%p) IWineD3DIndexBuffer::Lock failed with hr = %08x\n", This, hr);
4577 LeaveCriticalSection(&ddraw_cs);
4578 return hr;
4580 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4581 hr = IWineD3DIndexBuffer_Unlock(This->indexbuffer);
4582 if(hr != D3D_OK)
4584 ERR("(%p) IWineD3DIndexBuffer::Unlock failed with hr = %08x\n", This, hr);
4585 LeaveCriticalSection(&ddraw_cs);
4586 return hr;
4589 /* Set the index stream */
4590 IWineD3DDevice_SetBaseVertexIndex(This->wineD3DDevice, StartVertex);
4591 hr = IWineD3DDevice_SetIndices(This->wineD3DDevice, This->indexbuffer);
4593 /* Set the vertex stream source */
4594 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4595 0 /* StreamNumber */,
4596 vb->wineD3DVertexBuffer,
4597 0 /* offset, we pass this to DrawIndexedPrimitive */,
4598 stride);
4599 if(hr != D3D_OK)
4601 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4602 LeaveCriticalSection(&ddraw_cs);
4603 return hr;
4607 hr = IWineD3DDevice_DrawIndexedPrimitive(This->wineD3DDevice,
4608 PrimitiveType,
4609 0 /* minIndex */,
4610 NumVertices,
4611 0 /* StartIndex */,
4612 PrimitiveCount);
4614 LeaveCriticalSection(&ddraw_cs);
4615 return hr;
4618 static HRESULT WINAPI
4619 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4620 D3DPRIMITIVETYPE PrimitiveType,
4621 IDirect3DVertexBuffer7 *D3DVertexBuf,
4622 DWORD StartVertex,
4623 DWORD NumVertices,
4624 WORD *Indices,
4625 DWORD IndexCount,
4626 DWORD Flags)
4628 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4631 static HRESULT WINAPI
4632 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4633 D3DPRIMITIVETYPE PrimitiveType,
4634 IDirect3DVertexBuffer7 *D3DVertexBuf,
4635 DWORD StartVertex,
4636 DWORD NumVertices,
4637 WORD *Indices,
4638 DWORD IndexCount,
4639 DWORD Flags)
4641 HRESULT hr;
4642 WORD old_fpucw;
4644 old_fpucw = d3d_fpu_setup();
4645 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4646 set_fpu_control_word(old_fpucw);
4648 return hr;
4651 static HRESULT WINAPI
4652 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4653 D3DPRIMITIVETYPE PrimitiveType,
4654 IDirect3DVertexBuffer *D3DVertexBuf,
4655 WORD *Indices,
4656 DWORD IndexCount,
4657 DWORD Flags)
4659 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4660 IDirect3DVertexBufferImpl *VB = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, D3DVertexBuf);
4661 TRACE_(ddraw_thunk)("(%p)->(%08x,%p,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VB, Indices, IndexCount, Flags);
4663 return IDirect3DDevice7_DrawIndexedPrimitiveVB(ICOM_INTERFACE(This, IDirect3DDevice7),
4664 PrimitiveType,
4665 ICOM_INTERFACE(VB, IDirect3DVertexBuffer7),
4667 IndexCount,
4668 Indices,
4669 IndexCount,
4670 Flags);
4673 /*****************************************************************************
4674 * IDirect3DDevice7::ComputeSphereVisibility
4676 * Calculates the visibility of spheres in the current viewport. The spheres
4677 * are passed in the Centers and Radii arrays, the results are passed back
4678 * in the ReturnValues array. Return values are either completely visible,
4679 * partially visible or completely invisible.
4680 * The return value consist of a combination of D3DCLIP_* flags, or it's
4681 * 0 if the sphere is completely visible(according to the SDK, not checked)
4683 * Sounds like an overdose of math ;)
4685 * Version 3 and 7
4687 * Params:
4688 * Centers: Array containing the sphere centers
4689 * Radii: Array containing the sphere radii
4690 * NumSpheres: The number of centers and radii in the arrays
4691 * Flags: Some flags
4692 * ReturnValues: Array to write the results to
4694 * Returns:
4695 * D3D_OK because it's a stub
4696 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4697 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4698 * is singular)
4700 *****************************************************************************/
4701 static HRESULT WINAPI
4702 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4703 D3DVECTOR *Centers,
4704 D3DVALUE *Radii,
4705 DWORD NumSpheres,
4706 DWORD Flags,
4707 DWORD *ReturnValues)
4709 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4710 FIXME("(%p)->(%p,%p,%08x,%08x,%p): stub!\n", This, Centers, Radii, NumSpheres, Flags, ReturnValues);
4712 /* the DirectX 7 sdk says that the visibility is computed by
4713 * back-transforming the viewing frustum to model space
4714 * using the inverse of the combined world, view and projection
4715 * matrix. If the matrix can't be reversed, D3DERR_INVALIDMATRIX
4716 * is returned.
4718 * Basic implementation idea:
4719 * 1) Check if the center is in the viewing frustum
4720 * 2) Cut the sphere with the planes of the viewing
4721 * frustum
4723 * ->Center inside the frustum, no intersections:
4724 * Fully visible
4725 * ->Center outside the frustum, no intersections:
4726 * Not visible
4727 * ->Some intersections: Partially visible
4729 * Implement this call in WineD3D. Either implement the
4730 * matrix and vector stuff in WineD3D, or use some external
4731 * math library.
4734 return D3D_OK;
4737 static HRESULT WINAPI
4738 Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4739 D3DVECTOR *Centers,
4740 D3DVALUE *Radii,
4741 DWORD NumSpheres,
4742 DWORD Flags,
4743 DWORD *ReturnValues)
4745 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4746 TRACE_(ddraw_thunk)("(%p)->(%p,%p,%08x,%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, Centers, Radii, NumSpheres, Flags, ReturnValues);
4747 return IDirect3DDevice7_ComputeSphereVisibility(ICOM_INTERFACE(This, IDirect3DDevice7),
4748 Centers,
4749 Radii,
4750 NumSpheres,
4751 Flags,
4752 ReturnValues);
4755 /*****************************************************************************
4756 * IDirect3DDevice7::GetTexture
4758 * Returns the texture interface handle assigned to a texture stage.
4759 * The returned texture is AddRefed. This is taken from old ddraw,
4760 * not checked in Windows.
4762 * Version 3 and 7
4764 * Params:
4765 * Stage: Texture stage to read the texture from
4766 * Texture: Address to store the interface pointer at
4768 * Returns:
4769 * D3D_OK on success
4770 * DDERR_INVALIDPARAMS if Texture is NULL
4771 * For details, see IWineD3DDevice::GetTexture
4773 *****************************************************************************/
4774 static HRESULT
4775 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4776 DWORD Stage,
4777 IDirectDrawSurface7 **Texture)
4779 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4780 IWineD3DBaseTexture *Surf;
4781 HRESULT hr;
4782 TRACE("(%p)->(%d,%p): Relay\n", This, Stage, Texture);
4784 if(!Texture)
4786 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4787 return DDERR_INVALIDPARAMS;
4790 EnterCriticalSection(&ddraw_cs);
4791 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, Stage, &Surf);
4792 if( (hr != D3D_OK) || (!Surf) )
4794 *Texture = NULL;
4795 LeaveCriticalSection(&ddraw_cs);
4796 return hr;
4799 /* GetParent AddRef()s, which is perfectly OK.
4800 * We have passed the IDirectDrawSurface7 interface to WineD3D, so that's OK too.
4802 hr = IWineD3DBaseTexture_GetParent(Surf,
4803 (IUnknown **) Texture);
4804 LeaveCriticalSection(&ddraw_cs);
4805 return hr;
4808 static HRESULT WINAPI
4809 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4810 DWORD Stage,
4811 IDirectDrawSurface7 **Texture)
4813 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4816 static HRESULT WINAPI
4817 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4818 DWORD Stage,
4819 IDirectDrawSurface7 **Texture)
4821 HRESULT hr;
4822 WORD old_fpucw;
4824 old_fpucw = d3d_fpu_setup();
4825 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4826 set_fpu_control_word(old_fpucw);
4828 return hr;
4831 static HRESULT WINAPI
4832 Thunk_IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface,
4833 DWORD Stage,
4834 IDirect3DTexture2 **Texture2)
4836 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4837 HRESULT ret;
4838 IDirectDrawSurface7 *ret_val;
4840 TRACE_(ddraw_thunk)("(%p)->(%d,%p) thunking to IDirect3DDevice7 interface.\n", This, Stage, Texture2);
4841 ret = IDirect3DDevice7_GetTexture(ICOM_INTERFACE(This, IDirect3DDevice7),
4842 Stage,
4843 &ret_val);
4845 *Texture2 = COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirectDrawSurface7, IDirect3DTexture2, ret_val);
4847 TRACE_(ddraw_thunk)(" returning interface %p.\n", *Texture2);
4849 return ret;
4852 /*****************************************************************************
4853 * IDirect3DDevice7::SetTexture
4855 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4857 * Version 3 and 7
4859 * Params:
4860 * Stage: The stage to assign the texture to
4861 * Texture: Interface pointer to the texture surface
4863 * Returns
4864 * D3D_OK on success
4865 * For details, see IWineD3DDevice::SetTexture
4867 *****************************************************************************/
4868 static HRESULT
4869 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4870 DWORD Stage,
4871 IDirectDrawSurface7 *Texture)
4873 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4874 IDirectDrawSurfaceImpl *surf = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, Texture);
4875 HRESULT hr;
4876 TRACE("(%p)->(%08x,%p): Relay!\n", This, Stage, surf);
4878 /* Texture may be NULL here */
4879 EnterCriticalSection(&ddraw_cs);
4880 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
4881 Stage,
4882 surf ? surf->wineD3DTexture : NULL);
4883 LeaveCriticalSection(&ddraw_cs);
4884 return hr;
4887 static HRESULT WINAPI
4888 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4889 DWORD Stage,
4890 IDirectDrawSurface7 *Texture)
4892 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4895 static HRESULT WINAPI
4896 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4897 DWORD Stage,
4898 IDirectDrawSurface7 *Texture)
4900 HRESULT hr;
4901 WORD old_fpucw;
4903 old_fpucw = d3d_fpu_setup();
4904 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4905 set_fpu_control_word(old_fpucw);
4907 return hr;
4910 static HRESULT WINAPI
4911 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4912 DWORD Stage,
4913 IDirect3DTexture2 *Texture2)
4915 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4916 IDirectDrawSurfaceImpl *tex = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture2, Texture2);
4917 DWORD texmapblend;
4918 HRESULT hr;
4919 TRACE("(%p)->(%d,%p)\n", This, Stage, tex);
4921 EnterCriticalSection(&ddraw_cs);
4923 if (This->legacyTextureBlending)
4924 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4926 hr = IDirect3DDevice7_SetTexture(ICOM_INTERFACE(This, IDirect3DDevice7),
4927 Stage,
4928 ICOM_INTERFACE(tex, IDirectDrawSurface7));
4930 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4932 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4933 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4934 BOOL tex_alpha = FALSE;
4935 IWineD3DBaseTexture *tex = NULL;
4936 WINED3DSURFACE_DESC desc;
4937 WINED3DFORMAT fmt;
4938 DDPIXELFORMAT ddfmt;
4939 HRESULT result;
4941 result = IWineD3DDevice_GetTexture(This->wineD3DDevice,
4943 &tex);
4945 if(result == WINED3D_OK && tex)
4947 memset(&desc, 0, sizeof(desc));
4948 desc.Format = &fmt;
4949 result = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
4950 if (SUCCEEDED(result))
4952 ddfmt.dwSize = sizeof(ddfmt);
4953 PixelFormat_WineD3DtoDD(&ddfmt, fmt);
4954 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4957 IWineD3DBaseTexture_Release(tex);
4960 /* alphaop is WINED3DTOP_SELECTARG1 if it's D3DTBLEND_MODULATE, so only modify alphaarg1 */
4961 if (tex_alpha)
4963 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
4965 else
4967 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_CURRENT);
4971 LeaveCriticalSection(&ddraw_cs);
4973 return hr;
4976 /*****************************************************************************
4977 * IDirect3DDevice7::GetTextureStageState
4979 * Retrieves a state from a texture stage.
4981 * Version 3 and 7
4983 * Params:
4984 * Stage: The stage to retrieve the state from
4985 * TexStageStateType: The state type to retrieve
4986 * State: Address to store the state's value at
4988 * Returns:
4989 * D3D_OK on success
4990 * DDERR_INVALIDPARAMS if State is NULL
4991 * For details, see IWineD3DDevice::GetTextureStageState
4993 *****************************************************************************/
4994 static HRESULT
4995 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4996 DWORD Stage,
4997 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4998 DWORD *State)
5000 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5001 HRESULT hr;
5002 TRACE("(%p)->(%08x,%08x,%p): Relay!\n", This, Stage, TexStageStateType, State);
5004 if(!State)
5005 return DDERR_INVALIDPARAMS;
5007 EnterCriticalSection(&ddraw_cs);
5008 switch(TexStageStateType)
5010 /* Mipfilter is a sampler state with different values */
5011 case D3DTSS_MIPFILTER:
5013 WINED3DTEXTUREFILTERTYPE value;
5015 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
5016 Stage,
5017 WINED3DSAMP_MIPFILTER,
5018 &value);
5019 switch(value)
5021 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
5022 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
5023 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
5024 default:
5025 ERR("Unexpected mipfilter value %d\n", value);
5026 *State = D3DTFP_NONE;
5028 break;
5031 /* Minfilter is a sampler state too, equal values */
5032 case D3DTSS_MINFILTER:
5033 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
5034 Stage,
5035 WINED3DSAMP_MINFILTER,
5036 State);
5037 break;
5039 /* Magfilter has slightly different values */
5040 case D3DTSS_MAGFILTER:
5042 WINED3DTEXTUREFILTERTYPE wined3dfilter;
5043 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
5044 Stage,
5045 WINED3DSAMP_MAGFILTER,
5046 &wined3dfilter);
5047 switch(wined3dfilter)
5049 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
5050 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
5051 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
5052 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
5053 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
5054 default:
5055 ERR("Unexpected wined3d mag filter value %d\n", wined3dfilter);
5056 *State = D3DTFG_POINT;
5058 break;
5061 case D3DTSS_ADDRESS:
5062 case D3DTSS_ADDRESSU:
5063 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
5064 Stage,
5065 WINED3DSAMP_ADDRESSU,
5066 State);
5067 break;
5068 case D3DTSS_ADDRESSV:
5069 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
5070 Stage,
5071 WINED3DSAMP_ADDRESSV,
5072 State);
5073 break;
5074 default:
5075 hr = IWineD3DDevice_GetTextureStageState(This->wineD3DDevice,
5076 Stage,
5077 TexStageStateType,
5078 State);
5079 break;
5081 LeaveCriticalSection(&ddraw_cs);
5082 return hr;
5085 static HRESULT WINAPI
5086 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5087 DWORD Stage,
5088 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5089 DWORD *State)
5091 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
5094 static HRESULT WINAPI
5095 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5096 DWORD Stage,
5097 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5098 DWORD *State)
5100 HRESULT hr;
5101 WORD old_fpucw;
5103 old_fpucw = d3d_fpu_setup();
5104 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
5105 set_fpu_control_word(old_fpucw);
5107 return hr;
5110 static HRESULT WINAPI
5111 Thunk_IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
5112 DWORD Stage,
5113 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5114 DWORD *State)
5116 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
5117 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, Stage, TexStageStateType, State);
5118 return IDirect3DDevice7_GetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
5119 Stage,
5120 TexStageStateType,
5121 State);
5124 /*****************************************************************************
5125 * IDirect3DDevice7::SetTextureStageState
5127 * Sets a texture stage state. Some stage types need to be handled specially,
5128 * because they do not exist in WineD3D and were moved to another place
5130 * Version 3 and 7
5132 * Params:
5133 * Stage: The stage to modify
5134 * TexStageStateType: The state to change
5135 * State: The new value for the state
5137 * Returns:
5138 * D3D_OK on success
5139 * For details, see IWineD3DDevice::SetTextureStageState
5141 *****************************************************************************/
5142 static HRESULT
5143 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
5144 DWORD Stage,
5145 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5146 DWORD State)
5148 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5149 HRESULT hr;
5150 TRACE("(%p)->(%08x,%08x,%08x): Relay!\n", This, Stage, TexStageStateType, State);
5152 EnterCriticalSection(&ddraw_cs);
5153 switch(TexStageStateType)
5155 /* Mipfilter is a sampler state with different values */
5156 case D3DTSS_MIPFILTER:
5158 WINED3DTEXTUREFILTERTYPE value;
5159 switch(State)
5161 case D3DTFP_NONE: value = WINED3DTEXF_NONE; break;
5162 case D3DTFP_POINT: value = WINED3DTEXF_POINT; break;
5163 case 0: /* Unchecked */
5164 case D3DTFP_LINEAR: value = WINED3DTEXF_LINEAR; break;
5165 default:
5166 ERR("Unexpected mipfilter value %d\n", State);
5167 value = WINED3DTEXF_NONE;
5169 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
5170 Stage,
5171 WINED3DSAMP_MIPFILTER,
5172 value);
5173 break;
5176 /* Minfilter is a sampler state too, equal values */
5177 case D3DTSS_MINFILTER:
5178 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
5179 Stage,
5180 WINED3DSAMP_MINFILTER,
5181 State);
5182 break;
5184 /* Magfilter has slightly different values */
5185 case D3DTSS_MAGFILTER:
5187 WINED3DTEXTUREFILTERTYPE wined3dfilter;
5188 switch((D3DTEXTUREMAGFILTER) State)
5190 case D3DTFG_POINT: wined3dfilter = WINED3DTEXF_POINT; break;
5191 case D3DTFG_LINEAR: wined3dfilter = WINED3DTEXF_LINEAR; break;
5192 case D3DTFG_FLATCUBIC: wined3dfilter = WINED3DTEXF_FLATCUBIC; break;
5193 case D3DTFG_GAUSSIANCUBIC: wined3dfilter = WINED3DTEXF_GAUSSIANCUBIC; break;
5194 case D3DTFG_ANISOTROPIC: wined3dfilter = WINED3DTEXF_ANISOTROPIC; break;
5195 default:
5196 ERR("Unexpected d3d7 mag filter type %d\n", State);
5197 wined3dfilter = WINED3DTEXF_POINT;
5199 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
5200 Stage,
5201 WINED3DSAMP_MAGFILTER,
5202 wined3dfilter);
5203 break;
5206 case D3DTSS_ADDRESS:
5207 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
5208 Stage,
5209 WINED3DSAMP_ADDRESSV,
5210 State);
5211 /* Drop through */
5212 case D3DTSS_ADDRESSU:
5213 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
5214 Stage,
5215 WINED3DSAMP_ADDRESSU,
5216 State);
5217 break;
5219 case D3DTSS_ADDRESSV:
5220 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
5221 Stage,
5222 WINED3DSAMP_ADDRESSV,
5223 State);
5224 break;
5226 default:
5227 hr = IWineD3DDevice_SetTextureStageState(This->wineD3DDevice,
5228 Stage,
5229 TexStageStateType,
5230 State);
5231 break;
5233 LeaveCriticalSection(&ddraw_cs);
5234 return hr;
5237 static HRESULT WINAPI
5238 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5239 DWORD Stage,
5240 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5241 DWORD State)
5243 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5246 static HRESULT WINAPI
5247 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5248 DWORD Stage,
5249 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5250 DWORD State)
5252 HRESULT hr;
5253 WORD old_fpucw;
5255 old_fpucw = d3d_fpu_setup();
5256 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5257 set_fpu_control_word(old_fpucw);
5259 return hr;
5262 static HRESULT WINAPI
5263 Thunk_IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
5264 DWORD Stage,
5265 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5266 DWORD State)
5268 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
5269 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, Stage, TexStageStateType, State);
5270 return IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
5271 Stage,
5272 TexStageStateType,
5273 State);
5276 /*****************************************************************************
5277 * IDirect3DDevice7::ValidateDevice
5279 * SDK: "Reports the device's ability to render the currently set
5280 * texture-blending operations in a single pass". Whatever that means
5281 * exactly...
5283 * Version 3 and 7
5285 * Params:
5286 * NumPasses: Address to write the number of necessary passes for the
5287 * desired effect to.
5289 * Returns:
5290 * D3D_OK on success
5291 * See IWineD3DDevice::ValidateDevice for more details
5293 *****************************************************************************/
5294 static HRESULT
5295 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
5296 DWORD *NumPasses)
5298 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5299 HRESULT hr;
5300 TRACE("(%p)->(%p): Relay\n", This, NumPasses);
5302 EnterCriticalSection(&ddraw_cs);
5303 hr = IWineD3DDevice_ValidateDevice(This->wineD3DDevice, NumPasses);
5304 LeaveCriticalSection(&ddraw_cs);
5305 return hr;
5308 static HRESULT WINAPI
5309 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
5310 DWORD *NumPasses)
5312 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5315 static HRESULT WINAPI
5316 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
5317 DWORD *NumPasses)
5319 HRESULT hr;
5320 WORD old_fpucw;
5322 old_fpucw = d3d_fpu_setup();
5323 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5324 set_fpu_control_word(old_fpucw);
5326 return hr;
5329 static HRESULT WINAPI
5330 Thunk_IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface,
5331 DWORD *Passes)
5333 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
5334 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Passes);
5335 return IDirect3DDevice7_ValidateDevice(ICOM_INTERFACE(This, IDirect3DDevice7),
5336 Passes);
5339 /*****************************************************************************
5340 * IDirect3DDevice7::Clear
5342 * Fills the render target, the z buffer and the stencil buffer with a
5343 * clear color / value
5345 * Version 7 only
5347 * Params:
5348 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5349 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5350 * Flags: Some flags, as usual
5351 * Color: Clear color for the render target
5352 * Z: Clear value for the Z buffer
5353 * Stencil: Clear value to store in each stencil buffer entry
5355 * Returns:
5356 * D3D_OK on success
5357 * For details, see IWineD3DDevice::Clear
5359 *****************************************************************************/
5360 static HRESULT
5361 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
5362 DWORD Count,
5363 D3DRECT *Rects,
5364 DWORD Flags,
5365 D3DCOLOR Color,
5366 D3DVALUE Z,
5367 DWORD Stencil)
5369 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5370 HRESULT hr;
5371 TRACE("(%p)->(%08x,%p,%08x,%08x,%f,%08x): Relay\n", This, Count, Rects, Flags, Color, Z, Stencil);
5373 /* Note; D3DRECT is compatible with WINED3DRECT */
5374 EnterCriticalSection(&ddraw_cs);
5375 hr = IWineD3DDevice_Clear(This->wineD3DDevice, Count, (WINED3DRECT*) Rects, Flags, Color, Z, Stencil);
5376 LeaveCriticalSection(&ddraw_cs);
5377 return hr;
5380 static HRESULT WINAPI
5381 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5382 DWORD Count,
5383 D3DRECT *Rects,
5384 DWORD Flags,
5385 D3DCOLOR Color,
5386 D3DVALUE Z,
5387 DWORD Stencil)
5389 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5392 static HRESULT WINAPI
5393 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5394 DWORD Count,
5395 D3DRECT *Rects,
5396 DWORD Flags,
5397 D3DCOLOR Color,
5398 D3DVALUE Z,
5399 DWORD Stencil)
5401 HRESULT hr;
5402 WORD old_fpucw;
5404 old_fpucw = d3d_fpu_setup();
5405 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5406 set_fpu_control_word(old_fpucw);
5408 return hr;
5411 /*****************************************************************************
5412 * IDirect3DDevice7::SetViewport
5414 * Sets the current viewport.
5416 * Version 7 only, but IDirect3DViewport uses this call for older
5417 * versions
5419 * Params:
5420 * Data: The new viewport to set
5422 * Returns:
5423 * D3D_OK on success
5424 * DDERR_INVALIDPARAMS if Data is NULL
5425 * For more details, see IWineDDDevice::SetViewport
5427 *****************************************************************************/
5428 static HRESULT
5429 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5430 D3DVIEWPORT7 *Data)
5432 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5433 HRESULT hr;
5434 TRACE("(%p)->(%p) Relay!\n", This, Data);
5436 if(!Data)
5437 return DDERR_INVALIDPARAMS;
5439 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5440 EnterCriticalSection(&ddraw_cs);
5441 hr = IWineD3DDevice_SetViewport(This->wineD3DDevice,
5442 (WINED3DVIEWPORT*) Data);
5443 LeaveCriticalSection(&ddraw_cs);
5444 return hr;
5447 static HRESULT WINAPI
5448 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5449 D3DVIEWPORT7 *Data)
5451 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5454 static HRESULT WINAPI
5455 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5456 D3DVIEWPORT7 *Data)
5458 HRESULT hr;
5459 WORD old_fpucw;
5461 old_fpucw = d3d_fpu_setup();
5462 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5463 set_fpu_control_word(old_fpucw);
5465 return hr;
5468 /*****************************************************************************
5469 * IDirect3DDevice::GetViewport
5471 * Returns the current viewport
5473 * Version 7
5475 * Params:
5476 * Data: D3D7Viewport structure to write the viewport information to
5478 * Returns:
5479 * D3D_OK on success
5480 * DDERR_INVALIDPARAMS if Data is NULL
5481 * For more details, see IWineD3DDevice::GetViewport
5483 *****************************************************************************/
5484 static HRESULT
5485 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5486 D3DVIEWPORT7 *Data)
5488 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5489 HRESULT hr;
5490 TRACE("(%p)->(%p) Relay!\n", This, Data);
5492 if(!Data)
5493 return DDERR_INVALIDPARAMS;
5495 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5496 EnterCriticalSection(&ddraw_cs);
5497 hr = IWineD3DDevice_GetViewport(This->wineD3DDevice,
5498 (WINED3DVIEWPORT*) Data);
5500 LeaveCriticalSection(&ddraw_cs);
5501 return hr_ddraw_from_wined3d(hr);
5504 static HRESULT WINAPI
5505 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5506 D3DVIEWPORT7 *Data)
5508 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5511 static HRESULT WINAPI
5512 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5513 D3DVIEWPORT7 *Data)
5515 HRESULT hr;
5516 WORD old_fpucw;
5518 old_fpucw = d3d_fpu_setup();
5519 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5520 set_fpu_control_word(old_fpucw);
5522 return hr;
5525 /*****************************************************************************
5526 * IDirect3DDevice7::SetMaterial
5528 * Sets the Material
5530 * Version 7
5532 * Params:
5533 * Mat: The material to set
5535 * Returns:
5536 * D3D_OK on success
5537 * DDERR_INVALIDPARAMS if Mat is NULL.
5538 * For more details, see IWineD3DDevice::SetMaterial
5540 *****************************************************************************/
5541 static HRESULT
5542 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5543 D3DMATERIAL7 *Mat)
5545 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5546 HRESULT hr;
5547 TRACE("(%p)->(%p): Relay!\n", This, Mat);
5549 if (!Mat) return DDERR_INVALIDPARAMS;
5550 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5551 EnterCriticalSection(&ddraw_cs);
5552 hr = IWineD3DDevice_SetMaterial(This->wineD3DDevice,
5553 (WINED3DMATERIAL*) Mat);
5554 LeaveCriticalSection(&ddraw_cs);
5555 return hr_ddraw_from_wined3d(hr);
5558 static HRESULT WINAPI
5559 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5560 D3DMATERIAL7 *Mat)
5562 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5565 static HRESULT WINAPI
5566 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5567 D3DMATERIAL7 *Mat)
5569 HRESULT hr;
5570 WORD old_fpucw;
5572 old_fpucw = d3d_fpu_setup();
5573 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5574 set_fpu_control_word(old_fpucw);
5576 return hr;
5579 /*****************************************************************************
5580 * IDirect3DDevice7::GetMaterial
5582 * Returns the current material
5584 * Version 7
5586 * Params:
5587 * Mat: D3DMATERIAL7 structure to write the material parameters to
5589 * Returns:
5590 * D3D_OK on success
5591 * DDERR_INVALIDPARAMS if Mat is NULL
5592 * For more details, see IWineD3DDevice::GetMaterial
5594 *****************************************************************************/
5595 static HRESULT
5596 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5597 D3DMATERIAL7 *Mat)
5599 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5600 HRESULT hr;
5601 TRACE("(%p)->(%p): Relay!\n", This, Mat);
5603 EnterCriticalSection(&ddraw_cs);
5604 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5605 hr = IWineD3DDevice_GetMaterial(This->wineD3DDevice,
5606 (WINED3DMATERIAL*) Mat);
5607 LeaveCriticalSection(&ddraw_cs);
5608 return hr_ddraw_from_wined3d(hr);
5611 static HRESULT WINAPI
5612 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5613 D3DMATERIAL7 *Mat)
5615 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5618 static HRESULT WINAPI
5619 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5620 D3DMATERIAL7 *Mat)
5622 HRESULT hr;
5623 WORD old_fpucw;
5625 old_fpucw = d3d_fpu_setup();
5626 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5627 set_fpu_control_word(old_fpucw);
5629 return hr;
5632 /*****************************************************************************
5633 * IDirect3DDevice7::SetLight
5635 * Assigns a light to a light index, but doesn't activate it yet.
5637 * Version 7, IDirect3DLight uses this method for older versions
5639 * Params:
5640 * LightIndex: The index of the new light
5641 * Light: A D3DLIGHT7 structure describing the light
5643 * Returns:
5644 * D3D_OK on success
5645 * For more details, see IWineD3DDevice::SetLight
5647 *****************************************************************************/
5648 static HRESULT
5649 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5650 DWORD LightIndex,
5651 D3DLIGHT7 *Light)
5653 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5654 HRESULT hr;
5655 TRACE("(%p)->(%08x,%p): Relay!\n", This, LightIndex, Light);
5657 EnterCriticalSection(&ddraw_cs);
5658 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5659 hr = IWineD3DDevice_SetLight(This->wineD3DDevice,
5660 LightIndex,
5661 (WINED3DLIGHT*) Light);
5662 LeaveCriticalSection(&ddraw_cs);
5663 return hr_ddraw_from_wined3d(hr);
5666 static HRESULT WINAPI
5667 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5668 DWORD LightIndex,
5669 D3DLIGHT7 *Light)
5671 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5674 static HRESULT WINAPI
5675 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5676 DWORD LightIndex,
5677 D3DLIGHT7 *Light)
5679 HRESULT hr;
5680 WORD old_fpucw;
5682 old_fpucw = d3d_fpu_setup();
5683 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5684 set_fpu_control_word(old_fpucw);
5686 return hr;
5689 /*****************************************************************************
5690 * IDirect3DDevice7::GetLight
5692 * Returns the light assigned to a light index
5694 * Params:
5695 * Light: Structure to write the light information to
5697 * Returns:
5698 * D3D_OK on success
5699 * DDERR_INVALIDPARAMS if Light is NULL
5700 * For details, see IWineD3DDevice::GetLight
5702 *****************************************************************************/
5703 static HRESULT
5704 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5705 DWORD LightIndex,
5706 D3DLIGHT7 *Light)
5708 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5709 HRESULT rc;
5710 TRACE("(%p)->(%08x,%p): Relay!\n", This, LightIndex, Light);
5712 EnterCriticalSection(&ddraw_cs);
5713 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5714 rc = IWineD3DDevice_GetLight(This->wineD3DDevice,
5715 LightIndex,
5716 (WINED3DLIGHT*) Light);
5718 /* Translate the result. WineD3D returns other values than D3D7 */
5719 LeaveCriticalSection(&ddraw_cs);
5720 return hr_ddraw_from_wined3d(rc);
5723 static HRESULT WINAPI
5724 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5725 DWORD LightIndex,
5726 D3DLIGHT7 *Light)
5728 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5731 static HRESULT WINAPI
5732 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5733 DWORD LightIndex,
5734 D3DLIGHT7 *Light)
5736 HRESULT hr;
5737 WORD old_fpucw;
5739 old_fpucw = d3d_fpu_setup();
5740 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5741 set_fpu_control_word(old_fpucw);
5743 return hr;
5746 /*****************************************************************************
5747 * IDirect3DDevice7::BeginStateBlock
5749 * Begins recording to a stateblock
5751 * Version 7
5753 * Returns:
5754 * D3D_OK on success
5755 * For details see IWineD3DDevice::BeginStateBlock
5757 *****************************************************************************/
5758 static HRESULT
5759 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5761 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5762 HRESULT hr;
5763 TRACE("(%p)->(): Relay!\n", This);
5765 EnterCriticalSection(&ddraw_cs);
5766 hr = IWineD3DDevice_BeginStateBlock(This->wineD3DDevice);
5767 LeaveCriticalSection(&ddraw_cs);
5768 return hr_ddraw_from_wined3d(hr);
5771 static HRESULT WINAPI
5772 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5774 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5777 static HRESULT WINAPI
5778 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5780 HRESULT hr;
5781 WORD old_fpucw;
5783 old_fpucw = d3d_fpu_setup();
5784 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5785 set_fpu_control_word(old_fpucw);
5787 return hr;
5790 /*****************************************************************************
5791 * IDirect3DDevice7::EndStateBlock
5793 * Stops recording to a state block and returns the created stateblock
5794 * handle.
5796 * Version 7
5798 * Params:
5799 * BlockHandle: Address to store the stateblock's handle to
5801 * Returns:
5802 * D3D_OK on success
5803 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5804 * See IWineD3DDevice::EndStateBlock for more details
5806 *****************************************************************************/
5807 static HRESULT
5808 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5809 DWORD *BlockHandle)
5811 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5812 HRESULT hr;
5813 TRACE("(%p)->(%p): Relay!\n", This, BlockHandle);
5815 if(!BlockHandle)
5817 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5818 return DDERR_INVALIDPARAMS;
5821 EnterCriticalSection(&ddraw_cs);
5822 *BlockHandle = IDirect3DDeviceImpl_CreateHandle(This);
5823 if(!*BlockHandle)
5825 ERR("Cannot get a handle number for the stateblock\n");
5826 LeaveCriticalSection(&ddraw_cs);
5827 return DDERR_OUTOFMEMORY;
5829 This->Handles[*BlockHandle - 1].type = DDrawHandle_StateBlock;
5830 hr = IWineD3DDevice_EndStateBlock(This->wineD3DDevice,
5831 (IWineD3DStateBlock **) &This->Handles[*BlockHandle - 1].ptr);
5832 LeaveCriticalSection(&ddraw_cs);
5833 return hr_ddraw_from_wined3d(hr);
5836 static HRESULT WINAPI
5837 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5838 DWORD *BlockHandle)
5840 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5843 static HRESULT WINAPI
5844 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5845 DWORD *BlockHandle)
5847 HRESULT hr;
5848 WORD old_fpucw;
5850 old_fpucw = d3d_fpu_setup();
5851 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5852 set_fpu_control_word(old_fpucw);
5854 return hr;
5857 /*****************************************************************************
5858 * IDirect3DDevice7::PreLoad
5860 * Allows the app to signal that a texture will be used soon, to allow
5861 * the Direct3DDevice to load it to the video card in the meantime.
5863 * Version 7
5865 * Params:
5866 * Texture: The texture to preload
5868 * Returns:
5869 * D3D_OK on success
5870 * DDERR_INVALIDPARAMS if Texture is NULL
5871 * See IWineD3DSurface::PreLoad for details
5873 *****************************************************************************/
5874 static HRESULT
5875 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5876 IDirectDrawSurface7 *Texture)
5878 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5879 IDirectDrawSurfaceImpl *surf = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, Texture);
5881 TRACE("(%p)->(%p): Relay!\n", This, surf);
5883 if(!Texture)
5884 return DDERR_INVALIDPARAMS;
5886 EnterCriticalSection(&ddraw_cs);
5887 IWineD3DSurface_PreLoad(surf->WineD3DSurface);
5888 LeaveCriticalSection(&ddraw_cs);
5889 return D3D_OK;
5892 static HRESULT WINAPI
5893 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5894 IDirectDrawSurface7 *Texture)
5896 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5899 static HRESULT WINAPI
5900 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5901 IDirectDrawSurface7 *Texture)
5903 HRESULT hr;
5904 WORD old_fpucw;
5906 old_fpucw = d3d_fpu_setup();
5907 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5908 set_fpu_control_word(old_fpucw);
5910 return hr;
5913 /*****************************************************************************
5914 * IDirect3DDevice7::ApplyStateBlock
5916 * Activates the state stored in a state block handle.
5918 * Params:
5919 * BlockHandle: The stateblock handle to activate
5921 * Returns:
5922 * D3D_OK on success
5923 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5925 *****************************************************************************/
5926 static HRESULT
5927 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5928 DWORD BlockHandle)
5930 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5931 HRESULT hr;
5932 TRACE("(%p)->(%08x): Relay!\n", This, BlockHandle);
5934 EnterCriticalSection(&ddraw_cs);
5935 if(!BlockHandle || BlockHandle > This->numHandles)
5937 WARN("Out of range handle %d, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5938 LeaveCriticalSection(&ddraw_cs);
5939 return D3DERR_INVALIDSTATEBLOCK;
5941 if(This->Handles[BlockHandle - 1].type != DDrawHandle_StateBlock)
5943 WARN("Handle %d is not a stateblock, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5944 LeaveCriticalSection(&ddraw_cs);
5945 return D3DERR_INVALIDSTATEBLOCK;
5948 hr = IWineD3DStateBlock_Apply((IWineD3DStateBlock *) This->Handles[BlockHandle - 1].ptr);
5949 LeaveCriticalSection(&ddraw_cs);
5950 return hr_ddraw_from_wined3d(hr);
5953 static HRESULT WINAPI
5954 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5955 DWORD BlockHandle)
5957 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5960 static HRESULT WINAPI
5961 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5962 DWORD BlockHandle)
5964 HRESULT hr;
5965 WORD old_fpucw;
5967 old_fpucw = d3d_fpu_setup();
5968 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5969 set_fpu_control_word(old_fpucw);
5971 return hr;
5974 /*****************************************************************************
5975 * IDirect3DDevice7::CaptureStateBlock
5977 * Updates a stateblock's values to the values currently set for the device
5979 * Version 7
5981 * Params:
5982 * BlockHandle: Stateblock to update
5984 * Returns:
5985 * D3D_OK on success
5986 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5987 * See IWineD3DDevice::CaptureStateBlock for more details
5989 *****************************************************************************/
5990 static HRESULT
5991 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5992 DWORD BlockHandle)
5994 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5995 HRESULT hr;
5996 TRACE("(%p)->(%08x): Relay!\n", This, BlockHandle);
5998 EnterCriticalSection(&ddraw_cs);
5999 if(BlockHandle == 0 || BlockHandle > This->numHandles)
6001 WARN("Out of range handle %d, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
6002 LeaveCriticalSection(&ddraw_cs);
6003 return D3DERR_INVALIDSTATEBLOCK;
6005 if(This->Handles[BlockHandle - 1].type != DDrawHandle_StateBlock)
6007 WARN("Handle %d is not a stateblock, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
6008 LeaveCriticalSection(&ddraw_cs);
6009 return D3DERR_INVALIDSTATEBLOCK;
6012 hr = IWineD3DStateBlock_Capture((IWineD3DStateBlock *) This->Handles[BlockHandle - 1].ptr);
6013 LeaveCriticalSection(&ddraw_cs);
6014 return hr_ddraw_from_wined3d(hr);
6017 static HRESULT WINAPI
6018 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
6019 DWORD BlockHandle)
6021 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
6024 static HRESULT WINAPI
6025 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
6026 DWORD BlockHandle)
6028 HRESULT hr;
6029 WORD old_fpucw;
6031 old_fpucw = d3d_fpu_setup();
6032 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
6033 set_fpu_control_word(old_fpucw);
6035 return hr;
6038 /*****************************************************************************
6039 * IDirect3DDevice7::DeleteStateBlock
6041 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
6043 * Version 7
6045 * Params:
6046 * BlockHandle: Stateblock handle to delete
6048 * Returns:
6049 * D3D_OK on success
6050 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
6052 *****************************************************************************/
6053 static HRESULT
6054 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
6055 DWORD BlockHandle)
6057 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6058 ULONG ref;
6059 TRACE("(%p)->(%08x): Relay!\n", This, BlockHandle);
6061 EnterCriticalSection(&ddraw_cs);
6062 if(BlockHandle == 0 || BlockHandle > This->numHandles)
6064 WARN("Out of range handle %d, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
6065 LeaveCriticalSection(&ddraw_cs);
6066 return D3DERR_INVALIDSTATEBLOCK;
6068 if(This->Handles[BlockHandle - 1].type != DDrawHandle_StateBlock)
6070 WARN("Handle %d is not a stateblock, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
6071 LeaveCriticalSection(&ddraw_cs);
6072 return D3DERR_INVALIDSTATEBLOCK;
6075 ref = IWineD3DStateBlock_Release((IWineD3DStateBlock *) This->Handles[BlockHandle - 1].ptr);
6076 if(ref)
6078 ERR("Something is still holding the stateblock %p(Handle %d). Ref = %d\n", This->Handles[BlockHandle - 1].ptr, BlockHandle, ref);
6080 This->Handles[BlockHandle - 1].ptr = NULL;
6081 This->Handles[BlockHandle - 1].type = DDrawHandle_Unknown;
6083 LeaveCriticalSection(&ddraw_cs);
6084 return D3D_OK;
6087 static HRESULT WINAPI
6088 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
6089 DWORD BlockHandle)
6091 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
6094 static HRESULT WINAPI
6095 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
6096 DWORD BlockHandle)
6098 HRESULT hr;
6099 WORD old_fpucw;
6101 old_fpucw = d3d_fpu_setup();
6102 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
6103 set_fpu_control_word(old_fpucw);
6105 return hr;
6108 /*****************************************************************************
6109 * IDirect3DDevice7::CreateStateBlock
6111 * Creates a new state block handle.
6113 * Version 7
6115 * Params:
6116 * Type: The state block type
6117 * BlockHandle: Address to write the created handle to
6119 * Returns:
6120 * D3D_OK on success
6121 * DDERR_INVALIDPARAMS if BlockHandle is NULL
6123 *****************************************************************************/
6124 static HRESULT
6125 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
6126 D3DSTATEBLOCKTYPE Type,
6127 DWORD *BlockHandle)
6129 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6130 HRESULT hr;
6131 TRACE("(%p)->(%08x,%p)!\n", This, Type, BlockHandle);
6133 if(!BlockHandle)
6135 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
6136 return DDERR_INVALIDPARAMS;
6138 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
6139 Type != D3DSBT_VERTEXSTATE ) {
6140 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
6141 return DDERR_INVALIDPARAMS;
6144 EnterCriticalSection(&ddraw_cs);
6145 *BlockHandle = IDirect3DDeviceImpl_CreateHandle(This);
6146 if(!*BlockHandle)
6148 ERR("Cannot get a handle number for the stateblock\n");
6149 LeaveCriticalSection(&ddraw_cs);
6150 return DDERR_OUTOFMEMORY;
6152 This->Handles[*BlockHandle - 1].type = DDrawHandle_StateBlock;
6154 /* The D3DSTATEBLOCKTYPE enum is fine here */
6155 hr = IWineD3DDevice_CreateStateBlock(This->wineD3DDevice,
6156 Type,
6157 (IWineD3DStateBlock **) &This->Handles[*BlockHandle - 1].ptr,
6158 NULL /* Parent, hope that works */);
6159 LeaveCriticalSection(&ddraw_cs);
6160 return hr_ddraw_from_wined3d(hr);
6163 static HRESULT WINAPI
6164 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
6165 D3DSTATEBLOCKTYPE Type,
6166 DWORD *BlockHandle)
6168 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6171 static HRESULT WINAPI
6172 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
6173 D3DSTATEBLOCKTYPE Type,
6174 DWORD *BlockHandle)
6176 HRESULT hr;
6177 WORD old_fpucw;
6179 old_fpucw = d3d_fpu_setup();
6180 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6181 set_fpu_control_word(old_fpucw);
6183 return hr;
6186 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6187 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
6188 IDirectDrawSurfaceImpl *src)
6190 IDirectDrawSurfaceImpl *src_level, *dest_level;
6191 IDirectDrawSurface7 *temp;
6192 DDSURFACEDESC2 ddsd;
6193 BOOL levelFound; /* at least one suitable sublevel in dest found */
6195 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
6196 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
6197 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
6199 levelFound = FALSE;
6201 src_level = src;
6202 dest_level = dest;
6204 for (;src_level && dest_level;)
6206 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6207 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6209 levelFound = TRUE;
6211 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6212 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6213 IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(dest_level, IDirectDrawSurface7), &ddsd.ddsCaps, &temp);
6215 if (dest_level != dest) IDirectDrawSurface7_Release(ICOM_INTERFACE(dest_level, IDirectDrawSurface7));
6217 dest_level = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, temp);
6220 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6221 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6222 IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(src_level, IDirectDrawSurface7), &ddsd.ddsCaps, &temp);
6224 if (src_level != src) IDirectDrawSurface7_Release(ICOM_INTERFACE(src_level, IDirectDrawSurface7));
6226 src_level = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, temp);
6229 if (src_level && src_level != src) IDirectDrawSurface7_Release(ICOM_INTERFACE(src_level, IDirectDrawSurface7));
6230 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(ICOM_INTERFACE(dest_level, IDirectDrawSurface7));
6232 return !dest_level && levelFound;
6235 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6236 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
6237 IDirectDrawSurfaceImpl *dest,
6238 IDirectDrawSurfaceImpl *src,
6239 POINT *DestPoint,
6240 RECT *SrcRect)
6242 IDirectDrawSurfaceImpl *src_level, *dest_level;
6243 IDirectDrawSurface7 *temp;
6244 DDSURFACEDESC2 ddsd;
6245 POINT point;
6246 RECT rect;
6247 HRESULT hr;
6248 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
6249 DWORD ckeyflag;
6250 DDCOLORKEY ddckey;
6251 BOOL palette_missing = FALSE;
6253 /* Copy palette, if possible. */
6254 IDirectDrawSurface7_GetPalette(ICOM_INTERFACE(src, IDirectDrawSurface7), &pal_src);
6255 IDirectDrawSurface7_GetPalette(ICOM_INTERFACE(dest, IDirectDrawSurface7), &pal);
6257 if (pal_src != NULL && pal != NULL)
6259 PALETTEENTRY palent[256];
6261 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
6262 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
6265 if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
6266 DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
6268 palette_missing = TRUE;
6271 if (pal) IDirectDrawPalette_Release(pal);
6272 if (pal_src) IDirectDrawPalette_Release(pal_src);
6274 /* Copy colorkeys, if present. */
6275 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6277 hr = IDirectDrawSurface7_GetColorKey(ICOM_INTERFACE(src, IDirectDrawSurface7), ckeyflag, &ddckey);
6279 if (SUCCEEDED(hr))
6281 IDirectDrawSurface7_SetColorKey(ICOM_INTERFACE(dest, IDirectDrawSurface7), ckeyflag, &ddckey);
6285 src_level = src;
6286 dest_level = dest;
6288 point = *DestPoint;
6289 rect = *SrcRect;
6291 for (;src_level && dest_level;)
6293 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6294 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6296 /* Try UpdateSurface that may perform a more direct opengl loading. But skip this if destination is paletted texture and has no palette.
6297 * Some games like Sacrifice set palette after Load, and it is a waste of effort to try to load texture without palette and generates
6298 * warnings in wined3d. */
6299 if (!palette_missing)
6300 hr = IWineD3DDevice_UpdateSurface(device->wineD3DDevice, src_level->WineD3DSurface, &rect, dest_level->WineD3DSurface,
6301 &point);
6303 if (palette_missing || FAILED(hr))
6305 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
6306 IWineD3DSurface_BltFast(dest_level->WineD3DSurface,
6307 point.x, point.y,
6308 src_level->WineD3DSurface, &rect, 0);
6311 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6312 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6313 IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(dest_level, IDirectDrawSurface7), &ddsd.ddsCaps, &temp);
6315 if (dest_level != dest) IDirectDrawSurface7_Release(ICOM_INTERFACE(dest_level, IDirectDrawSurface7));
6317 dest_level = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, temp);
6320 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6321 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6322 IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(src_level, IDirectDrawSurface7), &ddsd.ddsCaps, &temp);
6324 if (src_level != src) IDirectDrawSurface7_Release(ICOM_INTERFACE(src_level, IDirectDrawSurface7));
6326 src_level = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, temp);
6328 point.x /= 2;
6329 point.y /= 2;
6331 rect.top /= 2;
6332 rect.left /= 2;
6333 rect.right = (rect.right + 1) / 2;
6334 rect.bottom = (rect.bottom + 1) / 2;
6337 if (src_level && src_level != src) IDirectDrawSurface7_Release(ICOM_INTERFACE(src_level, IDirectDrawSurface7));
6338 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(ICOM_INTERFACE(dest_level, IDirectDrawSurface7));
6341 /*****************************************************************************
6342 * IDirect3DDevice7::Load
6344 * Loads a rectangular area from the source into the destination texture.
6345 * It can also copy the source to the faces of a cubic environment map
6347 * Version 7
6349 * Params:
6350 * DestTex: Destination texture
6351 * DestPoint: Point in the destination where the source image should be
6352 * written to
6353 * SrcTex: Source texture
6354 * SrcRect: Source rectangle
6355 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6356 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6357 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6359 * Returns:
6360 * D3D_OK on success
6361 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6364 *****************************************************************************/
6366 static HRESULT
6367 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6368 IDirectDrawSurface7 *DestTex,
6369 POINT *DestPoint,
6370 IDirectDrawSurface7 *SrcTex,
6371 RECT *SrcRect,
6372 DWORD Flags)
6374 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6375 IDirectDrawSurfaceImpl *dest = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, DestTex);
6376 IDirectDrawSurfaceImpl *src = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, SrcTex);
6377 POINT destpoint;
6378 RECT srcrect;
6379 TRACE("(%p)->(%p,%p,%p,%p,%08x)\n", This, dest, DestPoint, src, SrcRect, Flags);
6381 if( (!src) || (!dest) )
6382 return DDERR_INVALIDPARAMS;
6384 EnterCriticalSection(&ddraw_cs);
6386 if (SrcRect) srcrect = *SrcRect;
6387 else
6389 srcrect.left = srcrect.top = 0;
6390 srcrect.right = src->surface_desc.dwWidth;
6391 srcrect.bottom = src->surface_desc.dwHeight;
6394 if (DestPoint) destpoint = *DestPoint;
6395 else
6397 destpoint.x = destpoint.y = 0;
6399 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6400 * destination can be a subset of mip levels, in which case actual coordinates used
6401 * for it may be divided. If any dimension of dest is larger than source, it can't be
6402 * mip level subset, so an error can be returned early.
6404 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6405 srcrect.right > src->surface_desc.dwWidth ||
6406 srcrect.bottom > src->surface_desc.dwHeight ||
6407 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6408 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6409 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6410 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6412 LeaveCriticalSection(&ddraw_cs);
6413 return DDERR_INVALIDPARAMS;
6416 /* Must be top level surfaces. */
6417 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6418 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6420 LeaveCriticalSection(&ddraw_cs);
6421 return DDERR_INVALIDPARAMS;
6424 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6426 DWORD src_face_flag, dest_face_flag;
6427 IDirectDrawSurfaceImpl *src_face, *dest_face;
6428 IDirectDrawSurface7 *temp;
6429 DDSURFACEDESC2 ddsd;
6430 int i;
6432 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6434 LeaveCriticalSection(&ddraw_cs);
6435 return DDERR_INVALIDPARAMS;
6438 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6439 * time it's actual surface loading. */
6440 for (i = 0; i < 2; i++)
6442 dest_face = dest;
6443 src_face = src;
6445 for (;dest_face && src_face;)
6447 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6448 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6450 if (src_face_flag == dest_face_flag)
6452 if (i == 0)
6454 /* Destination mip levels must be subset of source mip levels. */
6455 if (!is_mip_level_subset(dest_face, src_face))
6457 LeaveCriticalSection(&ddraw_cs);
6458 return DDERR_INVALIDPARAMS;
6461 else if (Flags & dest_face_flag)
6463 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6466 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6468 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6469 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6470 IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(src, IDirectDrawSurface7), &ddsd.ddsCaps, &temp);
6472 if (src_face != src) IDirectDrawSurface7_Release(ICOM_INTERFACE(src_face, IDirectDrawSurface7));
6474 src_face = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, temp);
6476 else
6478 if (src_face != src) IDirectDrawSurface7_Release(ICOM_INTERFACE(src_face, IDirectDrawSurface7));
6480 src_face = NULL;
6484 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6486 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6487 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6488 IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(dest, IDirectDrawSurface7), &ddsd.ddsCaps, &temp);
6490 if (dest_face != dest) IDirectDrawSurface7_Release(ICOM_INTERFACE(dest_face, IDirectDrawSurface7));
6492 dest_face = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, temp);
6494 else
6496 if (dest_face != dest) IDirectDrawSurface7_Release(ICOM_INTERFACE(dest_face, IDirectDrawSurface7));
6498 dest_face = NULL;
6502 if (i == 0)
6504 /* Native returns error if src faces are not subset of dest faces. */
6505 if (src_face)
6507 LeaveCriticalSection(&ddraw_cs);
6508 return DDERR_INVALIDPARAMS;
6513 LeaveCriticalSection(&ddraw_cs);
6514 return D3D_OK;
6516 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6518 LeaveCriticalSection(&ddraw_cs);
6519 return DDERR_INVALIDPARAMS;
6522 /* Handle non cube map textures. */
6524 /* Destination mip levels must be subset of source mip levels. */
6525 if (!is_mip_level_subset(dest, src))
6527 LeaveCriticalSection(&ddraw_cs);
6528 return DDERR_INVALIDPARAMS;
6531 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6533 LeaveCriticalSection(&ddraw_cs);
6534 return D3D_OK;
6537 static HRESULT WINAPI
6538 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6539 IDirectDrawSurface7 *DestTex,
6540 POINT *DestPoint,
6541 IDirectDrawSurface7 *SrcTex,
6542 RECT *SrcRect,
6543 DWORD Flags)
6545 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6548 static HRESULT WINAPI
6549 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6550 IDirectDrawSurface7 *DestTex,
6551 POINT *DestPoint,
6552 IDirectDrawSurface7 *SrcTex,
6553 RECT *SrcRect,
6554 DWORD Flags)
6556 HRESULT hr;
6557 WORD old_fpucw;
6559 old_fpucw = d3d_fpu_setup();
6560 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6561 set_fpu_control_word(old_fpucw);
6563 return hr;
6566 /*****************************************************************************
6567 * IDirect3DDevice7::LightEnable
6569 * Enables or disables a light
6571 * Version 7, IDirect3DLight uses this method too.
6573 * Params:
6574 * LightIndex: The index of the light to enable / disable
6575 * Enable: Enable or disable the light
6577 * Returns:
6578 * D3D_OK on success
6579 * For more details, see IWineD3DDevice::SetLightEnable
6581 *****************************************************************************/
6582 static HRESULT
6583 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6584 DWORD LightIndex,
6585 BOOL Enable)
6587 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6588 HRESULT hr;
6589 TRACE("(%p)->(%08x,%d): Relay!\n", This, LightIndex, Enable);
6591 EnterCriticalSection(&ddraw_cs);
6592 hr = IWineD3DDevice_SetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6593 LeaveCriticalSection(&ddraw_cs);
6594 return hr_ddraw_from_wined3d(hr);
6597 static HRESULT WINAPI
6598 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6599 DWORD LightIndex,
6600 BOOL Enable)
6602 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6605 static HRESULT WINAPI
6606 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6607 DWORD LightIndex,
6608 BOOL Enable)
6610 HRESULT hr;
6611 WORD old_fpucw;
6613 old_fpucw = d3d_fpu_setup();
6614 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6615 set_fpu_control_word(old_fpucw);
6617 return hr;
6620 /*****************************************************************************
6621 * IDirect3DDevice7::GetLightEnable
6623 * Retrieves if the light with the given index is enabled or not
6625 * Version 7
6627 * Params:
6628 * LightIndex: Index of desired light
6629 * Enable: Pointer to a BOOL which contains the result
6631 * Returns:
6632 * D3D_OK on success
6633 * DDERR_INVALIDPARAMS if Enable is NULL
6634 * See IWineD3DDevice::GetLightEnable for more details
6636 *****************************************************************************/
6637 static HRESULT
6638 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6639 DWORD LightIndex,
6640 BOOL* Enable)
6642 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6643 HRESULT hr;
6644 TRACE("(%p)->(%08x,%p): Relay\n", This, LightIndex, Enable);
6646 if(!Enable)
6647 return DDERR_INVALIDPARAMS;
6649 EnterCriticalSection(&ddraw_cs);
6650 hr = IWineD3DDevice_GetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6651 LeaveCriticalSection(&ddraw_cs);
6652 return hr_ddraw_from_wined3d(hr);
6655 static HRESULT WINAPI
6656 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6657 DWORD LightIndex,
6658 BOOL* Enable)
6660 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6663 static HRESULT WINAPI
6664 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6665 DWORD LightIndex,
6666 BOOL* Enable)
6668 HRESULT hr;
6669 WORD old_fpucw;
6671 old_fpucw = d3d_fpu_setup();
6672 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6673 set_fpu_control_word(old_fpucw);
6675 return hr;
6678 /*****************************************************************************
6679 * IDirect3DDevice7::SetClipPlane
6681 * Sets custom clipping plane
6683 * Version 7
6685 * Params:
6686 * Index: The index of the clipping plane
6687 * PlaneEquation: An equation defining the clipping plane
6689 * Returns:
6690 * D3D_OK on success
6691 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6692 * See IWineD3DDevice::SetClipPlane for more details
6694 *****************************************************************************/
6695 static HRESULT
6696 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6697 DWORD Index,
6698 D3DVALUE* PlaneEquation)
6700 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6701 HRESULT hr;
6702 TRACE("(%p)->(%08x,%p): Relay!\n", This, Index, PlaneEquation);
6704 if(!PlaneEquation)
6705 return DDERR_INVALIDPARAMS;
6707 EnterCriticalSection(&ddraw_cs);
6708 hr = IWineD3DDevice_SetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6709 LeaveCriticalSection(&ddraw_cs);
6710 return hr;
6713 static HRESULT WINAPI
6714 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6715 DWORD Index,
6716 D3DVALUE* PlaneEquation)
6718 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6721 static HRESULT WINAPI
6722 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6723 DWORD Index,
6724 D3DVALUE* PlaneEquation)
6726 HRESULT hr;
6727 WORD old_fpucw;
6729 old_fpucw = d3d_fpu_setup();
6730 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6731 set_fpu_control_word(old_fpucw);
6733 return hr;
6736 /*****************************************************************************
6737 * IDirect3DDevice7::GetClipPlane
6739 * Returns the clipping plane with a specific index
6741 * Params:
6742 * Index: The index of the desired plane
6743 * PlaneEquation: Address to store the plane equation to
6745 * Returns:
6746 * D3D_OK on success
6747 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6748 * See IWineD3DDevice::GetClipPlane for more details
6750 *****************************************************************************/
6751 static HRESULT
6752 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6753 DWORD Index,
6754 D3DVALUE* PlaneEquation)
6756 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6757 HRESULT hr;
6758 TRACE("(%p)->(%d,%p): Relay!\n", This, Index, PlaneEquation);
6760 if(!PlaneEquation)
6761 return DDERR_INVALIDPARAMS;
6763 EnterCriticalSection(&ddraw_cs);
6764 hr = IWineD3DDevice_GetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6765 LeaveCriticalSection(&ddraw_cs);
6766 return hr;
6769 static HRESULT WINAPI
6770 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6771 DWORD Index,
6772 D3DVALUE* PlaneEquation)
6774 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6777 static HRESULT WINAPI
6778 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6779 DWORD Index,
6780 D3DVALUE* PlaneEquation)
6782 HRESULT hr;
6783 WORD old_fpucw;
6785 old_fpucw = d3d_fpu_setup();
6786 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6787 set_fpu_control_word(old_fpucw);
6789 return hr;
6792 /*****************************************************************************
6793 * IDirect3DDevice7::GetInfo
6795 * Retrieves some information about the device. The DirectX sdk says that
6796 * this version returns S_FALSE for all retail builds of DirectX, that's what
6797 * this implementation does.
6799 * Params:
6800 * DevInfoID: Information type requested
6801 * DevInfoStruct: Pointer to a structure to store the info to
6802 * Size: Size of the structure
6804 * Returns:
6805 * S_FALSE, because it's a non-debug driver
6807 *****************************************************************************/
6808 static HRESULT WINAPI
6809 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6810 DWORD DevInfoID,
6811 void *DevInfoStruct,
6812 DWORD Size)
6814 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6815 TRACE("(%p)->(%08x,%p,%08x)\n", This, DevInfoID, DevInfoStruct, Size);
6817 if (TRACE_ON(d3d7))
6819 TRACE(" info requested : ");
6820 switch (DevInfoID)
6822 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6823 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6824 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6825 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6829 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6832 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6833 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6834 * are not duplicated.
6836 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6837 * has already been setup for optimal d3d operation.
6839 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6840 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6841 * by Sacrifice (game). */
6842 const IDirect3DDevice7Vtbl IDirect3DDevice7_FPUSetup_Vtbl =
6844 /*** IUnknown Methods ***/
6845 IDirect3DDeviceImpl_7_QueryInterface,
6846 IDirect3DDeviceImpl_7_AddRef,
6847 IDirect3DDeviceImpl_7_Release,
6848 /*** IDirect3DDevice7 ***/
6849 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6850 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6851 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6852 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6853 IDirect3DDeviceImpl_7_GetDirect3D,
6854 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6855 IDirect3DDeviceImpl_7_GetRenderTarget,
6856 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6857 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6858 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6859 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6860 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6861 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6862 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6863 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6864 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6865 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6866 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6867 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6868 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6869 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6870 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6871 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6872 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6873 IDirect3DDeviceImpl_7_SetClipStatus,
6874 IDirect3DDeviceImpl_7_GetClipStatus,
6875 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6876 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6877 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6878 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6879 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6880 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6881 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6882 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6883 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6884 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6885 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6886 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6887 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6888 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6889 IDirect3DDeviceImpl_7_Load_FPUSetup,
6890 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6891 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6892 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6893 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6894 IDirect3DDeviceImpl_7_GetInfo
6897 const IDirect3DDevice7Vtbl IDirect3DDevice7_FPUPreserve_Vtbl =
6899 /*** IUnknown Methods ***/
6900 IDirect3DDeviceImpl_7_QueryInterface,
6901 IDirect3DDeviceImpl_7_AddRef,
6902 IDirect3DDeviceImpl_7_Release,
6903 /*** IDirect3DDevice7 ***/
6904 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6905 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6906 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6907 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6908 IDirect3DDeviceImpl_7_GetDirect3D,
6909 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6910 IDirect3DDeviceImpl_7_GetRenderTarget,
6911 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6912 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6913 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6914 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6915 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6916 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6917 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6918 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6919 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6920 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6921 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6922 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6923 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6924 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6925 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6926 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6927 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6928 IDirect3DDeviceImpl_7_SetClipStatus,
6929 IDirect3DDeviceImpl_7_GetClipStatus,
6930 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6931 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6932 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6933 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6934 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6935 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6936 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6937 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6938 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6939 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6940 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6941 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6942 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6943 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6944 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6945 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6946 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6947 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6948 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6949 IDirect3DDeviceImpl_7_GetInfo
6952 const IDirect3DDevice3Vtbl IDirect3DDevice3_Vtbl =
6954 /*** IUnknown Methods ***/
6955 Thunk_IDirect3DDeviceImpl_3_QueryInterface,
6956 Thunk_IDirect3DDeviceImpl_3_AddRef,
6957 Thunk_IDirect3DDeviceImpl_3_Release,
6958 /*** IDirect3DDevice3 ***/
6959 IDirect3DDeviceImpl_3_GetCaps,
6960 IDirect3DDeviceImpl_3_GetStats,
6961 IDirect3DDeviceImpl_3_AddViewport,
6962 IDirect3DDeviceImpl_3_DeleteViewport,
6963 IDirect3DDeviceImpl_3_NextViewport,
6964 Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
6965 Thunk_IDirect3DDeviceImpl_3_BeginScene,
6966 Thunk_IDirect3DDeviceImpl_3_EndScene,
6967 Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
6968 IDirect3DDeviceImpl_3_SetCurrentViewport,
6969 IDirect3DDeviceImpl_3_GetCurrentViewport,
6970 Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
6971 Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
6972 IDirect3DDeviceImpl_3_Begin,
6973 IDirect3DDeviceImpl_3_BeginIndexed,
6974 IDirect3DDeviceImpl_3_Vertex,
6975 IDirect3DDeviceImpl_3_Index,
6976 IDirect3DDeviceImpl_3_End,
6977 IDirect3DDeviceImpl_3_GetRenderState,
6978 IDirect3DDeviceImpl_3_SetRenderState,
6979 IDirect3DDeviceImpl_3_GetLightState,
6980 IDirect3DDeviceImpl_3_SetLightState,
6981 Thunk_IDirect3DDeviceImpl_3_SetTransform,
6982 Thunk_IDirect3DDeviceImpl_3_GetTransform,
6983 Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
6984 Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
6985 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6986 Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
6987 Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
6988 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6989 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6990 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6991 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6992 Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6993 Thunk_IDirect3DDeviceImpl_3_GetTexture,
6994 IDirect3DDeviceImpl_3_SetTexture,
6995 Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
6996 Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
6997 Thunk_IDirect3DDeviceImpl_3_ValidateDevice
7000 const IDirect3DDevice2Vtbl IDirect3DDevice2_Vtbl =
7002 /*** IUnknown Methods ***/
7003 Thunk_IDirect3DDeviceImpl_2_QueryInterface,
7004 Thunk_IDirect3DDeviceImpl_2_AddRef,
7005 Thunk_IDirect3DDeviceImpl_2_Release,
7006 /*** IDirect3DDevice2 ***/
7007 Thunk_IDirect3DDeviceImpl_2_GetCaps,
7008 IDirect3DDeviceImpl_2_SwapTextureHandles,
7009 Thunk_IDirect3DDeviceImpl_2_GetStats,
7010 Thunk_IDirect3DDeviceImpl_2_AddViewport,
7011 Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
7012 Thunk_IDirect3DDeviceImpl_2_NextViewport,
7013 IDirect3DDeviceImpl_2_EnumTextureFormats,
7014 Thunk_IDirect3DDeviceImpl_2_BeginScene,
7015 Thunk_IDirect3DDeviceImpl_2_EndScene,
7016 Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
7017 Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
7018 Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
7019 Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
7020 Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
7021 Thunk_IDirect3DDeviceImpl_2_Begin,
7022 Thunk_IDirect3DDeviceImpl_2_BeginIndexed,
7023 Thunk_IDirect3DDeviceImpl_2_Vertex,
7024 Thunk_IDirect3DDeviceImpl_2_Index,
7025 Thunk_IDirect3DDeviceImpl_2_End,
7026 Thunk_IDirect3DDeviceImpl_2_GetRenderState,
7027 Thunk_IDirect3DDeviceImpl_2_SetRenderState,
7028 Thunk_IDirect3DDeviceImpl_2_GetLightState,
7029 Thunk_IDirect3DDeviceImpl_2_SetLightState,
7030 Thunk_IDirect3DDeviceImpl_2_SetTransform,
7031 Thunk_IDirect3DDeviceImpl_2_GetTransform,
7032 Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
7033 Thunk_IDirect3DDeviceImpl_2_DrawPrimitive,
7034 Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
7035 Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
7036 Thunk_IDirect3DDeviceImpl_2_GetClipStatus
7039 const IDirect3DDeviceVtbl IDirect3DDevice1_Vtbl =
7041 /*** IUnknown Methods ***/
7042 Thunk_IDirect3DDeviceImpl_1_QueryInterface,
7043 Thunk_IDirect3DDeviceImpl_1_AddRef,
7044 Thunk_IDirect3DDeviceImpl_1_Release,
7045 /*** IDirect3DDevice1 ***/
7046 IDirect3DDeviceImpl_1_Initialize,
7047 Thunk_IDirect3DDeviceImpl_1_GetCaps,
7048 Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
7049 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
7050 Thunk_IDirect3DDeviceImpl_1_GetStats,
7051 IDirect3DDeviceImpl_1_Execute,
7052 Thunk_IDirect3DDeviceImpl_1_AddViewport,
7053 Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
7054 Thunk_IDirect3DDeviceImpl_1_NextViewport,
7055 IDirect3DDeviceImpl_1_Pick,
7056 IDirect3DDeviceImpl_1_GetPickRecords,
7057 Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
7058 IDirect3DDeviceImpl_1_CreateMatrix,
7059 IDirect3DDeviceImpl_1_SetMatrix,
7060 IDirect3DDeviceImpl_1_GetMatrix,
7061 IDirect3DDeviceImpl_1_DeleteMatrix,
7062 Thunk_IDirect3DDeviceImpl_1_BeginScene,
7063 Thunk_IDirect3DDeviceImpl_1_EndScene,
7064 Thunk_IDirect3DDeviceImpl_1_GetDirect3D
7067 /*****************************************************************************
7068 * IDirect3DDeviceImpl_CreateHandle
7070 * Not called from the VTable
7072 * Some older interface versions operate with handles, which are basically
7073 * DWORDs which identify an interface, for example
7074 * IDirect3DDevice::SetRenderState with DIRECT3DRENDERSTATE_TEXTUREHANDLE
7076 * Those handle could be just casts to the interface pointers or vice versa,
7077 * but that is not 64 bit safe and would mean blindly derefering a DWORD
7078 * passed by the app. Instead there is a dynamic array in the device which
7079 * keeps a DWORD to pointer information and a type for the handle.
7081 * Basically this array only grows, when a handle is freed its pointer is
7082 * just set to NULL. There will be much more reads from the array than
7083 * insertion operations, so a dynamic array is fine.
7085 * Params:
7086 * This: D3DDevice implementation for which this handle should be created
7088 * Returns:
7089 * A free handle on success
7090 * 0 on failure
7092 *****************************************************************************/
7093 DWORD
7094 IDirect3DDeviceImpl_CreateHandle(IDirect3DDeviceImpl *This)
7096 DWORD i;
7097 struct HandleEntry *oldHandles = This->Handles;
7099 TRACE("(%p)\n", This);
7101 for(i = 0; i < This->numHandles; i++)
7103 if(This->Handles[i].ptr == NULL &&
7104 This->Handles[i].type == DDrawHandle_Unknown)
7106 TRACE("Reusing freed handle %d\n", i + 1);
7107 return i + 1;
7111 TRACE("Growing the handle array\n");
7113 This->numHandles++;
7114 This->Handles = HeapAlloc(GetProcessHeap(), 0, sizeof(struct HandleEntry) * This->numHandles);
7115 if(!This->Handles)
7117 ERR("Out of memory\n");
7118 This->Handles = oldHandles;
7119 This->numHandles--;
7120 return 0;
7122 if(oldHandles)
7124 memcpy(This->Handles, oldHandles, (This->numHandles - 1) * sizeof(struct HandleEntry));
7125 HeapFree(GetProcessHeap(), 0, oldHandles);
7128 TRACE("Returning %d\n", This->numHandles);
7129 return This->numHandles;
7132 /*****************************************************************************
7133 * IDirect3DDeviceImpl_UpdateDepthStencil
7135 * Checks the current render target for attached depth stencils and sets the
7136 * WineD3D depth stencil accordingly.
7138 * Returns:
7139 * The depth stencil state to set if creating the device
7141 *****************************************************************************/
7142 WINED3DZBUFFERTYPE
7143 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
7145 IDirectDrawSurface7 *depthStencil = NULL;
7146 IDirectDrawSurfaceImpl *dsi;
7147 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
7149 IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(This->target, IDirectDrawSurface7),
7150 &depthcaps,
7151 &depthStencil);
7152 if(!depthStencil)
7154 TRACE("Setting wined3d depth stencil to NULL\n");
7155 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
7156 NULL);
7157 return WINED3DZB_FALSE;
7160 dsi = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, depthStencil);
7161 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->WineD3DSurface);
7162 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
7163 dsi->WineD3DSurface);
7165 IDirectDrawSurface7_Release(depthStencil);
7166 return WINED3DZB_TRUE;