push 9758e6fe7ae8fbab538c98c718d6619029bb3457
[wine/hacks.git] / dlls / ddraw / device.c
blob6a3ecfcffaeef2872211ac96ebb79c28ef3692ec
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 if(hr == D3D_OK)
1216 DDPIXELFORMAT pformat;
1218 memset(&pformat, 0, sizeof(pformat));
1219 pformat.dwSize = sizeof(pformat);
1220 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1222 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1223 hr = Callback(&pformat, Arg);
1224 if(hr != DDENUMRET_OK)
1226 TRACE("Format enumeration cancelled by application\n");
1227 LeaveCriticalSection(&ddraw_cs);
1228 return D3D_OK;
1233 for(i = 0; i < sizeof(BumpFormatList) / sizeof(WINED3DFORMAT); i++)
1235 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1236 0 /* Adapter */,
1237 0 /* DeviceType */,
1238 0 /* AdapterFormat */,
1239 WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1240 0 /* ResourceType */,
1241 BumpFormatList[i]);
1242 if(hr == D3D_OK)
1244 DDPIXELFORMAT pformat;
1246 memset(&pformat, 0, sizeof(pformat));
1247 pformat.dwSize = sizeof(pformat);
1248 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1250 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1251 hr = Callback(&pformat, Arg);
1252 if(hr != DDENUMRET_OK)
1254 TRACE("Format enumeration cancelled by application\n");
1255 LeaveCriticalSection(&ddraw_cs);
1256 return D3D_OK;
1260 TRACE("End of enumeration\n");
1261 LeaveCriticalSection(&ddraw_cs);
1262 return D3D_OK;
1265 static HRESULT WINAPI
1266 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1267 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1268 void *Arg)
1270 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1273 static HRESULT WINAPI
1274 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1275 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1276 void *Arg)
1278 HRESULT hr;
1279 WORD old_fpucw;
1281 old_fpucw = d3d_fpu_setup();
1282 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1283 set_fpu_control_word(old_fpucw);
1285 return hr;
1288 static HRESULT WINAPI
1289 Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1290 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1291 void *Arg)
1293 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1294 TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice7 interface.\n", This, Callback, Arg);
1295 return IDirect3DDevice7_EnumTextureFormats(ICOM_INTERFACE(This, IDirect3DDevice7),
1296 Callback,
1297 Arg);
1300 /*****************************************************************************
1301 * IDirect3DDevice2::EnumTextureformats
1303 * EnumTextureFormats for Version 1 and 2, see
1304 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1306 * This version has a different callback and does not enumerate FourCC
1307 * formats
1309 *****************************************************************************/
1310 static HRESULT WINAPI
1311 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1312 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1313 void *Arg)
1315 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1316 HRESULT hr;
1317 int i;
1319 WINED3DFORMAT FormatList[] = {
1320 /* 32 bit */
1321 WINED3DFMT_A8R8G8B8,
1322 WINED3DFMT_X8R8G8B8,
1323 /* 24 bit */
1324 WINED3DFMT_R8G8B8,
1325 /* 16 Bit */
1326 WINED3DFMT_A1R5G5B5,
1327 WINED3DFMT_A4R4G4B4,
1328 WINED3DFMT_R5G6B5,
1329 WINED3DFMT_X1R5G5B5,
1330 /* 8 Bit */
1331 WINED3DFMT_R3G3B2,
1332 WINED3DFMT_P8,
1333 /* FOURCC codes - Not in this version*/
1336 TRACE("(%p)->(%p,%p): Relay\n", This, Callback, Arg);
1338 if(!Callback)
1339 return DDERR_INVALIDPARAMS;
1341 EnterCriticalSection(&ddraw_cs);
1342 for(i = 0; i < sizeof(FormatList) / sizeof(WINED3DFORMAT); i++)
1344 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1345 0 /* Adapter */,
1346 0 /* DeviceType */,
1347 0 /* AdapterFormat */,
1348 0 /* Usage */,
1349 0 /* ResourceType */,
1350 FormatList[i]);
1351 if(hr == D3D_OK)
1353 DDSURFACEDESC sdesc;
1355 memset(&sdesc, 0, sizeof(sdesc));
1356 sdesc.dwSize = sizeof(sdesc);
1357 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1358 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1359 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1360 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1362 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1363 hr = Callback(&sdesc, Arg);
1364 if(hr != DDENUMRET_OK)
1366 TRACE("Format enumeration cancelled by application\n");
1367 LeaveCriticalSection(&ddraw_cs);
1368 return D3D_OK;
1372 TRACE("End of enumeration\n");
1373 LeaveCriticalSection(&ddraw_cs);
1374 return D3D_OK;
1377 static HRESULT WINAPI
1378 Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1379 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1380 void *Arg)
1382 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1383 TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice2 interface.\n", This, Callback, Arg);
1384 return IDirect3DDevice2_EnumTextureFormats(ICOM_INTERFACE(This, IDirect3DDevice2),
1385 Callback,
1386 Arg);
1389 /*****************************************************************************
1390 * IDirect3DDevice::CreateMatrix
1392 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1393 * allocated for the handle.
1395 * Version 1 only
1397 * Params
1398 * D3DMatHandle: Address to return the handle at
1400 * Returns:
1401 * D3D_OK on success
1402 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1404 *****************************************************************************/
1405 static HRESULT WINAPI
1406 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1408 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1409 D3DMATRIX *Matrix;
1410 TRACE("(%p)->(%p)\n", This, D3DMatHandle);
1412 if(!D3DMatHandle)
1413 return DDERR_INVALIDPARAMS;
1415 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1416 if(!Matrix)
1418 ERR("Out of memory when allocating a D3DMATRIX\n");
1419 return DDERR_OUTOFMEMORY;
1422 EnterCriticalSection(&ddraw_cs);
1423 *D3DMatHandle = IDirect3DDeviceImpl_CreateHandle(This);
1424 if(!(*D3DMatHandle))
1426 ERR("Failed to create a matrix handle\n");
1427 HeapFree(GetProcessHeap(), 0, Matrix);
1428 LeaveCriticalSection(&ddraw_cs);
1429 return DDERR_OUTOFMEMORY;
1431 This->Handles[*D3DMatHandle - 1].ptr = Matrix;
1432 This->Handles[*D3DMatHandle - 1].type = DDrawHandle_Matrix;
1433 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1435 LeaveCriticalSection(&ddraw_cs);
1436 return D3D_OK;
1439 /*****************************************************************************
1440 * IDirect3DDevice::SetMatrix
1442 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1443 * allocated for the handle
1445 * Version 1 only
1447 * Params:
1448 * D3DMatHandle: Handle to set the matrix to
1449 * D3DMatrix: Matrix to set
1451 * Returns:
1452 * D3D_OK on success
1453 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1454 * to set is NULL
1456 *****************************************************************************/
1457 static HRESULT WINAPI
1458 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1459 D3DMATRIXHANDLE D3DMatHandle,
1460 D3DMATRIX *D3DMatrix)
1462 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1463 TRACE("(%p)->(%08x,%p)\n", This, D3DMatHandle, D3DMatrix);
1465 if( (!D3DMatHandle) || (!D3DMatrix) )
1466 return DDERR_INVALIDPARAMS;
1468 EnterCriticalSection(&ddraw_cs);
1469 if(D3DMatHandle > This->numHandles)
1471 ERR("Handle %d out of range\n", D3DMatHandle);
1472 LeaveCriticalSection(&ddraw_cs);
1473 return DDERR_INVALIDPARAMS;
1475 else if(This->Handles[D3DMatHandle - 1].type != DDrawHandle_Matrix)
1477 ERR("Handle %d is not a matrix handle\n", D3DMatHandle);
1478 LeaveCriticalSection(&ddraw_cs);
1479 return DDERR_INVALIDPARAMS;
1482 if (TRACE_ON(d3d7))
1483 dump_D3DMATRIX(D3DMatrix);
1485 *((D3DMATRIX *) This->Handles[D3DMatHandle - 1].ptr) = *D3DMatrix;
1487 if(This->world == D3DMatHandle)
1489 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1490 WINED3DTS_WORLDMATRIX(0),
1491 (WINED3DMATRIX *) D3DMatrix);
1493 if(This->view == D3DMatHandle)
1495 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1496 WINED3DTS_VIEW,
1497 (WINED3DMATRIX *) D3DMatrix);
1499 if(This->proj == D3DMatHandle)
1501 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1502 WINED3DTS_PROJECTION,
1503 (WINED3DMATRIX *) D3DMatrix);
1506 LeaveCriticalSection(&ddraw_cs);
1507 return D3D_OK;
1510 /*****************************************************************************
1511 * IDirect3DDevice::SetMatrix
1513 * Returns the content of a D3DMATRIX handle
1515 * Version 1 only
1517 * Params:
1518 * D3DMatHandle: Matrix handle to read the content from
1519 * D3DMatrix: Address to store the content at
1521 * Returns:
1522 * D3D_OK on success
1523 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1525 *****************************************************************************/
1526 static HRESULT WINAPI
1527 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1528 D3DMATRIXHANDLE D3DMatHandle,
1529 D3DMATRIX *D3DMatrix)
1531 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1532 TRACE("(%p)->(%08x,%p)\n", This, D3DMatHandle, D3DMatrix);
1534 if(!D3DMatrix)
1535 return DDERR_INVALIDPARAMS;
1536 if(!D3DMatHandle)
1537 return DDERR_INVALIDPARAMS;
1539 EnterCriticalSection(&ddraw_cs);
1540 if(D3DMatHandle > This->numHandles)
1542 ERR("Handle %d out of range\n", D3DMatHandle);
1543 LeaveCriticalSection(&ddraw_cs);
1544 return DDERR_INVALIDPARAMS;
1546 else if(This->Handles[D3DMatHandle - 1].type != DDrawHandle_Matrix)
1548 ERR("Handle %d is not a matrix handle\n", D3DMatHandle);
1549 LeaveCriticalSection(&ddraw_cs);
1550 return DDERR_INVALIDPARAMS;
1553 /* The handle is simply a pointer to a D3DMATRIX structure */
1554 *D3DMatrix = *((D3DMATRIX *) This->Handles[D3DMatHandle - 1].ptr);
1556 LeaveCriticalSection(&ddraw_cs);
1557 return D3D_OK;
1560 /*****************************************************************************
1561 * IDirect3DDevice::DeleteMatrix
1563 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1565 * Version 1 only
1567 * Params:
1568 * D3DMatHandle: Handle to destroy
1570 * Returns:
1571 * D3D_OK on success
1572 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1574 *****************************************************************************/
1575 static HRESULT WINAPI
1576 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1577 D3DMATRIXHANDLE D3DMatHandle)
1579 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1580 TRACE("(%p)->(%08x)\n", This, D3DMatHandle);
1582 if(!D3DMatHandle)
1583 return DDERR_INVALIDPARAMS;
1585 EnterCriticalSection(&ddraw_cs);
1586 if(D3DMatHandle > This->numHandles)
1588 ERR("Handle %d out of range\n", D3DMatHandle);
1589 LeaveCriticalSection(&ddraw_cs);
1590 return DDERR_INVALIDPARAMS;
1592 else if(This->Handles[D3DMatHandle - 1].type != DDrawHandle_Matrix)
1594 ERR("Handle %d is not a matrix handle\n", D3DMatHandle);
1595 LeaveCriticalSection(&ddraw_cs);
1596 return DDERR_INVALIDPARAMS;
1599 HeapFree(GetProcessHeap(), 0, This->Handles[D3DMatHandle - 1].ptr);
1600 This->Handles[D3DMatHandle - 1].ptr = NULL;
1601 This->Handles[D3DMatHandle - 1].type = DDrawHandle_Unknown;
1603 LeaveCriticalSection(&ddraw_cs);
1604 return D3D_OK;
1607 /*****************************************************************************
1608 * IDirect3DDevice7::BeginScene
1610 * This method must be called before any rendering is performed.
1611 * IDirect3DDevice::EndScene has to be called after the scene is complete
1613 * Version 1, 2, 3 and 7
1615 * Returns:
1616 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1617 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1618 * started scene).
1620 *****************************************************************************/
1621 static HRESULT
1622 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1624 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1625 HRESULT hr;
1626 TRACE("(%p): Relay\n", This);
1628 EnterCriticalSection(&ddraw_cs);
1629 hr = IWineD3DDevice_BeginScene(This->wineD3DDevice);
1630 LeaveCriticalSection(&ddraw_cs);
1631 if(hr == WINED3D_OK) return D3D_OK;
1632 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1635 static HRESULT WINAPI
1636 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1638 return IDirect3DDeviceImpl_7_BeginScene(iface);
1641 static HRESULT WINAPI
1642 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1644 HRESULT hr;
1645 WORD old_fpucw;
1647 old_fpucw = d3d_fpu_setup();
1648 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1649 set_fpu_control_word(old_fpucw);
1651 return hr;
1654 static HRESULT WINAPI
1655 Thunk_IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1657 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1658 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1659 return IDirect3DDevice7_BeginScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1662 static HRESULT WINAPI
1663 Thunk_IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1665 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1666 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1667 return IDirect3DDevice7_BeginScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1670 static HRESULT WINAPI
1671 Thunk_IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1673 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1674 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1675 return IDirect3DDevice7_BeginScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1678 /*****************************************************************************
1679 * IDirect3DDevice7::EndScene
1681 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1682 * This method must be called after rendering is finished.
1684 * Version 1, 2, 3 and 7
1686 * Returns:
1687 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1688 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1689 * that only if the scene was already ended.
1691 *****************************************************************************/
1692 static HRESULT
1693 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1695 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1696 HRESULT hr;
1697 TRACE("(%p): Relay\n", This);
1699 EnterCriticalSection(&ddraw_cs);
1700 hr = IWineD3DDevice_EndScene(This->wineD3DDevice);
1701 LeaveCriticalSection(&ddraw_cs);
1702 if(hr == WINED3D_OK) return D3D_OK;
1703 else return D3DERR_SCENE_NOT_IN_SCENE;
1706 static HRESULT WINAPI
1707 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1709 return IDirect3DDeviceImpl_7_EndScene(iface);
1712 static HRESULT WINAPI
1713 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1715 HRESULT hr;
1716 WORD old_fpucw;
1718 old_fpucw = d3d_fpu_setup();
1719 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1720 set_fpu_control_word(old_fpucw);
1722 return hr;
1725 static HRESULT WINAPI
1726 Thunk_IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1728 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1729 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1730 return IDirect3DDevice7_EndScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1733 static HRESULT WINAPI
1734 Thunk_IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1736 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1737 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1738 return IDirect3DDevice7_EndScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1741 static HRESULT WINAPI
1742 Thunk_IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1744 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1745 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1746 return IDirect3DDevice7_EndScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1749 /*****************************************************************************
1750 * IDirect3DDevice7::GetDirect3D
1752 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1753 * this device.
1755 * Params:
1756 * Direct3D7: Address to store the interface pointer at
1758 * Returns:
1759 * D3D_OK on success
1760 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1762 *****************************************************************************/
1763 static HRESULT WINAPI
1764 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1765 IDirect3D7 **Direct3D7)
1767 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1768 TRACE("(%p)->(%p)\n", This, Direct3D7);
1770 if(!Direct3D7)
1771 return DDERR_INVALIDPARAMS;
1773 *Direct3D7 = ICOM_INTERFACE(This->ddraw, IDirect3D7);
1774 IDirect3D7_AddRef(*Direct3D7);
1776 TRACE(" returning interface %p\n", *Direct3D7);
1777 return D3D_OK;
1780 static HRESULT WINAPI
1781 Thunk_IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1782 IDirect3D3 **Direct3D3)
1784 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1785 HRESULT ret;
1786 IDirect3D7 *ret_ptr;
1788 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Direct3D3);
1789 ret = IDirect3DDevice7_GetDirect3D(ICOM_INTERFACE(This, IDirect3DDevice7),
1790 &ret_ptr);
1791 if(ret != D3D_OK)
1792 return ret;
1793 *Direct3D3 = COM_INTERFACE_CAST(IDirectDrawImpl, IDirect3D7, IDirect3D3, ret_ptr);
1794 TRACE(" returning interface %p\n", *Direct3D3);
1795 return D3D_OK;
1798 static HRESULT WINAPI
1799 Thunk_IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1800 IDirect3D2 **Direct3D2)
1802 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1803 HRESULT ret;
1804 IDirect3D7 *ret_ptr;
1806 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Direct3D2);
1807 ret = IDirect3DDevice7_GetDirect3D(ICOM_INTERFACE(This, IDirect3DDevice7),
1808 &ret_ptr);
1809 if(ret != D3D_OK)
1810 return ret;
1811 *Direct3D2 = COM_INTERFACE_CAST(IDirectDrawImpl, IDirect3D7, IDirect3D2, ret_ptr);
1812 TRACE(" returning interface %p\n", *Direct3D2);
1813 return D3D_OK;
1816 static HRESULT WINAPI
1817 Thunk_IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1818 IDirect3D **Direct3D)
1820 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1821 HRESULT ret;
1822 IDirect3D7 *ret_ptr;
1824 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Direct3D);
1825 ret = IDirect3DDevice7_GetDirect3D(ICOM_INTERFACE(This, IDirect3DDevice7),
1826 &ret_ptr);
1827 if(ret != D3D_OK)
1828 return ret;
1829 *Direct3D = COM_INTERFACE_CAST(IDirectDrawImpl, IDirect3D7, IDirect3D, ret_ptr);
1830 TRACE(" returning interface %p\n", *Direct3D);
1831 return D3D_OK;
1834 /*****************************************************************************
1835 * IDirect3DDevice3::SetCurrentViewport
1837 * Sets a Direct3DViewport as the current viewport.
1838 * For the thunks note that all viewport interface versions are equal
1840 * Params:
1841 * Direct3DViewport3: The viewport to set
1843 * Version 2 and 3
1845 * Returns:
1846 * D3D_OK on success
1847 * (Is a NULL viewport valid?)
1849 *****************************************************************************/
1850 static HRESULT WINAPI
1851 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1852 IDirect3DViewport3 *Direct3DViewport3)
1854 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1855 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Direct3DViewport3);
1856 TRACE("(%p)->(%p)\n", This, Direct3DViewport3);
1858 EnterCriticalSection(&ddraw_cs);
1859 /* Do nothing if the specified viewport is the same as the current one */
1860 if (This->current_viewport == vp )
1862 LeaveCriticalSection(&ddraw_cs);
1863 return D3D_OK;
1866 /* Should check if the viewport was added or not */
1868 /* Release previous viewport and AddRef the new one */
1869 if (This->current_viewport)
1871 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport, ICOM_INTERFACE(This->current_viewport, IDirect3DViewport3));
1872 IDirect3DViewport3_Release( ICOM_INTERFACE(This->current_viewport, IDirect3DViewport3) );
1874 IDirect3DViewport3_AddRef(Direct3DViewport3);
1876 /* Set this viewport as the current viewport */
1877 This->current_viewport = vp;
1879 /* Activate this viewport */
1880 This->current_viewport->active_device = This;
1881 This->current_viewport->activate(This->current_viewport, FALSE);
1883 LeaveCriticalSection(&ddraw_cs);
1884 return D3D_OK;
1887 static HRESULT WINAPI
1888 Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1889 IDirect3DViewport2 *Direct3DViewport2)
1891 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1892 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Direct3DViewport2);
1893 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
1894 return IDirect3DDevice3_SetCurrentViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
1895 ICOM_INTERFACE(vp, IDirect3DViewport3));
1898 /*****************************************************************************
1899 * IDirect3DDevice3::GetCurrentViewport
1901 * Returns the currently active viewport.
1903 * Version 2 and 3
1905 * Params:
1906 * Direct3DViewport3: Address to return the interface pointer at
1908 * Returns:
1909 * D3D_OK on success
1910 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1912 *****************************************************************************/
1913 static HRESULT WINAPI
1914 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1915 IDirect3DViewport3 **Direct3DViewport3)
1917 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1918 TRACE("(%p)->(%p)\n", This, Direct3DViewport3);
1920 if(!Direct3DViewport3)
1921 return DDERR_INVALIDPARAMS;
1923 EnterCriticalSection(&ddraw_cs);
1924 *Direct3DViewport3 = ICOM_INTERFACE(This->current_viewport, IDirect3DViewport3);
1926 /* AddRef the returned viewport */
1927 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1929 TRACE(" returning interface %p\n", *Direct3DViewport3);
1931 LeaveCriticalSection(&ddraw_cs);
1932 return D3D_OK;
1935 static HRESULT WINAPI
1936 Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1937 IDirect3DViewport2 **Direct3DViewport2)
1939 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1940 HRESULT hr;
1941 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, Direct3DViewport2);
1942 hr = IDirect3DDevice3_GetCurrentViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
1943 (IDirect3DViewport3 **) Direct3DViewport2);
1944 if(hr != D3D_OK) return hr;
1945 *Direct3DViewport2 = (IDirect3DViewport2 *) COM_INTERFACE_CAST(IDirect3DViewportImpl, IDirect3DViewport3, IDirect3DViewport3, *Direct3DViewport2);
1946 return D3D_OK;
1949 /*****************************************************************************
1950 * IDirect3DDevice7::SetRenderTarget
1952 * Sets the render target for the Direct3DDevice.
1953 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1954 * IDirectDrawSurface3 == IDirectDrawSurface
1956 * Version 2, 3 and 7
1958 * Params:
1959 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1960 * render target
1961 * Flags: Some flags
1963 * Returns:
1964 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1966 *****************************************************************************/
1967 static HRESULT
1968 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1969 IDirectDrawSurface7 *NewTarget,
1970 DWORD Flags)
1972 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1973 IDirectDrawSurfaceImpl *Target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, NewTarget);
1974 HRESULT hr;
1975 TRACE("(%p)->(%p,%08x): Relay\n", This, NewTarget, Flags);
1977 EnterCriticalSection(&ddraw_cs);
1978 /* Flags: Not used */
1980 if(This->target == Target)
1982 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1983 LeaveCriticalSection(&ddraw_cs);
1984 return D3D_OK;
1987 hr = IWineD3DDevice_SetRenderTarget(This->wineD3DDevice,
1989 Target ? Target->WineD3DSurface : NULL);
1990 if(hr != D3D_OK)
1992 LeaveCriticalSection(&ddraw_cs);
1993 return hr;
1995 IDirectDrawSurface7_AddRef(NewTarget);
1996 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->target, IDirectDrawSurface7));
1997 This->target = Target;
1998 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1999 LeaveCriticalSection(&ddraw_cs);
2000 return D3D_OK;
2003 static HRESULT WINAPI
2004 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
2005 IDirectDrawSurface7 *NewTarget,
2006 DWORD Flags)
2008 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
2011 static HRESULT WINAPI
2012 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
2013 IDirectDrawSurface7 *NewTarget,
2014 DWORD Flags)
2016 HRESULT hr;
2017 WORD old_fpucw;
2019 old_fpucw = d3d_fpu_setup();
2020 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
2021 set_fpu_control_word(old_fpucw);
2023 return hr;
2026 static HRESULT WINAPI
2027 Thunk_IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
2028 IDirectDrawSurface4 *NewRenderTarget,
2029 DWORD Flags)
2031 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2032 IDirectDrawSurfaceImpl *Target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, NewRenderTarget);
2033 TRACE_(ddraw_thunk)("(%p)->(%p,%08x) thunking to IDirect3DDevice7 interface.\n", This, Target, Flags);
2034 return IDirect3DDevice7_SetRenderTarget(ICOM_INTERFACE(This, IDirect3DDevice7),
2035 ICOM_INTERFACE(Target, IDirectDrawSurface7),
2036 Flags);
2039 static HRESULT WINAPI
2040 Thunk_IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
2041 IDirectDrawSurface *NewRenderTarget,
2042 DWORD Flags)
2044 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2045 IDirectDrawSurfaceImpl *Target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface3, NewRenderTarget);
2046 TRACE_(ddraw_thunk)("(%p)->(%p,%08x) thunking to IDirect3DDevice7 interface.\n", This, Target, Flags);
2047 return IDirect3DDevice7_SetRenderTarget(ICOM_INTERFACE(This, IDirect3DDevice7),
2048 ICOM_INTERFACE(Target, IDirectDrawSurface7),
2049 Flags);
2052 /*****************************************************************************
2053 * IDirect3DDevice7::GetRenderTarget
2055 * Returns the current render target.
2056 * This is handled locally, because the WineD3D render target's parent
2057 * is an IParent
2059 * Version 2, 3 and 7
2061 * Params:
2062 * RenderTarget: Address to store the surface interface pointer
2064 * Returns:
2065 * D3D_OK on success
2066 * DDERR_INVALIDPARAMS if RenderTarget == NULL
2068 *****************************************************************************/
2069 static HRESULT WINAPI
2070 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
2071 IDirectDrawSurface7 **RenderTarget)
2073 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2074 TRACE("(%p)->(%p): Relay\n", This, RenderTarget);
2076 if(!RenderTarget)
2077 return DDERR_INVALIDPARAMS;
2079 EnterCriticalSection(&ddraw_cs);
2080 *RenderTarget = ICOM_INTERFACE(This->target, IDirectDrawSurface7);
2081 IDirectDrawSurface7_AddRef(*RenderTarget);
2083 LeaveCriticalSection(&ddraw_cs);
2084 return D3D_OK;
2087 static HRESULT WINAPI
2088 Thunk_IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
2089 IDirectDrawSurface4 **RenderTarget)
2091 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2092 HRESULT hr;
2093 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, RenderTarget);
2094 hr = IDirect3DDevice7_GetRenderTarget(ICOM_INTERFACE(This, IDirect3DDevice7),
2095 (IDirectDrawSurface7 **) RenderTarget);
2096 if(hr != D3D_OK) return hr;
2097 *RenderTarget = (IDirectDrawSurface4 *) COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirectDrawSurface7, IDirectDrawSurface7, *RenderTarget);
2098 return D3D_OK;
2101 static HRESULT WINAPI
2102 Thunk_IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
2103 IDirectDrawSurface **RenderTarget)
2105 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2106 HRESULT hr;
2107 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, RenderTarget);
2108 hr = IDirect3DDevice7_GetRenderTarget(ICOM_INTERFACE(This, IDirect3DDevice7),
2109 (IDirectDrawSurface7 **) RenderTarget);
2110 if(hr != D3D_OK) return hr;
2111 *RenderTarget = (IDirectDrawSurface *) COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirectDrawSurface7, IDirectDrawSurface3, *RenderTarget);
2112 return D3D_OK;
2115 /*****************************************************************************
2116 * IDirect3DDevice3::Begin
2118 * Begins a description block of vertices. This is similar to glBegin()
2119 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2120 * described with IDirect3DDevice::Vertex are drawn.
2122 * Version 2 and 3
2124 * Params:
2125 * PrimitiveType: The type of primitives to draw
2126 * VertexTypeDesc: A flexible vertex format description of the vertices
2127 * Flags: Some flags..
2129 * Returns:
2130 * D3D_OK on success
2132 *****************************************************************************/
2133 static HRESULT WINAPI
2134 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2135 D3DPRIMITIVETYPE PrimitiveType,
2136 DWORD VertexTypeDesc,
2137 DWORD Flags)
2139 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2140 TRACE("(%p)->(%d,%d,%08x)\n", This, PrimitiveType, VertexTypeDesc, Flags);
2142 EnterCriticalSection(&ddraw_cs);
2143 This->primitive_type = PrimitiveType;
2144 This->vertex_type = VertexTypeDesc;
2145 This->render_flags = Flags;
2146 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2147 This->nb_vertices = 0;
2148 LeaveCriticalSection(&ddraw_cs);
2150 return D3D_OK;
2153 static HRESULT WINAPI
2154 Thunk_IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface,
2155 D3DPRIMITIVETYPE d3dpt,
2156 D3DVERTEXTYPE dwVertexTypeDesc,
2157 DWORD dwFlags)
2159 DWORD FVF;
2160 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2161 TRACE_(ddraw_thunk)("(%p/%p)->(%08x,%08x,%08x): Thunking to IDirect3DDevice3\n", This, iface, d3dpt, dwVertexTypeDesc, dwFlags);
2163 switch(dwVertexTypeDesc)
2165 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2166 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2167 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2168 default:
2169 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2170 return DDERR_INVALIDPARAMS; /* Should never happen */
2173 return IDirect3DDevice3_Begin(ICOM_INTERFACE(This, IDirect3DDevice3),
2174 d3dpt,
2175 FVF,
2176 dwFlags);
2179 /*****************************************************************************
2180 * IDirect3DDevice3::BeginIndexed
2182 * Draws primitives based on vertices in a vertex array which are specified
2183 * by indices.
2185 * Version 2 and 3
2187 * Params:
2188 * PrimitiveType: Primitive type to draw
2189 * VertexType: A FVF description of the vertex format
2190 * Vertices: pointer to an array containing the vertices
2191 * NumVertices: The number of vertices in the vertex array
2192 * Flags: Some flags ...
2194 * Returns:
2195 * D3D_OK, because it's a stub
2197 *****************************************************************************/
2198 static HRESULT WINAPI
2199 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2200 D3DPRIMITIVETYPE PrimitiveType,
2201 DWORD VertexType,
2202 void *Vertices,
2203 DWORD NumVertices,
2204 DWORD Flags)
2206 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2207 FIXME("(%p)->(%08x,%08x,%p,%08x,%08x): stub!\n", This, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2208 return D3D_OK;
2212 static HRESULT WINAPI
2213 Thunk_IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2214 D3DPRIMITIVETYPE d3dptPrimitiveType,
2215 D3DVERTEXTYPE d3dvtVertexType,
2216 void *lpvVertices,
2217 DWORD dwNumVertices,
2218 DWORD dwFlags)
2220 DWORD FVF;
2221 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2222 TRACE_(ddraw_thunk)("(%p/%p)->(%08x,%08x,%p,%08x,%08x): Thunking to IDirect3DDevice3\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2224 switch(d3dvtVertexType)
2226 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2227 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2228 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2229 default:
2230 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2231 return DDERR_INVALIDPARAMS; /* Should never happen */
2234 return IDirect3DDevice3_BeginIndexed(ICOM_INTERFACE(This,IDirect3DDevice3),
2235 d3dptPrimitiveType,
2236 FVF,
2237 lpvVertices,
2238 dwNumVertices,
2239 dwFlags);
2242 /*****************************************************************************
2243 * IDirect3DDevice3::Vertex
2245 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2246 * drawn vertices in a vertex buffer. If the buffer is too small, its
2247 * size is increased.
2249 * Version 2 and 3
2251 * Params:
2252 * Vertex: Pointer to the vertex
2254 * Returns:
2255 * D3D_OK, on success
2256 * DDERR_INVALIDPARAMS if Vertex is NULL
2258 *****************************************************************************/
2259 static HRESULT WINAPI
2260 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2261 void *Vertex)
2263 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2264 TRACE("(%p)->(%p)\n", This, Vertex);
2266 if(!Vertex)
2267 return DDERR_INVALIDPARAMS;
2269 EnterCriticalSection(&ddraw_cs);
2270 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2272 BYTE *old_buffer;
2273 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2274 old_buffer = This->vertex_buffer;
2275 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2276 if (old_buffer)
2278 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2279 HeapFree(GetProcessHeap(), 0, old_buffer);
2283 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2285 LeaveCriticalSection(&ddraw_cs);
2286 return D3D_OK;
2289 static HRESULT WINAPI
2290 Thunk_IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface,
2291 void *lpVertexType)
2293 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2294 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, lpVertexType);
2295 return IDirect3DDevice3_Vertex(ICOM_INTERFACE(This, IDirect3DDevice3),
2296 lpVertexType);
2299 /*****************************************************************************
2300 * IDirect3DDevice3::Index
2302 * Specifies an index to a vertex to be drawn. The vertex array has to
2303 * be specified with BeginIndexed first.
2305 * Parameters:
2306 * VertexIndex: The index of the vertex to draw
2308 * Returns:
2309 * D3D_OK because it's a stub
2311 *****************************************************************************/
2312 static HRESULT WINAPI
2313 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2314 WORD VertexIndex)
2316 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2317 FIXME("(%p)->(%04x): stub!\n", This, VertexIndex);
2318 return D3D_OK;
2321 static HRESULT WINAPI
2322 Thunk_IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface,
2323 WORD wVertexIndex)
2325 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2326 TRACE_(ddraw_thunk)("(%p)->(%04x) thunking to IDirect3DDevice3 interface.\n", This, wVertexIndex);
2327 return IDirect3DDevice3_Index(ICOM_INTERFACE(This, IDirect3DDevice3),
2328 wVertexIndex);
2331 /*****************************************************************************
2332 * IDirect3DDevice3::End
2334 * Ends a draw begun with IDirect3DDevice3::Begin or
2335 * IDirect3DDevice::BeginIndexed. The vertices specified with
2336 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2337 * the IDirect3DDevice7::DrawPrimitive method. So far only
2338 * non-indexed mode is supported
2340 * Version 2 and 3
2342 * Params:
2343 * Flags: Some flags, as usual. Don't know which are defined
2345 * Returns:
2346 * The return value of IDirect3DDevice7::DrawPrimitive
2348 *****************************************************************************/
2349 static HRESULT WINAPI
2350 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2351 DWORD Flags)
2353 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2354 TRACE("(%p)->(%08x)\n", This, Flags);
2356 return IDirect3DDevice7_DrawPrimitive(ICOM_INTERFACE(This, IDirect3DDevice7),
2357 This->primitive_type, This->vertex_type,
2358 This->vertex_buffer, This->nb_vertices,
2359 This->render_flags);
2362 static HRESULT WINAPI
2363 Thunk_IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface,
2364 DWORD dwFlags)
2366 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2367 TRACE_(ddraw_thunk)("(%p)->(%08x) thunking to IDirect3DDevice3 interface.\n", This, dwFlags);
2368 return IDirect3DDevice3_End(ICOM_INTERFACE(This, IDirect3DDevice3),
2369 dwFlags);
2372 /*****************************************************************************
2373 * IDirect3DDevice7::GetRenderState
2375 * Returns the value of a render state. The possible render states are
2376 * defined in include/d3dtypes.h
2378 * Version 2, 3 and 7
2380 * Params:
2381 * RenderStateType: Render state to return the current setting of
2382 * Value: Address to store the value at
2384 * Returns:
2385 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2386 * DDERR_INVALIDPARAMS if Value == NULL
2388 *****************************************************************************/
2389 static HRESULT
2390 IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2391 D3DRENDERSTATETYPE RenderStateType,
2392 DWORD *Value)
2394 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2395 HRESULT hr;
2396 TRACE("(%p)->(%08x,%p): Relay\n", This, RenderStateType, Value);
2398 if(!Value)
2399 return DDERR_INVALIDPARAMS;
2401 EnterCriticalSection(&ddraw_cs);
2402 switch(RenderStateType)
2404 case D3DRENDERSTATE_TEXTUREMAG:
2406 WINED3DTEXTUREFILTERTYPE tex_mag;
2408 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2409 0, WINED3DSAMP_MAGFILTER,
2410 &tex_mag);
2412 switch (tex_mag)
2414 case WINED3DTEXF_POINT:
2415 *Value = D3DFILTER_NEAREST;
2416 break;
2417 case WINED3DTEXF_LINEAR:
2418 *Value = D3DFILTER_LINEAR;
2419 break;
2420 default:
2421 ERR("Unhandled texture mag %d !\n",tex_mag);
2422 *Value = 0;
2424 break;
2427 case D3DRENDERSTATE_TEXTUREMIN:
2429 WINED3DTEXTUREFILTERTYPE tex_min;
2431 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2432 0, WINED3DSAMP_MINFILTER,
2433 &tex_min);
2435 switch (tex_min)
2437 case WINED3DTEXF_POINT:
2438 *Value = D3DFILTER_NEAREST;
2439 break;
2440 case WINED3DTEXF_LINEAR:
2441 *Value = D3DFILTER_LINEAR;
2442 break;
2443 default:
2444 ERR("Unhandled texture mag %d !\n",tex_min);
2445 *Value = 0;
2447 break;
2450 case D3DRENDERSTATE_TEXTUREADDRESS:
2451 case D3DRENDERSTATE_TEXTUREADDRESSU:
2452 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2453 0, WINED3DSAMP_ADDRESSU,
2454 Value);
2455 break;
2456 case D3DRENDERSTATE_TEXTUREADDRESSV:
2457 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2458 0, WINED3DSAMP_ADDRESSV,
2459 Value);
2460 break;
2462 default:
2463 /* FIXME: Unhandled: D3DRENDERSTATE_STIPPLEPATTERN00 - 31 */
2464 hr = IWineD3DDevice_GetRenderState(This->wineD3DDevice,
2465 RenderStateType,
2466 Value);
2468 LeaveCriticalSection(&ddraw_cs);
2469 return hr;
2472 static HRESULT WINAPI
2473 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2474 D3DRENDERSTATETYPE RenderStateType,
2475 DWORD *Value)
2477 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2480 static HRESULT WINAPI
2481 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2482 D3DRENDERSTATETYPE RenderStateType,
2483 DWORD *Value)
2485 HRESULT hr;
2486 WORD old_fpucw;
2488 old_fpucw = d3d_fpu_setup();
2489 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2490 set_fpu_control_word(old_fpucw);
2492 return hr;
2495 static HRESULT WINAPI
2496 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2497 D3DRENDERSTATETYPE dwRenderStateType,
2498 DWORD *lpdwRenderState)
2500 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2501 HRESULT hr;
2502 TRACE("(%p)->(%08x,%p)\n", This, dwRenderStateType, lpdwRenderState);
2504 switch(dwRenderStateType)
2506 case D3DRENDERSTATE_TEXTUREHANDLE:
2508 /* This state is wrapped to SetTexture in SetRenderState, so
2509 * it has to be wrapped to GetTexture here
2511 IWineD3DBaseTexture *tex = NULL;
2512 *lpdwRenderState = 0;
2514 EnterCriticalSection(&ddraw_cs);
2516 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2518 &tex);
2520 if(hr == WINED3D_OK && tex)
2522 IDirectDrawSurface7 *parent = NULL;
2523 hr = IWineD3DBaseTexture_GetParent(tex,
2524 (IUnknown **) &parent);
2525 if(parent)
2527 /* The parent of the texture is the IDirectDrawSurface7 interface
2528 * of the ddraw surface
2530 IDirectDrawSurfaceImpl *texImpl = ICOM_OBJECT(IDirectDrawSurfaceImpl,
2531 IDirectDrawSurface7,
2532 parent);
2533 *lpdwRenderState = texImpl->Handle;
2534 IDirectDrawSurface7_Release(parent);
2536 IWineD3DBaseTexture_Release(tex);
2539 LeaveCriticalSection(&ddraw_cs);
2541 return hr;
2544 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2546 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2547 the mapping to get the value. */
2548 DWORD colorop, colorarg1, colorarg2;
2549 DWORD alphaop, alphaarg1, alphaarg2;
2551 EnterCriticalSection(&ddraw_cs);
2553 This->legacyTextureBlending = TRUE;
2555 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, &colorop);
2556 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, &colorarg1);
2557 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, &colorarg2);
2558 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, &alphaop);
2559 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2560 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2562 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2563 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2565 *lpdwRenderState = D3DTBLEND_DECAL;
2567 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2568 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2570 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2572 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2573 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2575 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2577 else
2579 HRESULT hr;
2580 BOOL tex_alpha = FALSE;
2581 IWineD3DBaseTexture *tex = NULL;
2582 WINED3DSURFACE_DESC desc;
2583 WINED3DFORMAT fmt;
2584 DDPIXELFORMAT ddfmt;
2586 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2588 &tex);
2590 if(hr == WINED3D_OK && tex)
2592 memset(&desc, 0, sizeof(desc));
2593 desc.Format = &fmt;
2594 hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2595 if (SUCCEEDED(hr))
2597 ddfmt.dwSize = sizeof(ddfmt);
2598 PixelFormat_WineD3DtoDD(&ddfmt, fmt);
2599 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2602 IWineD3DBaseTexture_Release(tex);
2605 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2606 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == (tex_alpha ? WINED3DTA_TEXTURE : WINED3DTA_CURRENT)))
2608 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2611 *lpdwRenderState = D3DTBLEND_MODULATE;
2614 LeaveCriticalSection(&ddraw_cs);
2616 return D3D_OK;
2619 default:
2620 return IDirect3DDevice7_GetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
2621 dwRenderStateType,
2622 lpdwRenderState);
2626 static HRESULT WINAPI
2627 Thunk_IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2628 D3DRENDERSTATETYPE dwRenderStateType,
2629 DWORD *lpdwRenderState)
2631 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2632 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice3 interface.\n", This, dwRenderStateType, lpdwRenderState);
2633 return IDirect3DDevice3_GetRenderState(ICOM_INTERFACE(This, IDirect3DDevice3),
2634 dwRenderStateType,
2635 lpdwRenderState);
2638 /*****************************************************************************
2639 * IDirect3DDevice7::SetRenderState
2641 * Sets a render state. The possible render states are defined in
2642 * include/d3dtypes.h
2644 * Version 2, 3 and 7
2646 * Params:
2647 * RenderStateType: State to set
2648 * Value: Value to assign to that state
2650 * Returns:
2651 * D3D_OK on success,
2652 * for details see IWineD3DDevice::SetRenderState
2654 *****************************************************************************/
2655 static HRESULT
2656 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2657 D3DRENDERSTATETYPE RenderStateType,
2658 DWORD Value)
2660 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2661 HRESULT hr;
2662 TRACE("(%p)->(%08x,%d): Relay\n", This, RenderStateType, Value);
2664 EnterCriticalSection(&ddraw_cs);
2665 /* Some render states need special care */
2666 switch(RenderStateType)
2668 case D3DRENDERSTATE_TEXTUREMAG:
2670 WINED3DTEXTUREFILTERTYPE tex_mag = WINED3DTEXF_NONE;
2672 switch ((D3DTEXTUREFILTER) Value)
2674 case D3DFILTER_NEAREST:
2675 case D3DFILTER_LINEARMIPNEAREST:
2676 tex_mag = WINED3DTEXF_POINT;
2677 break;
2678 case D3DFILTER_LINEAR:
2679 case D3DFILTER_LINEARMIPLINEAR:
2680 tex_mag = WINED3DTEXF_LINEAR;
2681 break;
2682 default:
2683 ERR("Unhandled texture mag %d !\n",Value);
2686 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2687 0, WINED3DSAMP_MAGFILTER,
2688 tex_mag);
2689 break;
2692 case D3DRENDERSTATE_TEXTUREMIN:
2694 WINED3DTEXTUREFILTERTYPE tex_min = WINED3DTEXF_NONE;
2695 WINED3DTEXTUREFILTERTYPE tex_mip = WINED3DTEXF_NONE;
2697 switch ((D3DTEXTUREFILTER) Value)
2699 case D3DFILTER_NEAREST:
2700 tex_min = WINED3DTEXF_POINT;
2701 break;
2702 case D3DFILTER_LINEAR:
2703 tex_min = WINED3DTEXF_LINEAR;
2704 break;
2705 case D3DFILTER_MIPNEAREST:
2706 tex_min = WINED3DTEXF_NONE;
2707 tex_mip = WINED3DTEXF_POINT;
2708 break;
2709 case D3DFILTER_MIPLINEAR:
2710 tex_min = WINED3DTEXF_NONE;
2711 tex_mip = WINED3DTEXF_LINEAR;
2712 break;
2713 case D3DFILTER_LINEARMIPNEAREST:
2714 tex_min = WINED3DTEXF_POINT;
2715 tex_mip = WINED3DTEXF_LINEAR;
2716 break;
2717 case D3DFILTER_LINEARMIPLINEAR:
2718 tex_min = WINED3DTEXF_LINEAR;
2719 tex_mip = WINED3DTEXF_LINEAR;
2720 break;
2722 default:
2723 ERR("Unhandled texture min %d !\n",Value);
2726 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2727 0, WINED3DSAMP_MIPFILTER,
2728 tex_mip);
2729 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2730 0, WINED3DSAMP_MINFILTER,
2731 tex_min);
2732 break;
2735 case D3DRENDERSTATE_TEXTUREADDRESS:
2736 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2737 0, WINED3DSAMP_ADDRESSV,
2738 Value);
2739 /* Drop through */
2740 case D3DRENDERSTATE_TEXTUREADDRESSU:
2741 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2742 0, WINED3DSAMP_ADDRESSU,
2743 Value);
2744 break;
2745 case D3DRENDERSTATE_TEXTUREADDRESSV:
2746 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2747 0, WINED3DSAMP_ADDRESSV,
2748 Value);
2749 break;
2751 default:
2753 /* FIXME: Unhandled: D3DRENDERSTATE_STIPPLEPATTERN00 - 31 */
2755 hr = IWineD3DDevice_SetRenderState(This->wineD3DDevice,
2756 RenderStateType,
2757 Value);
2758 break;
2760 LeaveCriticalSection(&ddraw_cs);
2761 return hr;
2764 static HRESULT WINAPI
2765 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2766 D3DRENDERSTATETYPE RenderStateType,
2767 DWORD Value)
2769 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2772 static HRESULT WINAPI
2773 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2774 D3DRENDERSTATETYPE RenderStateType,
2775 DWORD Value)
2777 HRESULT hr;
2778 WORD old_fpucw;
2780 old_fpucw = d3d_fpu_setup();
2781 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2782 set_fpu_control_word(old_fpucw);
2784 return hr;
2787 static HRESULT WINAPI
2788 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2789 D3DRENDERSTATETYPE RenderStateType,
2790 DWORD Value)
2792 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2793 for this state can be directly mapped to texture stage colorop and alphaop, but
2794 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2795 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2796 alphaarg when needed.
2798 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2800 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2801 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2802 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2803 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2804 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2805 in device - TRUE if the app is using TEXTUREMAPBLEND.
2807 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2808 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2809 unless some broken game will be found that cares. */
2811 HRESULT hr;
2812 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2813 TRACE("(%p)->(%08x,%d)\n", This, RenderStateType, Value);
2815 EnterCriticalSection(&ddraw_cs);
2817 switch(RenderStateType)
2819 case D3DRENDERSTATE_TEXTUREHANDLE:
2821 if(Value == 0)
2823 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
2825 NULL);
2826 break;
2829 if(Value > This->numHandles)
2831 FIXME("Specified handle %d out of range\n", Value);
2832 hr = DDERR_INVALIDPARAMS;
2833 break;
2835 if(This->Handles[Value - 1].type != DDrawHandle_Texture)
2837 FIXME("Handle %d isn't a texture handle\n", Value);
2838 hr = DDERR_INVALIDPARAMS;
2839 break;
2841 else
2843 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *) This->Handles[Value - 1].ptr;
2844 hr = IDirect3DDevice3_SetTexture(iface, 0, ICOM_INTERFACE(surf, IDirect3DTexture2));
2845 break;
2849 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2851 This->legacyTextureBlending = TRUE;
2853 switch ( (D3DTEXTUREBLEND) Value)
2855 case D3DTBLEND_MODULATE:
2857 BOOL tex_alpha = FALSE;
2858 IWineD3DBaseTexture *tex = NULL;
2859 WINED3DSURFACE_DESC desc;
2860 WINED3DFORMAT fmt;
2861 DDPIXELFORMAT ddfmt;
2863 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2865 &tex);
2867 if(hr == WINED3D_OK && tex)
2869 memset(&desc, 0, sizeof(desc));
2870 desc.Format = &fmt;
2871 hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2872 if (SUCCEEDED(hr))
2874 ddfmt.dwSize = sizeof(ddfmt);
2875 PixelFormat_WineD3DtoDD(&ddfmt, fmt);
2876 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2879 IWineD3DBaseTexture_Release(tex);
2882 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2883 if (tex_alpha)
2885 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2887 else
2889 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_CURRENT);
2892 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2893 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2894 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2896 break;
2899 case D3DTBLEND_ADD:
2900 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2901 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2902 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2903 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2904 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2905 break;
2907 case D3DTBLEND_MODULATEALPHA:
2908 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2909 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2910 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2911 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2912 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2913 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2914 break;
2916 case D3DTBLEND_COPY:
2917 case D3DTBLEND_DECAL:
2918 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2919 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2920 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2921 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2922 break;
2924 case D3DTBLEND_DECALALPHA:
2925 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2926 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2927 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2928 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2929 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2930 break;
2932 default:
2933 ERR("Unhandled texture environment %d !\n",Value);
2936 hr = D3D_OK;
2937 break;
2940 default:
2941 hr = IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
2942 RenderStateType,
2943 Value);
2944 break;
2947 LeaveCriticalSection(&ddraw_cs);
2949 return hr;
2952 static HRESULT WINAPI
2953 Thunk_IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2954 D3DRENDERSTATETYPE RenderStateType,
2955 DWORD Value)
2957 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2958 TRACE_(ddraw_thunk)("(%p)->(%08x,%d) thunking to IDirect3DDevice3 interface.\n", This, RenderStateType, Value);
2959 return IDirect3DDevice3_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice3), RenderStateType, Value);
2962 /*****************************************************************************
2963 * Direct3DDevice3::SetLightState
2965 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2966 * light states are forwarded to Direct3DDevice7 render states
2968 * Version 2 and 3
2970 * Params:
2971 * LightStateType: The light state to change
2972 * Value: The value to assign to that light state
2974 * Returns:
2975 * D3D_OK on success
2976 * DDERR_INVALIDPARAMS if the parameters were incorrect
2977 * Also check IDirect3DDevice7::SetRenderState
2979 *****************************************************************************/
2980 static HRESULT WINAPI
2981 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
2982 D3DLIGHTSTATETYPE LightStateType,
2983 DWORD Value)
2985 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2986 HRESULT hr;
2988 TRACE("(%p)->(%08x,%08x)\n", This, LightStateType, Value);
2990 if (!LightStateType && (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2992 TRACE("Unexpected Light State Type\n");
2993 return DDERR_INVALIDPARAMS;
2996 EnterCriticalSection(&ddraw_cs);
2997 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
2999 IDirect3DMaterialImpl *mat;
3001 if(Value == 0) mat = NULL;
3002 else if(Value > This->numHandles)
3004 ERR("Material handle out of range(%d)\n", Value);
3005 LeaveCriticalSection(&ddraw_cs);
3006 return DDERR_INVALIDPARAMS;
3008 else if(This->Handles[Value - 1].type != DDrawHandle_Material)
3010 ERR("Invalid handle %d\n", Value);
3011 LeaveCriticalSection(&ddraw_cs);
3012 return DDERR_INVALIDPARAMS;
3014 else
3016 mat = (IDirect3DMaterialImpl *) This->Handles[Value - 1].ptr;
3019 if (mat != NULL)
3021 TRACE(" activating material %p.\n", mat);
3022 mat->activate(mat);
3024 else
3026 FIXME(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
3028 This->material = Value;
3030 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3032 switch (Value)
3034 case D3DCOLOR_MONO:
3035 ERR("DDCOLOR_MONO should not happen!\n");
3036 break;
3037 case D3DCOLOR_RGB:
3038 /* We are already in this mode */
3039 TRACE("Setting color model to RGB (no-op).\n");
3040 break;
3041 default:
3042 ERR("Unknown color model!\n");
3043 LeaveCriticalSection(&ddraw_cs);
3044 return DDERR_INVALIDPARAMS;
3047 else
3049 D3DRENDERSTATETYPE rs;
3050 switch (LightStateType)
3052 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3053 rs = D3DRENDERSTATE_AMBIENT;
3054 break;
3055 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3056 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3057 break;
3058 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3059 rs = D3DRENDERSTATE_FOGSTART;
3060 break;
3061 case D3DLIGHTSTATE_FOGEND: /* 6 */
3062 rs = D3DRENDERSTATE_FOGEND;
3063 break;
3064 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3065 rs = D3DRENDERSTATE_FOGDENSITY;
3066 break;
3067 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3068 rs = D3DRENDERSTATE_COLORVERTEX;
3069 break;
3070 default:
3071 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3072 LeaveCriticalSection(&ddraw_cs);
3073 return DDERR_INVALIDPARAMS;
3076 hr = IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
3078 Value);
3079 LeaveCriticalSection(&ddraw_cs);
3080 return hr;
3083 LeaveCriticalSection(&ddraw_cs);
3084 return D3D_OK;
3087 static HRESULT WINAPI
3088 Thunk_IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3089 D3DLIGHTSTATETYPE LightStateType,
3090 DWORD Value)
3092 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3093 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x) thunking to IDirect3DDevice3 interface.\n", This, LightStateType, Value);
3094 return IDirect3DDevice3_SetLightState(ICOM_INTERFACE(This, IDirect3DDevice3),
3095 LightStateType,
3096 Value);
3099 /*****************************************************************************
3100 * IDirect3DDevice3::GetLightState
3102 * Returns the current setting of a light state. The state is read from
3103 * the Direct3DDevice7 render state.
3105 * Version 2 and 3
3107 * Params:
3108 * LightStateType: The light state to return
3109 * Value: The address to store the light state setting at
3111 * Returns:
3112 * D3D_OK on success
3113 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3114 * Also see IDirect3DDevice7::GetRenderState
3116 *****************************************************************************/
3117 static HRESULT WINAPI
3118 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3119 D3DLIGHTSTATETYPE LightStateType,
3120 DWORD *Value)
3122 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3123 HRESULT hr;
3125 TRACE("(%p)->(%08x,%p)\n", This, LightStateType, Value);
3127 if (!LightStateType && (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3129 TRACE("Unexpected Light State Type\n");
3130 return DDERR_INVALIDPARAMS;
3133 if(!Value)
3134 return DDERR_INVALIDPARAMS;
3136 EnterCriticalSection(&ddraw_cs);
3137 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3139 *Value = This->material;
3141 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3143 *Value = D3DCOLOR_RGB;
3145 else
3147 D3DRENDERSTATETYPE rs;
3148 switch (LightStateType)
3150 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3151 rs = D3DRENDERSTATE_AMBIENT;
3152 break;
3153 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3154 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3155 break;
3156 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3157 rs = D3DRENDERSTATE_FOGSTART;
3158 break;
3159 case D3DLIGHTSTATE_FOGEND: /* 6 */
3160 rs = D3DRENDERSTATE_FOGEND;
3161 break;
3162 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3163 rs = D3DRENDERSTATE_FOGDENSITY;
3164 break;
3165 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3166 rs = D3DRENDERSTATE_COLORVERTEX;
3167 break;
3168 default:
3169 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3170 LeaveCriticalSection(&ddraw_cs);
3171 return DDERR_INVALIDPARAMS;
3174 hr = IDirect3DDevice7_GetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
3176 Value);
3177 LeaveCriticalSection(&ddraw_cs);
3178 return hr;
3181 LeaveCriticalSection(&ddraw_cs);
3182 return D3D_OK;
3185 static HRESULT WINAPI
3186 Thunk_IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3187 D3DLIGHTSTATETYPE LightStateType,
3188 DWORD *Value)
3190 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3191 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice3 interface.\n", This, LightStateType, Value);
3192 return IDirect3DDevice3_GetLightState(ICOM_INTERFACE(This, IDirect3DDevice3),
3193 LightStateType,
3194 Value);
3197 /*****************************************************************************
3198 * IDirect3DDevice7::SetTransform
3200 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3201 * in include/d3dtypes.h.
3202 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3203 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3204 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3206 * Version 2, 3 and 7
3208 * Params:
3209 * TransformStateType: transform state to set
3210 * Matrix: Matrix to assign to the state
3212 * Returns:
3213 * D3D_OK on success
3214 * DDERR_INVALIDPARAMS if Matrix == NULL
3215 * For details see IWineD3DDevice::SetTransform
3217 *****************************************************************************/
3218 static HRESULT
3219 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3220 D3DTRANSFORMSTATETYPE TransformStateType,
3221 D3DMATRIX *Matrix)
3223 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3224 D3DTRANSFORMSTATETYPE type = TransformStateType;
3225 HRESULT hr;
3226 TRACE("(%p)->(%08x,%p): Relay\n", This, TransformStateType, Matrix);
3228 switch(TransformStateType)
3230 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3231 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3232 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3233 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3234 default: type = TransformStateType;
3237 if(!Matrix)
3238 return DDERR_INVALIDPARAMS;
3240 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3241 EnterCriticalSection(&ddraw_cs);
3242 hr = IWineD3DDevice_SetTransform(This->wineD3DDevice,
3243 type,
3244 (WINED3DMATRIX*) Matrix);
3245 LeaveCriticalSection(&ddraw_cs);
3246 return hr;
3249 static HRESULT WINAPI
3250 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3251 D3DTRANSFORMSTATETYPE TransformStateType,
3252 D3DMATRIX *Matrix)
3254 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3257 static HRESULT WINAPI
3258 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3259 D3DTRANSFORMSTATETYPE TransformStateType,
3260 D3DMATRIX *Matrix)
3262 HRESULT hr;
3263 WORD old_fpucw;
3265 old_fpucw = d3d_fpu_setup();
3266 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3267 set_fpu_control_word(old_fpucw);
3269 return hr;
3272 static HRESULT WINAPI
3273 Thunk_IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3274 D3DTRANSFORMSTATETYPE TransformStateType,
3275 D3DMATRIX *D3DMatrix)
3277 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3278 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3279 return IDirect3DDevice7_SetTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
3280 TransformStateType,
3281 D3DMatrix);
3284 static HRESULT WINAPI
3285 Thunk_IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3286 D3DTRANSFORMSTATETYPE TransformStateType,
3287 D3DMATRIX *D3DMatrix)
3289 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3290 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3291 return IDirect3DDevice7_SetTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
3292 TransformStateType,
3293 D3DMatrix);
3296 /*****************************************************************************
3297 * IDirect3DDevice7::GetTransform
3299 * Returns the matrix assigned to a transform state
3300 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3301 * SetTransform
3303 * Params:
3304 * TransformStateType: State to read the matrix from
3305 * Matrix: Address to store the matrix at
3307 * Returns:
3308 * D3D_OK on success
3309 * DDERR_INVALIDPARAMS if Matrix == NULL
3310 * For details, see IWineD3DDevice::GetTransform
3312 *****************************************************************************/
3313 static HRESULT
3314 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3315 D3DTRANSFORMSTATETYPE TransformStateType,
3316 D3DMATRIX *Matrix)
3318 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3319 D3DTRANSFORMSTATETYPE type = TransformStateType;
3320 HRESULT hr;
3321 TRACE("(%p)->(%08x,%p): Relay\n", This, TransformStateType, Matrix);
3323 switch(TransformStateType)
3325 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3326 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3327 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3328 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3329 default: type = TransformStateType;
3332 if(!Matrix)
3333 return DDERR_INVALIDPARAMS;
3335 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3336 EnterCriticalSection(&ddraw_cs);
3337 hr = IWineD3DDevice_GetTransform(This->wineD3DDevice, type, (WINED3DMATRIX*) Matrix);
3338 LeaveCriticalSection(&ddraw_cs);
3339 return hr;
3342 static HRESULT WINAPI
3343 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3344 D3DTRANSFORMSTATETYPE TransformStateType,
3345 D3DMATRIX *Matrix)
3347 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3350 static HRESULT WINAPI
3351 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3352 D3DTRANSFORMSTATETYPE TransformStateType,
3353 D3DMATRIX *Matrix)
3355 HRESULT hr;
3356 WORD old_fpucw;
3358 old_fpucw = d3d_fpu_setup();
3359 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3360 set_fpu_control_word(old_fpucw);
3362 return hr;
3365 static HRESULT WINAPI
3366 Thunk_IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3367 D3DTRANSFORMSTATETYPE TransformStateType,
3368 D3DMATRIX *D3DMatrix)
3370 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3371 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3372 return IDirect3DDevice7_GetTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
3373 TransformStateType,
3374 D3DMatrix);
3377 static HRESULT WINAPI
3378 Thunk_IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3379 D3DTRANSFORMSTATETYPE TransformStateType,
3380 D3DMATRIX *D3DMatrix)
3382 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3383 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3384 return IDirect3DDevice7_GetTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
3385 TransformStateType,
3386 D3DMatrix);
3389 /*****************************************************************************
3390 * IDirect3DDevice7::MultiplyTransform
3392 * Multiplies the already-set transform matrix of a transform state
3393 * with another matrix. For the world matrix, see SetTransform
3395 * Version 2, 3 and 7
3397 * Params:
3398 * TransformStateType: Transform state to multiply
3399 * D3DMatrix Matrix to multiply with.
3401 * Returns
3402 * D3D_OK on success
3403 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3404 * For details, see IWineD3DDevice::MultiplyTransform
3406 *****************************************************************************/
3407 static HRESULT
3408 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3409 D3DTRANSFORMSTATETYPE TransformStateType,
3410 D3DMATRIX *D3DMatrix)
3412 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3413 HRESULT hr;
3414 D3DTRANSFORMSTATETYPE type;
3415 TRACE("(%p)->(%08x,%p): Relay\n", This, TransformStateType, D3DMatrix);
3417 switch(TransformStateType)
3419 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3420 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3421 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3422 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3423 default: type = TransformStateType;
3426 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3427 EnterCriticalSection(&ddraw_cs);
3428 hr = IWineD3DDevice_MultiplyTransform(This->wineD3DDevice,
3429 type,
3430 (WINED3DMATRIX*) D3DMatrix);
3431 LeaveCriticalSection(&ddraw_cs);
3432 return hr;
3435 static HRESULT WINAPI
3436 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3437 D3DTRANSFORMSTATETYPE TransformStateType,
3438 D3DMATRIX *D3DMatrix)
3440 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3443 static HRESULT WINAPI
3444 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3445 D3DTRANSFORMSTATETYPE TransformStateType,
3446 D3DMATRIX *D3DMatrix)
3448 HRESULT hr;
3449 WORD old_fpucw;
3451 old_fpucw = d3d_fpu_setup();
3452 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3453 set_fpu_control_word(old_fpucw);
3455 return hr;
3458 static HRESULT WINAPI
3459 Thunk_IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3460 D3DTRANSFORMSTATETYPE TransformStateType,
3461 D3DMATRIX *D3DMatrix)
3463 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3464 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3465 return IDirect3DDevice7_MultiplyTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
3466 TransformStateType,
3467 D3DMatrix);
3470 static HRESULT WINAPI
3471 Thunk_IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3472 D3DTRANSFORMSTATETYPE TransformStateType,
3473 D3DMATRIX *D3DMatrix)
3475 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3476 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3477 return IDirect3DDevice7_MultiplyTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
3478 TransformStateType,
3479 D3DMatrix);
3482 /*****************************************************************************
3483 * IDirect3DDevice7::DrawPrimitive
3485 * Draws primitives based on vertices in an application-provided pointer
3487 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3488 * an FVF format for D3D7
3490 * Params:
3491 * PrimitiveType: The type of the primitives to draw
3492 * Vertex type: Flexible vertex format vertex description
3493 * Vertices: Pointer to the vertex array
3494 * VertexCount: The number of vertices to draw
3495 * Flags: As usual a few flags
3497 * Returns:
3498 * D3D_OK on success
3499 * DDERR_INVALIDPARAMS if Vertices is NULL
3500 * For details, see IWineD3DDevice::DrawPrimitiveUP
3502 *****************************************************************************/
3503 static HRESULT
3504 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3505 D3DPRIMITIVETYPE PrimitiveType,
3506 DWORD VertexType,
3507 void *Vertices,
3508 DWORD VertexCount,
3509 DWORD Flags)
3511 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3512 UINT PrimitiveCount, stride;
3513 HRESULT hr;
3514 TRACE("(%p)->(%08x,%08x,%p,%08x,%08x): Relay!\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3516 if(!Vertices)
3517 return DDERR_INVALIDPARAMS;
3519 /* Get the vertex count */
3520 switch(PrimitiveType)
3522 case D3DPT_POINTLIST:
3523 PrimitiveCount = VertexCount;
3524 break;
3526 case D3DPT_LINELIST:
3527 PrimitiveCount = VertexCount / 2;
3528 break;
3530 case D3DPT_LINESTRIP:
3531 PrimitiveCount = VertexCount - 1;
3532 break;
3534 case D3DPT_TRIANGLELIST:
3535 PrimitiveCount = VertexCount / 3;
3536 break;
3538 case D3DPT_TRIANGLESTRIP:
3539 PrimitiveCount = VertexCount - 2;
3540 break;
3542 case D3DPT_TRIANGLEFAN:
3543 PrimitiveCount = VertexCount - 2;
3544 break;
3546 default:
3547 return DDERR_INVALIDPARAMS;
3550 /* Get the stride */
3551 stride = get_flexible_vertex_size(VertexType);
3553 /* Set the FVF */
3554 EnterCriticalSection(&ddraw_cs);
3555 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
3556 IDirectDrawImpl_FindDecl(This->ddraw, VertexType));
3557 if(hr != D3D_OK)
3559 LeaveCriticalSection(&ddraw_cs);
3560 return hr;
3563 /* This method translates to the user pointer draw of WineD3D */
3564 hr = IWineD3DDevice_DrawPrimitiveUP(This->wineD3DDevice,
3565 PrimitiveType,
3566 PrimitiveCount,
3567 Vertices,
3568 stride);
3569 LeaveCriticalSection(&ddraw_cs);
3570 return hr;
3573 static HRESULT WINAPI
3574 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3575 D3DPRIMITIVETYPE PrimitiveType,
3576 DWORD VertexType,
3577 void *Vertices,
3578 DWORD VertexCount,
3579 DWORD Flags)
3581 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3584 static HRESULT WINAPI
3585 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3586 D3DPRIMITIVETYPE PrimitiveType,
3587 DWORD VertexType,
3588 void *Vertices,
3589 DWORD VertexCount,
3590 DWORD Flags)
3592 HRESULT hr;
3593 WORD old_fpucw;
3595 old_fpucw = d3d_fpu_setup();
3596 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3597 set_fpu_control_word(old_fpucw);
3599 return hr;
3602 static HRESULT WINAPI
3603 Thunk_IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3604 D3DPRIMITIVETYPE PrimitiveType,
3605 DWORD VertexType,
3606 void *Vertices,
3607 DWORD VertexCount,
3608 DWORD Flags)
3610 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3611 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3612 return IDirect3DDevice7_DrawPrimitive(ICOM_INTERFACE(This, IDirect3DDevice7),
3613 PrimitiveType,
3614 VertexType,
3615 Vertices,
3616 VertexCount,
3617 Flags);
3620 static HRESULT WINAPI
3621 Thunk_IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3622 D3DPRIMITIVETYPE PrimitiveType,
3623 D3DVERTEXTYPE VertexType,
3624 void *Vertices,
3625 DWORD VertexCount,
3626 DWORD Flags)
3628 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3629 DWORD FVF;
3630 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3632 switch(VertexType)
3634 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3635 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3636 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3637 default:
3638 ERR("Unexpected vertex type %d\n", VertexType);
3639 return DDERR_INVALIDPARAMS; /* Should never happen */
3642 return IDirect3DDevice7_DrawPrimitive(ICOM_INTERFACE(This, IDirect3DDevice7),
3643 PrimitiveType,
3644 FVF,
3645 Vertices,
3646 VertexCount,
3647 Flags);
3650 /*****************************************************************************
3651 * IDirect3DDevice7::DrawIndexedPrimitive
3653 * Draws vertices from an application-provided pointer, based on the index
3654 * numbers in a WORD array.
3656 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3657 * an FVF format for D3D7
3659 * Params:
3660 * PrimitiveType: The primitive type to draw
3661 * VertexType: The FVF vertex description
3662 * Vertices: Pointer to the vertex array
3663 * VertexCount: ?
3664 * Indices: Pointer to the index array
3665 * IndexCount: Number of indices = Number of vertices to draw
3666 * Flags: As usual, some flags
3668 * Returns:
3669 * D3D_OK on success
3670 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3671 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3673 *****************************************************************************/
3674 static HRESULT
3675 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3676 D3DPRIMITIVETYPE PrimitiveType,
3677 DWORD VertexType,
3678 void *Vertices,
3679 DWORD VertexCount,
3680 WORD *Indices,
3681 DWORD IndexCount,
3682 DWORD Flags)
3684 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3685 UINT PrimitiveCount = 0;
3686 HRESULT hr;
3687 TRACE("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x): Relay!\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3689 /* Get the primitive number */
3690 switch(PrimitiveType)
3692 case D3DPT_POINTLIST:
3693 PrimitiveCount = IndexCount;
3694 break;
3696 case D3DPT_LINELIST:
3697 PrimitiveCount = IndexCount / 2;
3698 break;
3700 case D3DPT_LINESTRIP:
3701 PrimitiveCount = IndexCount - 1;
3702 break;
3704 case D3DPT_TRIANGLELIST:
3705 PrimitiveCount = IndexCount / 3;
3706 break;
3708 case D3DPT_TRIANGLESTRIP:
3709 PrimitiveCount = IndexCount - 2;
3710 break;
3712 case D3DPT_TRIANGLEFAN:
3713 PrimitiveCount = IndexCount - 2;
3714 break;
3716 default:
3717 return DDERR_INVALIDPARAMS;
3720 /* Set the D3DDevice's FVF */
3721 EnterCriticalSection(&ddraw_cs);
3722 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
3723 IDirectDrawImpl_FindDecl(This->ddraw, VertexType));
3724 if(FAILED(hr))
3726 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3727 LeaveCriticalSection(&ddraw_cs);
3728 return hr;
3731 hr = IWineD3DDevice_DrawIndexedPrimitiveUP(This->wineD3DDevice,
3732 PrimitiveType,
3733 0 /* MinVertexIndex */,
3734 VertexCount /* UINT NumVertexIndex */,
3735 PrimitiveCount,
3736 Indices,
3737 WINED3DFMT_INDEX16,
3738 Vertices,
3739 get_flexible_vertex_size(VertexType));
3740 LeaveCriticalSection(&ddraw_cs);
3741 return hr;
3744 static HRESULT WINAPI
3745 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3746 D3DPRIMITIVETYPE PrimitiveType,
3747 DWORD VertexType,
3748 void *Vertices,
3749 DWORD VertexCount,
3750 WORD *Indices,
3751 DWORD IndexCount,
3752 DWORD Flags)
3754 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3757 static HRESULT WINAPI
3758 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3759 D3DPRIMITIVETYPE PrimitiveType,
3760 DWORD VertexType,
3761 void *Vertices,
3762 DWORD VertexCount,
3763 WORD *Indices,
3764 DWORD IndexCount,
3765 DWORD Flags)
3767 HRESULT hr;
3768 WORD old_fpucw;
3770 old_fpucw = d3d_fpu_setup();
3771 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3772 set_fpu_control_word(old_fpucw);
3774 return hr;
3777 static HRESULT WINAPI
3778 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3779 D3DPRIMITIVETYPE PrimitiveType,
3780 DWORD VertexType,
3781 void *Vertices,
3782 DWORD VertexCount,
3783 WORD *Indices,
3784 DWORD IndexCount,
3785 DWORD Flags)
3787 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3788 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3789 return IDirect3DDevice7_DrawIndexedPrimitive(ICOM_INTERFACE(This, IDirect3DDevice7),
3790 PrimitiveType,
3791 VertexType,
3792 Vertices,
3793 VertexCount,
3794 Indices,
3795 IndexCount,
3796 Flags);
3799 static HRESULT WINAPI
3800 Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3801 D3DPRIMITIVETYPE PrimitiveType,
3802 D3DVERTEXTYPE VertexType,
3803 void *Vertices,
3804 DWORD VertexCount,
3805 WORD *Indices,
3806 DWORD IndexCount,
3807 DWORD Flags)
3809 DWORD FVF;
3810 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3811 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3813 switch(VertexType)
3815 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3816 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3817 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3818 default:
3819 ERR("Unexpected vertex type %d\n", VertexType);
3820 return DDERR_INVALIDPARAMS; /* Should never happen */
3823 return IDirect3DDevice7_DrawIndexedPrimitive(ICOM_INTERFACE(This, IDirect3DDevice7),
3824 PrimitiveType,
3825 FVF,
3826 Vertices,
3827 VertexCount,
3828 Indices,
3829 IndexCount,
3830 Flags);
3833 /*****************************************************************************
3834 * IDirect3DDevice7::SetClipStatus
3836 * Sets the clip status. This defines things as clipping conditions and
3837 * the extents of the clipping region.
3839 * Version 2, 3 and 7
3841 * Params:
3842 * ClipStatus:
3844 * Returns:
3845 * D3D_OK because it's a stub
3846 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3848 *****************************************************************************/
3849 static HRESULT WINAPI
3850 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3851 D3DCLIPSTATUS *ClipStatus)
3853 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3854 FIXME("(%p)->(%p): Stub!\n", This, ClipStatus);
3856 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3857 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3859 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3860 return D3D_OK;
3863 static HRESULT WINAPI
3864 Thunk_IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3865 D3DCLIPSTATUS *ClipStatus)
3867 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3868 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3869 return IDirect3DDevice7_SetClipStatus(ICOM_INTERFACE(This, IDirect3DDevice7),
3870 ClipStatus);
3873 static HRESULT WINAPI
3874 Thunk_IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3875 D3DCLIPSTATUS *ClipStatus)
3877 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3878 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3879 return IDirect3DDevice7_SetClipStatus(ICOM_INTERFACE(This, IDirect3DDevice7),
3880 ClipStatus);
3883 /*****************************************************************************
3884 * IDirect3DDevice7::GetClipStatus
3886 * Returns the clip status
3888 * Params:
3889 * ClipStatus: Address to write the clip status to
3891 * Returns:
3892 * D3D_OK because it's a stub
3894 *****************************************************************************/
3895 static HRESULT WINAPI
3896 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3897 D3DCLIPSTATUS *ClipStatus)
3899 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3900 FIXME("(%p)->(%p): Stub!\n", This, ClipStatus);
3902 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3903 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3904 return D3D_OK;
3907 static HRESULT WINAPI
3908 Thunk_IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3909 D3DCLIPSTATUS *ClipStatus)
3911 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3912 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3913 return IDirect3DDevice7_GetClipStatus(ICOM_INTERFACE(This, IDirect3DDevice7),
3914 ClipStatus);
3917 static HRESULT WINAPI
3918 Thunk_IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3919 D3DCLIPSTATUS *ClipStatus)
3921 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3922 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3923 return IDirect3DDevice7_GetClipStatus(ICOM_INTERFACE(This, IDirect3DDevice7),
3924 ClipStatus);
3927 /*****************************************************************************
3928 * IDirect3DDevice::DrawPrimitiveStrided
3930 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3932 * Version 3 and 7
3934 * Params:
3935 * PrimitiveType: The primitive type to draw
3936 * VertexType: The FVF description of the vertices to draw (for the stride??)
3937 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3938 * the vertex data locations
3939 * VertexCount: The number of vertices to draw
3940 * Flags: Some flags
3942 * Returns:
3943 * D3D_OK, because it's a stub
3944 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3945 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3947 *****************************************************************************/
3948 static HRESULT
3949 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3950 D3DPRIMITIVETYPE PrimitiveType,
3951 DWORD VertexType,
3952 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3953 DWORD VertexCount,
3954 DWORD Flags)
3956 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3957 WineDirect3DVertexStridedData WineD3DStrided;
3958 int i;
3959 UINT PrimitiveCount;
3960 HRESULT hr;
3962 TRACE("(%p)->(%08x,%08x,%p,%08x,%08x): stub!\n", This, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3964 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3965 /* Get the strided data right. the wined3d structure is a bit bigger
3966 * Watch out: The contents of the strided data are determined by the fvf,
3967 * not by the members set in D3DDrawPrimStrideData. So it's valid
3968 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3969 * not set in the fvf.
3971 if(VertexType & D3DFVF_POSITION_MASK)
3973 WineD3DStrided.u.s.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3974 WineD3DStrided.u.s.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3975 WineD3DStrided.u.s.position.dwType = WINED3DDECLTYPE_FLOAT3;
3976 if (VertexType & D3DFVF_XYZRHW)
3978 WineD3DStrided.u.s.position.dwType = WINED3DDECLTYPE_FLOAT4;
3979 WineD3DStrided.u.s.position_transformed = TRUE;
3980 } else
3981 WineD3DStrided.u.s.position_transformed = FALSE;
3984 if(VertexType & D3DFVF_NORMAL)
3986 WineD3DStrided.u.s.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3987 WineD3DStrided.u.s.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3988 WineD3DStrided.u.s.normal.dwType = WINED3DDECLTYPE_FLOAT3;
3991 if(VertexType & D3DFVF_DIFFUSE)
3993 WineD3DStrided.u.s.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3994 WineD3DStrided.u.s.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3995 WineD3DStrided.u.s.diffuse.dwType = WINED3DDECLTYPE_D3DCOLOR;
3998 if(VertexType & D3DFVF_SPECULAR)
4000 WineD3DStrided.u.s.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
4001 WineD3DStrided.u.s.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
4002 WineD3DStrided.u.s.specular.dwType = WINED3DDECLTYPE_D3DCOLOR;
4005 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
4007 WineD3DStrided.u.s.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4008 WineD3DStrided.u.s.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4009 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
4011 case 1: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT1; break;
4012 case 2: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT2; break;
4013 case 3: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT3; break;
4014 case 4: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT4; break;
4015 default: ERR("Unexpected texture coordinate size %d\n",
4016 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4020 /* Get the primitive count */
4021 switch(PrimitiveType)
4023 case D3DPT_POINTLIST:
4024 PrimitiveCount = VertexCount;
4025 break;
4027 case D3DPT_LINELIST:
4028 PrimitiveCount = VertexCount / 2;
4029 break;
4031 case D3DPT_LINESTRIP:
4032 PrimitiveCount = VertexCount - 1;
4033 break;
4035 case D3DPT_TRIANGLELIST:
4036 PrimitiveCount = VertexCount / 3;
4037 break;
4039 case D3DPT_TRIANGLESTRIP:
4040 PrimitiveCount = VertexCount - 2;
4041 break;
4043 case D3DPT_TRIANGLEFAN:
4044 PrimitiveCount = VertexCount - 2;
4045 break;
4047 default: return DDERR_INVALIDPARAMS;
4050 /* WineD3D doesn't need the FVF here */
4051 EnterCriticalSection(&ddraw_cs);
4052 hr = IWineD3DDevice_DrawPrimitiveStrided(This->wineD3DDevice,
4053 PrimitiveType,
4054 PrimitiveCount,
4055 &WineD3DStrided);
4056 LeaveCriticalSection(&ddraw_cs);
4057 return hr;
4060 static HRESULT WINAPI
4061 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4062 D3DPRIMITIVETYPE PrimitiveType,
4063 DWORD VertexType,
4064 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4065 DWORD VertexCount,
4066 DWORD Flags)
4068 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4071 static HRESULT WINAPI
4072 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4073 D3DPRIMITIVETYPE PrimitiveType,
4074 DWORD VertexType,
4075 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4076 DWORD VertexCount,
4077 DWORD Flags)
4079 HRESULT hr;
4080 WORD old_fpucw;
4082 old_fpucw = d3d_fpu_setup();
4083 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4084 set_fpu_control_word(old_fpucw);
4086 return hr;
4089 static HRESULT WINAPI
4090 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
4091 D3DPRIMITIVETYPE PrimitiveType,
4092 DWORD VertexType,
4093 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4094 DWORD VertexCount,
4095 DWORD Flags)
4097 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4098 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4099 return IDirect3DDevice7_DrawPrimitiveStrided(ICOM_INTERFACE(This, IDirect3DDevice7),
4100 PrimitiveType,
4101 VertexType,
4102 D3DDrawPrimStrideData,
4103 VertexCount,
4104 Flags);
4107 /*****************************************************************************
4108 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
4110 * Draws primitives specified by strided data locations based on indices
4112 * Version 3 and 7
4114 * Params:
4115 * PrimitiveType:
4117 * Returns:
4118 * D3D_OK, because it's a stub
4119 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
4120 * (DDERR_INVALIDPARAMS if Indices is NULL)
4121 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
4123 *****************************************************************************/
4124 static HRESULT
4125 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
4126 D3DPRIMITIVETYPE PrimitiveType,
4127 DWORD VertexType,
4128 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4129 DWORD VertexCount,
4130 WORD *Indices,
4131 DWORD IndexCount,
4132 DWORD Flags)
4134 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4135 WineDirect3DVertexStridedData WineD3DStrided;
4136 int i;
4137 UINT PrimitiveCount;
4138 HRESULT hr;
4140 TRACE("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x)\n", This, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4142 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
4143 /* Get the strided data right. the wined3d structure is a bit bigger
4144 * Watch out: The contents of the strided data are determined by the fvf,
4145 * not by the members set in D3DDrawPrimStrideData. So it's valid
4146 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
4147 * not set in the fvf.
4149 if(VertexType & D3DFVF_POSITION_MASK)
4151 WineD3DStrided.u.s.position.lpData = D3DDrawPrimStrideData->position.lpvData;
4152 WineD3DStrided.u.s.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
4153 WineD3DStrided.u.s.position.dwType = WINED3DDECLTYPE_FLOAT3;
4154 if (VertexType & D3DFVF_XYZRHW)
4156 WineD3DStrided.u.s.position.dwType = WINED3DDECLTYPE_FLOAT4;
4157 WineD3DStrided.u.s.position_transformed = TRUE;
4158 } else
4159 WineD3DStrided.u.s.position_transformed = FALSE;
4162 if(VertexType & D3DFVF_NORMAL)
4164 WineD3DStrided.u.s.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
4165 WineD3DStrided.u.s.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
4166 WineD3DStrided.u.s.normal.dwType = WINED3DDECLTYPE_FLOAT3;
4169 if(VertexType & D3DFVF_DIFFUSE)
4171 WineD3DStrided.u.s.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
4172 WineD3DStrided.u.s.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
4173 WineD3DStrided.u.s.diffuse.dwType = WINED3DDECLTYPE_D3DCOLOR;
4176 if(VertexType & D3DFVF_SPECULAR)
4178 WineD3DStrided.u.s.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
4179 WineD3DStrided.u.s.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
4180 WineD3DStrided.u.s.specular.dwType = WINED3DDECLTYPE_D3DCOLOR;
4183 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
4185 WineD3DStrided.u.s.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4186 WineD3DStrided.u.s.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4187 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
4189 case 1: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT1; break;
4190 case 2: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT2; break;
4191 case 3: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT3; break;
4192 case 4: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT4; break;
4193 default: ERR("Unexpected texture coordinate size %d\n",
4194 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4198 /* Get the primitive count */
4199 switch(PrimitiveType)
4201 case D3DPT_POINTLIST:
4202 PrimitiveCount = IndexCount;
4203 break;
4205 case D3DPT_LINELIST:
4206 PrimitiveCount = IndexCount / 2;
4207 break;
4209 case D3DPT_LINESTRIP:
4210 PrimitiveCount = IndexCount - 1;
4211 break;
4213 case D3DPT_TRIANGLELIST:
4214 PrimitiveCount = IndexCount / 3;
4215 break;
4217 case D3DPT_TRIANGLESTRIP:
4218 PrimitiveCount = IndexCount - 2;
4219 break;
4221 case D3DPT_TRIANGLEFAN:
4222 PrimitiveCount = IndexCount - 2;
4223 break;
4225 default: return DDERR_INVALIDPARAMS;
4228 /* WineD3D doesn't need the FVF here */
4229 EnterCriticalSection(&ddraw_cs);
4230 hr = IWineD3DDevice_DrawIndexedPrimitiveStrided(This->wineD3DDevice,
4231 PrimitiveType,
4232 PrimitiveCount,
4233 &WineD3DStrided,
4234 VertexCount,
4235 Indices,
4236 WINED3DFMT_INDEX16);
4237 LeaveCriticalSection(&ddraw_cs);
4238 return hr;
4241 static HRESULT WINAPI
4242 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4243 D3DPRIMITIVETYPE PrimitiveType,
4244 DWORD VertexType,
4245 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4246 DWORD VertexCount,
4247 WORD *Indices,
4248 DWORD IndexCount,
4249 DWORD Flags)
4251 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4254 static HRESULT WINAPI
4255 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4256 D3DPRIMITIVETYPE PrimitiveType,
4257 DWORD VertexType,
4258 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4259 DWORD VertexCount,
4260 WORD *Indices,
4261 DWORD IndexCount,
4262 DWORD Flags)
4264 HRESULT hr;
4265 WORD old_fpucw;
4267 old_fpucw = d3d_fpu_setup();
4268 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4269 set_fpu_control_word(old_fpucw);
4271 return hr;
4274 static HRESULT WINAPI
4275 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4276 D3DPRIMITIVETYPE PrimitiveType,
4277 DWORD VertexType,
4278 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4279 DWORD VertexCount,
4280 WORD *Indices,
4281 DWORD IndexCount,
4282 DWORD Flags)
4284 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4285 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4286 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(ICOM_INTERFACE(This, IDirect3DDevice7),
4287 PrimitiveType,
4288 VertexType,
4289 D3DDrawPrimStrideData,
4290 VertexCount,
4291 Indices,
4292 IndexCount,
4293 Flags);
4296 /*****************************************************************************
4297 * IDirect3DDevice7::DrawPrimitiveVB
4299 * Draws primitives from a vertex buffer to the screen.
4301 * Version 3 and 7
4303 * Params:
4304 * PrimitiveType: Type of primitive to be rendered.
4305 * D3DVertexBuf: Source Vertex Buffer
4306 * StartVertex: Index of the first vertex from the buffer to be rendered
4307 * NumVertices: Number of vertices to be rendered
4308 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4310 * Return values
4311 * D3D_OK on success
4312 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4314 *****************************************************************************/
4315 static HRESULT
4316 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4317 D3DPRIMITIVETYPE PrimitiveType,
4318 IDirect3DVertexBuffer7 *D3DVertexBuf,
4319 DWORD StartVertex,
4320 DWORD NumVertices,
4321 DWORD Flags)
4323 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4324 IDirect3DVertexBufferImpl *vb = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, D3DVertexBuf);
4325 UINT PrimitiveCount;
4326 HRESULT hr;
4327 DWORD stride;
4328 WINED3DVERTEXBUFFER_DESC Desc;
4330 TRACE("(%p)->(%08x,%p,%08x,%08x,%08x)\n", This, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4332 /* Sanity checks */
4333 if(!vb)
4335 ERR("(%p) No Vertex buffer specified\n", This);
4336 return DDERR_INVALIDPARAMS;
4339 /* Get the primitive count */
4340 switch(PrimitiveType)
4342 case D3DPT_POINTLIST:
4343 PrimitiveCount = NumVertices;
4344 break;
4346 case D3DPT_LINELIST:
4347 PrimitiveCount = NumVertices / 2;
4348 break;
4350 case D3DPT_LINESTRIP:
4351 PrimitiveCount = NumVertices - 1;
4352 break;
4354 case D3DPT_TRIANGLELIST:
4355 PrimitiveCount = NumVertices / 3;
4356 break;
4358 case D3DPT_TRIANGLESTRIP:
4359 PrimitiveCount = NumVertices - 2;
4360 break;
4362 case D3DPT_TRIANGLEFAN:
4363 PrimitiveCount = NumVertices - 2;
4364 break;
4366 default:
4367 return DDERR_INVALIDPARAMS;
4370 /* Get the FVF of the vertex buffer, and its stride */
4371 EnterCriticalSection(&ddraw_cs);
4372 hr = IWineD3DVertexBuffer_GetDesc(vb->wineD3DVertexBuffer,
4373 &Desc);
4374 if(hr != D3D_OK)
4376 ERR("(%p) IWineD3DVertexBuffer::GetDesc failed with hr = %08x\n", This, hr);
4377 LeaveCriticalSection(&ddraw_cs);
4378 return hr;
4380 stride = get_flexible_vertex_size(Desc.FVF);
4382 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4383 vb->wineD3DVertexDeclaration);
4384 if(FAILED(hr))
4386 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4387 LeaveCriticalSection(&ddraw_cs);
4388 return hr;
4391 /* Set the vertex stream source */
4392 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4393 0 /* StreamNumber */,
4394 vb->wineD3DVertexBuffer,
4395 0 /* StartVertex - we pass this to DrawPrimitive */,
4396 stride);
4397 if(hr != D3D_OK)
4399 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4400 LeaveCriticalSection(&ddraw_cs);
4401 return hr;
4404 /* Now draw the primitives */
4405 hr = IWineD3DDevice_DrawPrimitive(This->wineD3DDevice,
4406 PrimitiveType,
4407 StartVertex,
4408 PrimitiveCount);
4409 LeaveCriticalSection(&ddraw_cs);
4410 return hr;
4413 static HRESULT WINAPI
4414 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4415 D3DPRIMITIVETYPE PrimitiveType,
4416 IDirect3DVertexBuffer7 *D3DVertexBuf,
4417 DWORD StartVertex,
4418 DWORD NumVertices,
4419 DWORD Flags)
4421 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4424 static HRESULT WINAPI
4425 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4426 D3DPRIMITIVETYPE PrimitiveType,
4427 IDirect3DVertexBuffer7 *D3DVertexBuf,
4428 DWORD StartVertex,
4429 DWORD NumVertices,
4430 DWORD Flags)
4432 HRESULT hr;
4433 WORD old_fpucw;
4435 old_fpucw = d3d_fpu_setup();
4436 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4437 set_fpu_control_word(old_fpucw);
4439 return hr;
4442 static HRESULT WINAPI
4443 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4444 D3DPRIMITIVETYPE PrimitiveType,
4445 IDirect3DVertexBuffer *D3DVertexBuf,
4446 DWORD StartVertex,
4447 DWORD NumVertices,
4448 DWORD Flags)
4450 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4451 IDirect3DVertexBufferImpl *vb = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, D3DVertexBuf);
4452 TRACE_(ddraw_thunk)("(%p)->(%08x,%p,%08x,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, vb, StartVertex, NumVertices, Flags);
4453 return IDirect3DDevice7_DrawPrimitiveVB(ICOM_INTERFACE(This, IDirect3DDevice7),
4454 PrimitiveType,
4455 ICOM_INTERFACE(vb, IDirect3DVertexBuffer7),
4456 StartVertex,
4457 NumVertices,
4458 Flags);
4462 /*****************************************************************************
4463 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4465 * Draws primitives from a vertex buffer to the screen
4467 * Params:
4468 * PrimitiveType: Type of primitive to be rendered.
4469 * D3DVertexBuf: Source Vertex Buffer
4470 * StartVertex: Index of the first vertex from the buffer to be rendered
4471 * NumVertices: Number of vertices to be rendered
4472 * Indices: Array of DWORDs used to index into the Vertices
4473 * IndexCount: Number of indices in Indices
4474 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4476 * Return values
4478 *****************************************************************************/
4479 static HRESULT
4480 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4481 D3DPRIMITIVETYPE PrimitiveType,
4482 IDirect3DVertexBuffer7 *D3DVertexBuf,
4483 DWORD StartVertex,
4484 DWORD NumVertices,
4485 WORD *Indices,
4486 DWORD IndexCount,
4487 DWORD Flags)
4489 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4490 IDirect3DVertexBufferImpl *vb = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, D3DVertexBuf);
4491 DWORD stride;
4492 UINT PrimitiveCount;
4493 WORD *LockedIndices;
4494 HRESULT hr;
4495 WINED3DVERTEXBUFFER_DESC Desc;
4497 TRACE("(%p)->(%08x,%p,%d,%d,%p,%d,%08x)\n", This, PrimitiveType, vb, StartVertex, NumVertices, Indices, IndexCount, Flags);
4499 /* Steps:
4500 * 1) Calculate some things: Vertex count -> Primitive count, stride, ...
4501 * 2) Upload the Indices to the index buffer
4502 * 3) Set the index source
4503 * 4) Set the Vertex Buffer as the Stream source
4504 * 5) Call IWineD3DDevice::DrawIndexedPrimitive
4507 /* Get the primitive count */
4508 switch(PrimitiveType)
4510 case D3DPT_POINTLIST:
4511 PrimitiveCount = IndexCount;
4512 break;
4514 case D3DPT_LINELIST:
4515 PrimitiveCount = IndexCount / 2;
4516 break;
4518 case D3DPT_LINESTRIP:
4519 PrimitiveCount = IndexCount - 1;
4520 break;
4522 case D3DPT_TRIANGLELIST:
4523 PrimitiveCount = IndexCount / 3;
4524 break;
4526 case D3DPT_TRIANGLESTRIP:
4527 PrimitiveCount = IndexCount - 2;
4528 break;
4530 case D3DPT_TRIANGLEFAN:
4531 PrimitiveCount = IndexCount - 2;
4532 break;
4534 default: return DDERR_INVALIDPARAMS;
4537 EnterCriticalSection(&ddraw_cs);
4538 /* Get the FVF of the vertex buffer, and its stride */
4539 hr = IWineD3DVertexBuffer_GetDesc(vb->wineD3DVertexBuffer,
4540 &Desc);
4541 if(hr != D3D_OK)
4543 ERR("(%p) IWineD3DVertexBuffer::GetDesc failed with hr = %08x\n", This, hr);
4544 LeaveCriticalSection(&ddraw_cs);
4545 return hr;
4547 stride = get_flexible_vertex_size(Desc.FVF);
4548 TRACE("Vertex buffer FVF = %08x, stride=%d\n", Desc.FVF, stride);
4550 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4551 vb->wineD3DVertexDeclaration);
4552 if(FAILED(hr))
4554 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4555 LeaveCriticalSection(&ddraw_cs);
4556 return hr;
4559 /* copy the index stream into the index buffer.
4560 * A new IWineD3DDevice method could be created
4561 * which takes an user pointer containing the indices
4562 * or a SetData-Method for the index buffer, which
4563 * overrides the index buffer data with our pointer.
4565 hr = IWineD3DIndexBuffer_Lock(This->indexbuffer,
4566 0 /* OffSetToLock */,
4567 IndexCount * sizeof(WORD),
4568 (BYTE **) &LockedIndices,
4569 0 /* Flags */);
4570 assert(IndexCount < 0x100000);
4571 if(hr != D3D_OK)
4573 ERR("(%p) IWineD3DIndexBuffer::Lock failed with hr = %08x\n", This, hr);
4574 LeaveCriticalSection(&ddraw_cs);
4575 return hr;
4577 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4578 hr = IWineD3DIndexBuffer_Unlock(This->indexbuffer);
4579 if(hr != D3D_OK)
4581 ERR("(%p) IWineD3DIndexBuffer::Unlock failed with hr = %08x\n", This, hr);
4582 LeaveCriticalSection(&ddraw_cs);
4583 return hr;
4586 /* Set the index stream */
4587 IWineD3DDevice_SetBaseVertexIndex(This->wineD3DDevice, StartVertex);
4588 hr = IWineD3DDevice_SetIndices(This->wineD3DDevice, This->indexbuffer);
4590 /* Set the vertex stream source */
4591 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4592 0 /* StreamNumber */,
4593 vb->wineD3DVertexBuffer,
4594 0 /* offset, we pass this to DrawIndexedPrimitive */,
4595 stride);
4596 if(hr != D3D_OK)
4598 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4599 LeaveCriticalSection(&ddraw_cs);
4600 return hr;
4604 hr = IWineD3DDevice_DrawIndexedPrimitive(This->wineD3DDevice,
4605 PrimitiveType,
4606 0 /* minIndex */,
4607 NumVertices,
4608 0 /* StartIndex */,
4609 PrimitiveCount);
4611 LeaveCriticalSection(&ddraw_cs);
4612 return hr;
4615 static HRESULT WINAPI
4616 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4617 D3DPRIMITIVETYPE PrimitiveType,
4618 IDirect3DVertexBuffer7 *D3DVertexBuf,
4619 DWORD StartVertex,
4620 DWORD NumVertices,
4621 WORD *Indices,
4622 DWORD IndexCount,
4623 DWORD Flags)
4625 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4628 static HRESULT WINAPI
4629 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4630 D3DPRIMITIVETYPE PrimitiveType,
4631 IDirect3DVertexBuffer7 *D3DVertexBuf,
4632 DWORD StartVertex,
4633 DWORD NumVertices,
4634 WORD *Indices,
4635 DWORD IndexCount,
4636 DWORD Flags)
4638 HRESULT hr;
4639 WORD old_fpucw;
4641 old_fpucw = d3d_fpu_setup();
4642 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4643 set_fpu_control_word(old_fpucw);
4645 return hr;
4648 static HRESULT WINAPI
4649 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4650 D3DPRIMITIVETYPE PrimitiveType,
4651 IDirect3DVertexBuffer *D3DVertexBuf,
4652 WORD *Indices,
4653 DWORD IndexCount,
4654 DWORD Flags)
4656 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4657 IDirect3DVertexBufferImpl *VB = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, D3DVertexBuf);
4658 TRACE_(ddraw_thunk)("(%p)->(%08x,%p,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VB, Indices, IndexCount, Flags);
4660 return IDirect3DDevice7_DrawIndexedPrimitiveVB(ICOM_INTERFACE(This, IDirect3DDevice7),
4661 PrimitiveType,
4662 ICOM_INTERFACE(VB, IDirect3DVertexBuffer7),
4664 IndexCount,
4665 Indices,
4666 IndexCount,
4667 Flags);
4670 /*****************************************************************************
4671 * IDirect3DDevice7::ComputeSphereVisibility
4673 * Calculates the visibility of spheres in the current viewport. The spheres
4674 * are passed in the Centers and Radii arrays, the results are passed back
4675 * in the ReturnValues array. Return values are either completely visible,
4676 * partially visible or completely invisible.
4677 * The return value consist of a combination of D3DCLIP_* flags, or it's
4678 * 0 if the sphere is completely visible(according to the SDK, not checked)
4680 * Sounds like an overdose of math ;)
4682 * Version 3 and 7
4684 * Params:
4685 * Centers: Array containing the sphere centers
4686 * Radii: Array containing the sphere radii
4687 * NumSpheres: The number of centers and radii in the arrays
4688 * Flags: Some flags
4689 * ReturnValues: Array to write the results to
4691 * Returns:
4692 * D3D_OK because it's a stub
4693 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4694 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4695 * is singular)
4697 *****************************************************************************/
4698 static HRESULT WINAPI
4699 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4700 D3DVECTOR *Centers,
4701 D3DVALUE *Radii,
4702 DWORD NumSpheres,
4703 DWORD Flags,
4704 DWORD *ReturnValues)
4706 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4707 FIXME("(%p)->(%p,%p,%08x,%08x,%p): stub!\n", This, Centers, Radii, NumSpheres, Flags, ReturnValues);
4709 /* the DirectX 7 sdk says that the visibility is computed by
4710 * back-transforming the viewing frustum to model space
4711 * using the inverse of the combined world, view and projection
4712 * matrix. If the matrix can't be reversed, D3DERR_INVALIDMATRIX
4713 * is returned.
4715 * Basic implementation idea:
4716 * 1) Check if the center is in the viewing frustum
4717 * 2) Cut the sphere with the planes of the viewing
4718 * frustum
4720 * ->Center inside the frustum, no intersections:
4721 * Fully visible
4722 * ->Center outside the frustum, no intersections:
4723 * Not visible
4724 * ->Some intersections: Partially visible
4726 * Implement this call in WineD3D. Either implement the
4727 * matrix and vector stuff in WineD3D, or use some external
4728 * math library.
4731 return D3D_OK;
4734 static HRESULT WINAPI
4735 Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4736 D3DVECTOR *Centers,
4737 D3DVALUE *Radii,
4738 DWORD NumSpheres,
4739 DWORD Flags,
4740 DWORD *ReturnValues)
4742 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4743 TRACE_(ddraw_thunk)("(%p)->(%p,%p,%08x,%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, Centers, Radii, NumSpheres, Flags, ReturnValues);
4744 return IDirect3DDevice7_ComputeSphereVisibility(ICOM_INTERFACE(This, IDirect3DDevice7),
4745 Centers,
4746 Radii,
4747 NumSpheres,
4748 Flags,
4749 ReturnValues);
4752 /*****************************************************************************
4753 * IDirect3DDevice7::GetTexture
4755 * Returns the texture interface handle assigned to a texture stage.
4756 * The returned texture is AddRefed. This is taken from old ddraw,
4757 * not checked in Windows.
4759 * Version 3 and 7
4761 * Params:
4762 * Stage: Texture stage to read the texture from
4763 * Texture: Address to store the interface pointer at
4765 * Returns:
4766 * D3D_OK on success
4767 * DDERR_INVALIDPARAMS if Texture is NULL
4768 * For details, see IWineD3DDevice::GetTexture
4770 *****************************************************************************/
4771 static HRESULT
4772 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4773 DWORD Stage,
4774 IDirectDrawSurface7 **Texture)
4776 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4777 IWineD3DBaseTexture *Surf;
4778 HRESULT hr;
4779 TRACE("(%p)->(%d,%p): Relay\n", This, Stage, Texture);
4781 if(!Texture)
4783 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4784 return DDERR_INVALIDPARAMS;
4787 EnterCriticalSection(&ddraw_cs);
4788 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, Stage, &Surf);
4789 if( (hr != D3D_OK) || (!Surf) )
4791 *Texture = NULL;
4792 LeaveCriticalSection(&ddraw_cs);
4793 return hr;
4796 /* GetParent AddRef()s, which is perfectly OK.
4797 * We have passed the IDirectDrawSurface7 interface to WineD3D, so that's OK too.
4799 hr = IWineD3DBaseTexture_GetParent(Surf,
4800 (IUnknown **) Texture);
4801 LeaveCriticalSection(&ddraw_cs);
4802 return hr;
4805 static HRESULT WINAPI
4806 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4807 DWORD Stage,
4808 IDirectDrawSurface7 **Texture)
4810 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4813 static HRESULT WINAPI
4814 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4815 DWORD Stage,
4816 IDirectDrawSurface7 **Texture)
4818 HRESULT hr;
4819 WORD old_fpucw;
4821 old_fpucw = d3d_fpu_setup();
4822 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4823 set_fpu_control_word(old_fpucw);
4825 return hr;
4828 static HRESULT WINAPI
4829 Thunk_IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface,
4830 DWORD Stage,
4831 IDirect3DTexture2 **Texture2)
4833 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4834 HRESULT ret;
4835 IDirectDrawSurface7 *ret_val;
4837 TRACE_(ddraw_thunk)("(%p)->(%d,%p) thunking to IDirect3DDevice7 interface.\n", This, Stage, Texture2);
4838 ret = IDirect3DDevice7_GetTexture(ICOM_INTERFACE(This, IDirect3DDevice7),
4839 Stage,
4840 &ret_val);
4842 *Texture2 = COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirectDrawSurface7, IDirect3DTexture2, ret_val);
4844 TRACE_(ddraw_thunk)(" returning interface %p.\n", *Texture2);
4846 return ret;
4849 /*****************************************************************************
4850 * IDirect3DDevice7::SetTexture
4852 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4854 * Version 3 and 7
4856 * Params:
4857 * Stage: The stage to assign the texture to
4858 * Texture: Interface pointer to the texture surface
4860 * Returns
4861 * D3D_OK on success
4862 * For details, see IWineD3DDevice::SetTexture
4864 *****************************************************************************/
4865 static HRESULT
4866 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4867 DWORD Stage,
4868 IDirectDrawSurface7 *Texture)
4870 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4871 IDirectDrawSurfaceImpl *surf = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, Texture);
4872 HRESULT hr;
4873 TRACE("(%p)->(%08x,%p): Relay!\n", This, Stage, surf);
4875 /* Texture may be NULL here */
4876 EnterCriticalSection(&ddraw_cs);
4877 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
4878 Stage,
4879 surf ? surf->wineD3DTexture : NULL);
4880 LeaveCriticalSection(&ddraw_cs);
4881 return hr;
4884 static HRESULT WINAPI
4885 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4886 DWORD Stage,
4887 IDirectDrawSurface7 *Texture)
4889 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4892 static HRESULT WINAPI
4893 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4894 DWORD Stage,
4895 IDirectDrawSurface7 *Texture)
4897 HRESULT hr;
4898 WORD old_fpucw;
4900 old_fpucw = d3d_fpu_setup();
4901 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4902 set_fpu_control_word(old_fpucw);
4904 return hr;
4907 static HRESULT WINAPI
4908 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4909 DWORD Stage,
4910 IDirect3DTexture2 *Texture2)
4912 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4913 IDirectDrawSurfaceImpl *tex = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture2, Texture2);
4914 DWORD texmapblend;
4915 HRESULT hr;
4916 TRACE("(%p)->(%d,%p)\n", This, Stage, tex);
4918 EnterCriticalSection(&ddraw_cs);
4920 if (This->legacyTextureBlending)
4921 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4923 hr = IDirect3DDevice7_SetTexture(ICOM_INTERFACE(This, IDirect3DDevice7),
4924 Stage,
4925 ICOM_INTERFACE(tex, IDirectDrawSurface7));
4927 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4929 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4930 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4931 BOOL tex_alpha = FALSE;
4932 IWineD3DBaseTexture *tex = NULL;
4933 WINED3DSURFACE_DESC desc;
4934 WINED3DFORMAT fmt;
4935 DDPIXELFORMAT ddfmt;
4936 HRESULT result;
4938 result = IWineD3DDevice_GetTexture(This->wineD3DDevice,
4940 &tex);
4942 if(result == WINED3D_OK && tex)
4944 memset(&desc, 0, sizeof(desc));
4945 desc.Format = &fmt;
4946 result = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
4947 if (SUCCEEDED(result))
4949 ddfmt.dwSize = sizeof(ddfmt);
4950 PixelFormat_WineD3DtoDD(&ddfmt, fmt);
4951 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4954 IWineD3DBaseTexture_Release(tex);
4957 /* alphaop is WINED3DTOP_SELECTARG1 if it's D3DTBLEND_MODULATE, so only modify alphaarg1 */
4958 if (tex_alpha)
4960 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
4962 else
4964 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_CURRENT);
4968 LeaveCriticalSection(&ddraw_cs);
4970 return hr;
4973 /*****************************************************************************
4974 * IDirect3DDevice7::GetTextureStageState
4976 * Retrieves a state from a texture stage.
4978 * Version 3 and 7
4980 * Params:
4981 * Stage: The stage to retrieve the state from
4982 * TexStageStateType: The state type to retrieve
4983 * State: Address to store the state's value at
4985 * Returns:
4986 * D3D_OK on success
4987 * DDERR_INVALIDPARAMS if State is NULL
4988 * For details, see IWineD3DDevice::GetTextureStageState
4990 *****************************************************************************/
4991 static HRESULT
4992 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4993 DWORD Stage,
4994 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4995 DWORD *State)
4997 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4998 HRESULT hr;
4999 TRACE("(%p)->(%08x,%08x,%p): Relay!\n", This, Stage, TexStageStateType, State);
5001 if(!State)
5002 return DDERR_INVALIDPARAMS;
5004 EnterCriticalSection(&ddraw_cs);
5005 switch(TexStageStateType)
5007 /* Mipfilter is a sampler state with different values */
5008 case D3DTSS_MIPFILTER:
5010 WINED3DTEXTUREFILTERTYPE value;
5012 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
5013 Stage,
5014 WINED3DSAMP_MIPFILTER,
5015 &value);
5016 switch(value)
5018 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
5019 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
5020 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
5021 default:
5022 ERR("Unexpected mipfilter value %d\n", value);
5023 *State = D3DTFP_NONE;
5025 break;
5028 /* Minfilter is a sampler state too, equal values */
5029 case D3DTSS_MINFILTER:
5030 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
5031 Stage,
5032 WINED3DSAMP_MINFILTER,
5033 State);
5034 break;
5036 /* Magfilter has slightly different values */
5037 case D3DTSS_MAGFILTER:
5039 WINED3DTEXTUREFILTERTYPE wined3dfilter;
5040 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
5041 Stage,
5042 WINED3DSAMP_MAGFILTER,
5043 &wined3dfilter);
5044 switch(wined3dfilter)
5046 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
5047 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
5048 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
5049 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
5050 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
5051 default:
5052 ERR("Unexpected wined3d mag filter value %d\n", wined3dfilter);
5053 *State = D3DTFG_POINT;
5055 break;
5058 case D3DTSS_ADDRESS:
5059 case D3DTSS_ADDRESSU:
5060 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
5061 Stage,
5062 WINED3DSAMP_ADDRESSU,
5063 State);
5064 break;
5065 case D3DTSS_ADDRESSV:
5066 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
5067 Stage,
5068 WINED3DSAMP_ADDRESSV,
5069 State);
5070 break;
5071 default:
5072 hr = IWineD3DDevice_GetTextureStageState(This->wineD3DDevice,
5073 Stage,
5074 TexStageStateType,
5075 State);
5076 break;
5078 LeaveCriticalSection(&ddraw_cs);
5079 return hr;
5082 static HRESULT WINAPI
5083 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5084 DWORD Stage,
5085 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5086 DWORD *State)
5088 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
5091 static HRESULT WINAPI
5092 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5093 DWORD Stage,
5094 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5095 DWORD *State)
5097 HRESULT hr;
5098 WORD old_fpucw;
5100 old_fpucw = d3d_fpu_setup();
5101 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
5102 set_fpu_control_word(old_fpucw);
5104 return hr;
5107 static HRESULT WINAPI
5108 Thunk_IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
5109 DWORD Stage,
5110 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5111 DWORD *State)
5113 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
5114 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, Stage, TexStageStateType, State);
5115 return IDirect3DDevice7_GetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
5116 Stage,
5117 TexStageStateType,
5118 State);
5121 /*****************************************************************************
5122 * IDirect3DDevice7::SetTextureStageState
5124 * Sets a texture stage state. Some stage types need to be handled specially,
5125 * because they do not exist in WineD3D and were moved to another place
5127 * Version 3 and 7
5129 * Params:
5130 * Stage: The stage to modify
5131 * TexStageStateType: The state to change
5132 * State: The new value for the state
5134 * Returns:
5135 * D3D_OK on success
5136 * For details, see IWineD3DDevice::SetTextureStageState
5138 *****************************************************************************/
5139 static HRESULT
5140 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
5141 DWORD Stage,
5142 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5143 DWORD State)
5145 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5146 HRESULT hr;
5147 TRACE("(%p)->(%08x,%08x,%08x): Relay!\n", This, Stage, TexStageStateType, State);
5149 EnterCriticalSection(&ddraw_cs);
5150 switch(TexStageStateType)
5152 /* Mipfilter is a sampler state with different values */
5153 case D3DTSS_MIPFILTER:
5155 WINED3DTEXTUREFILTERTYPE value;
5156 switch(State)
5158 case D3DTFP_NONE: value = WINED3DTEXF_NONE; break;
5159 case D3DTFP_POINT: value = WINED3DTEXF_POINT; break;
5160 case 0: /* Unchecked */
5161 case D3DTFP_LINEAR: value = WINED3DTEXF_LINEAR; break;
5162 default:
5163 ERR("Unexpected mipfilter value %d\n", State);
5164 value = WINED3DTEXF_NONE;
5166 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
5167 Stage,
5168 WINED3DSAMP_MIPFILTER,
5169 value);
5170 break;
5173 /* Minfilter is a sampler state too, equal values */
5174 case D3DTSS_MINFILTER:
5175 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
5176 Stage,
5177 WINED3DSAMP_MINFILTER,
5178 State);
5179 break;
5181 /* Magfilter has slightly different values */
5182 case D3DTSS_MAGFILTER:
5184 WINED3DTEXTUREFILTERTYPE wined3dfilter;
5185 switch((D3DTEXTUREMAGFILTER) State)
5187 case D3DTFG_POINT: wined3dfilter = WINED3DTEXF_POINT; break;
5188 case D3DTFG_LINEAR: wined3dfilter = WINED3DTEXF_LINEAR; break;
5189 case D3DTFG_FLATCUBIC: wined3dfilter = WINED3DTEXF_FLATCUBIC; break;
5190 case D3DTFG_GAUSSIANCUBIC: wined3dfilter = WINED3DTEXF_GAUSSIANCUBIC; break;
5191 case D3DTFG_ANISOTROPIC: wined3dfilter = WINED3DTEXF_ANISOTROPIC; break;
5192 default:
5193 ERR("Unexpected d3d7 mag filter type %d\n", State);
5194 wined3dfilter = WINED3DTEXF_POINT;
5196 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
5197 Stage,
5198 WINED3DSAMP_MAGFILTER,
5199 wined3dfilter);
5200 break;
5203 case D3DTSS_ADDRESS:
5204 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
5205 Stage,
5206 WINED3DSAMP_ADDRESSV,
5207 State);
5208 /* Drop through */
5209 case D3DTSS_ADDRESSU:
5210 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
5211 Stage,
5212 WINED3DSAMP_ADDRESSU,
5213 State);
5214 break;
5216 case D3DTSS_ADDRESSV:
5217 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
5218 Stage,
5219 WINED3DSAMP_ADDRESSV,
5220 State);
5221 break;
5223 default:
5224 hr = IWineD3DDevice_SetTextureStageState(This->wineD3DDevice,
5225 Stage,
5226 TexStageStateType,
5227 State);
5228 break;
5230 LeaveCriticalSection(&ddraw_cs);
5231 return hr;
5234 static HRESULT WINAPI
5235 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5236 DWORD Stage,
5237 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5238 DWORD State)
5240 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5243 static HRESULT WINAPI
5244 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5245 DWORD Stage,
5246 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5247 DWORD State)
5249 HRESULT hr;
5250 WORD old_fpucw;
5252 old_fpucw = d3d_fpu_setup();
5253 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5254 set_fpu_control_word(old_fpucw);
5256 return hr;
5259 static HRESULT WINAPI
5260 Thunk_IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
5261 DWORD Stage,
5262 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5263 DWORD State)
5265 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
5266 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, Stage, TexStageStateType, State);
5267 return IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
5268 Stage,
5269 TexStageStateType,
5270 State);
5273 /*****************************************************************************
5274 * IDirect3DDevice7::ValidateDevice
5276 * SDK: "Reports the device's ability to render the currently set
5277 * texture-blending operations in a single pass". Whatever that means
5278 * exactly...
5280 * Version 3 and 7
5282 * Params:
5283 * NumPasses: Address to write the number of necessary passes for the
5284 * desired effect to.
5286 * Returns:
5287 * D3D_OK on success
5288 * See IWineD3DDevice::ValidateDevice for more details
5290 *****************************************************************************/
5291 static HRESULT
5292 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
5293 DWORD *NumPasses)
5295 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5296 HRESULT hr;
5297 TRACE("(%p)->(%p): Relay\n", This, NumPasses);
5299 EnterCriticalSection(&ddraw_cs);
5300 hr = IWineD3DDevice_ValidateDevice(This->wineD3DDevice, NumPasses);
5301 LeaveCriticalSection(&ddraw_cs);
5302 return hr;
5305 static HRESULT WINAPI
5306 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
5307 DWORD *NumPasses)
5309 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5312 static HRESULT WINAPI
5313 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
5314 DWORD *NumPasses)
5316 HRESULT hr;
5317 WORD old_fpucw;
5319 old_fpucw = d3d_fpu_setup();
5320 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5321 set_fpu_control_word(old_fpucw);
5323 return hr;
5326 static HRESULT WINAPI
5327 Thunk_IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface,
5328 DWORD *Passes)
5330 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
5331 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Passes);
5332 return IDirect3DDevice7_ValidateDevice(ICOM_INTERFACE(This, IDirect3DDevice7),
5333 Passes);
5336 /*****************************************************************************
5337 * IDirect3DDevice7::Clear
5339 * Fills the render target, the z buffer and the stencil buffer with a
5340 * clear color / value
5342 * Version 7 only
5344 * Params:
5345 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5346 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5347 * Flags: Some flags, as usual
5348 * Color: Clear color for the render target
5349 * Z: Clear value for the Z buffer
5350 * Stencil: Clear value to store in each stencil buffer entry
5352 * Returns:
5353 * D3D_OK on success
5354 * For details, see IWineD3DDevice::Clear
5356 *****************************************************************************/
5357 static HRESULT
5358 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
5359 DWORD Count,
5360 D3DRECT *Rects,
5361 DWORD Flags,
5362 D3DCOLOR Color,
5363 D3DVALUE Z,
5364 DWORD Stencil)
5366 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5367 HRESULT hr;
5368 TRACE("(%p)->(%08x,%p,%08x,%08x,%f,%08x): Relay\n", This, Count, Rects, Flags, Color, Z, Stencil);
5370 /* Note; D3DRECT is compatible with WINED3DRECT */
5371 EnterCriticalSection(&ddraw_cs);
5372 hr = IWineD3DDevice_Clear(This->wineD3DDevice, Count, (WINED3DRECT*) Rects, Flags, Color, Z, Stencil);
5373 LeaveCriticalSection(&ddraw_cs);
5374 return hr;
5377 static HRESULT WINAPI
5378 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5379 DWORD Count,
5380 D3DRECT *Rects,
5381 DWORD Flags,
5382 D3DCOLOR Color,
5383 D3DVALUE Z,
5384 DWORD Stencil)
5386 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5389 static HRESULT WINAPI
5390 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5391 DWORD Count,
5392 D3DRECT *Rects,
5393 DWORD Flags,
5394 D3DCOLOR Color,
5395 D3DVALUE Z,
5396 DWORD Stencil)
5398 HRESULT hr;
5399 WORD old_fpucw;
5401 old_fpucw = d3d_fpu_setup();
5402 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5403 set_fpu_control_word(old_fpucw);
5405 return hr;
5408 /*****************************************************************************
5409 * IDirect3DDevice7::SetViewport
5411 * Sets the current viewport.
5413 * Version 7 only, but IDirect3DViewport uses this call for older
5414 * versions
5416 * Params:
5417 * Data: The new viewport to set
5419 * Returns:
5420 * D3D_OK on success
5421 * DDERR_INVALIDPARAMS if Data is NULL
5422 * For more details, see IWineDDDevice::SetViewport
5424 *****************************************************************************/
5425 static HRESULT
5426 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5427 D3DVIEWPORT7 *Data)
5429 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5430 HRESULT hr;
5431 TRACE("(%p)->(%p) Relay!\n", This, Data);
5433 if(!Data)
5434 return DDERR_INVALIDPARAMS;
5436 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5437 EnterCriticalSection(&ddraw_cs);
5438 hr = IWineD3DDevice_SetViewport(This->wineD3DDevice,
5439 (WINED3DVIEWPORT*) Data);
5440 LeaveCriticalSection(&ddraw_cs);
5441 return hr;
5444 static HRESULT WINAPI
5445 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5446 D3DVIEWPORT7 *Data)
5448 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5451 static HRESULT WINAPI
5452 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5453 D3DVIEWPORT7 *Data)
5455 HRESULT hr;
5456 WORD old_fpucw;
5458 old_fpucw = d3d_fpu_setup();
5459 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5460 set_fpu_control_word(old_fpucw);
5462 return hr;
5465 /*****************************************************************************
5466 * IDirect3DDevice::GetViewport
5468 * Returns the current viewport
5470 * Version 7
5472 * Params:
5473 * Data: D3D7Viewport structure to write the viewport information to
5475 * Returns:
5476 * D3D_OK on success
5477 * DDERR_INVALIDPARAMS if Data is NULL
5478 * For more details, see IWineD3DDevice::GetViewport
5480 *****************************************************************************/
5481 static HRESULT
5482 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5483 D3DVIEWPORT7 *Data)
5485 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5486 HRESULT hr;
5487 TRACE("(%p)->(%p) Relay!\n", This, Data);
5489 if(!Data)
5490 return DDERR_INVALIDPARAMS;
5492 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5493 EnterCriticalSection(&ddraw_cs);
5494 hr = IWineD3DDevice_GetViewport(This->wineD3DDevice,
5495 (WINED3DVIEWPORT*) Data);
5497 LeaveCriticalSection(&ddraw_cs);
5498 return hr_ddraw_from_wined3d(hr);
5501 static HRESULT WINAPI
5502 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5503 D3DVIEWPORT7 *Data)
5505 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5508 static HRESULT WINAPI
5509 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5510 D3DVIEWPORT7 *Data)
5512 HRESULT hr;
5513 WORD old_fpucw;
5515 old_fpucw = d3d_fpu_setup();
5516 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5517 set_fpu_control_word(old_fpucw);
5519 return hr;
5522 /*****************************************************************************
5523 * IDirect3DDevice7::SetMaterial
5525 * Sets the Material
5527 * Version 7
5529 * Params:
5530 * Mat: The material to set
5532 * Returns:
5533 * D3D_OK on success
5534 * DDERR_INVALIDPARAMS if Mat is NULL.
5535 * For more details, see IWineD3DDevice::SetMaterial
5537 *****************************************************************************/
5538 static HRESULT
5539 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5540 D3DMATERIAL7 *Mat)
5542 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5543 HRESULT hr;
5544 TRACE("(%p)->(%p): Relay!\n", This, Mat);
5546 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5547 EnterCriticalSection(&ddraw_cs);
5548 hr = IWineD3DDevice_SetMaterial(This->wineD3DDevice,
5549 (WINED3DMATERIAL*) Mat);
5550 LeaveCriticalSection(&ddraw_cs);
5551 return hr_ddraw_from_wined3d(hr);
5554 static HRESULT WINAPI
5555 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5556 D3DMATERIAL7 *Mat)
5558 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5561 static HRESULT WINAPI
5562 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5563 D3DMATERIAL7 *Mat)
5565 HRESULT hr;
5566 WORD old_fpucw;
5568 old_fpucw = d3d_fpu_setup();
5569 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5570 set_fpu_control_word(old_fpucw);
5572 return hr;
5575 /*****************************************************************************
5576 * IDirect3DDevice7::GetMaterial
5578 * Returns the current material
5580 * Version 7
5582 * Params:
5583 * Mat: D3DMATERIAL7 structure to write the material parameters to
5585 * Returns:
5586 * D3D_OK on success
5587 * DDERR_INVALIDPARAMS if Mat is NULL
5588 * For more details, see IWineD3DDevice::GetMaterial
5590 *****************************************************************************/
5591 static HRESULT
5592 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5593 D3DMATERIAL7 *Mat)
5595 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5596 HRESULT hr;
5597 TRACE("(%p)->(%p): Relay!\n", This, Mat);
5599 EnterCriticalSection(&ddraw_cs);
5600 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5601 hr = IWineD3DDevice_GetMaterial(This->wineD3DDevice,
5602 (WINED3DMATERIAL*) Mat);
5603 LeaveCriticalSection(&ddraw_cs);
5604 return hr_ddraw_from_wined3d(hr);
5607 static HRESULT WINAPI
5608 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5609 D3DMATERIAL7 *Mat)
5611 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5614 static HRESULT WINAPI
5615 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5616 D3DMATERIAL7 *Mat)
5618 HRESULT hr;
5619 WORD old_fpucw;
5621 old_fpucw = d3d_fpu_setup();
5622 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5623 set_fpu_control_word(old_fpucw);
5625 return hr;
5628 /*****************************************************************************
5629 * IDirect3DDevice7::SetLight
5631 * Assigns a light to a light index, but doesn't activate it yet.
5633 * Version 7, IDirect3DLight uses this method for older versions
5635 * Params:
5636 * LightIndex: The index of the new light
5637 * Light: A D3DLIGHT7 structure describing the light
5639 * Returns:
5640 * D3D_OK on success
5641 * For more details, see IWineD3DDevice::SetLight
5643 *****************************************************************************/
5644 static HRESULT
5645 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5646 DWORD LightIndex,
5647 D3DLIGHT7 *Light)
5649 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5650 HRESULT hr;
5651 TRACE("(%p)->(%08x,%p): Relay!\n", This, LightIndex, Light);
5653 EnterCriticalSection(&ddraw_cs);
5654 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5655 hr = IWineD3DDevice_SetLight(This->wineD3DDevice,
5656 LightIndex,
5657 (WINED3DLIGHT*) Light);
5658 LeaveCriticalSection(&ddraw_cs);
5659 return hr_ddraw_from_wined3d(hr);
5662 static HRESULT WINAPI
5663 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5664 DWORD LightIndex,
5665 D3DLIGHT7 *Light)
5667 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5670 static HRESULT WINAPI
5671 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5672 DWORD LightIndex,
5673 D3DLIGHT7 *Light)
5675 HRESULT hr;
5676 WORD old_fpucw;
5678 old_fpucw = d3d_fpu_setup();
5679 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5680 set_fpu_control_word(old_fpucw);
5682 return hr;
5685 /*****************************************************************************
5686 * IDirect3DDevice7::GetLight
5688 * Returns the light assigned to a light index
5690 * Params:
5691 * Light: Structure to write the light information to
5693 * Returns:
5694 * D3D_OK on success
5695 * DDERR_INVALIDPARAMS if Light is NULL
5696 * For details, see IWineD3DDevice::GetLight
5698 *****************************************************************************/
5699 static HRESULT
5700 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5701 DWORD LightIndex,
5702 D3DLIGHT7 *Light)
5704 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5705 HRESULT rc;
5706 TRACE("(%p)->(%08x,%p): Relay!\n", This, LightIndex, Light);
5708 EnterCriticalSection(&ddraw_cs);
5709 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5710 rc = IWineD3DDevice_GetLight(This->wineD3DDevice,
5711 LightIndex,
5712 (WINED3DLIGHT*) Light);
5714 /* Translate the result. WineD3D returns other values than D3D7 */
5715 LeaveCriticalSection(&ddraw_cs);
5716 return hr_ddraw_from_wined3d(rc);
5719 static HRESULT WINAPI
5720 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5721 DWORD LightIndex,
5722 D3DLIGHT7 *Light)
5724 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5727 static HRESULT WINAPI
5728 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5729 DWORD LightIndex,
5730 D3DLIGHT7 *Light)
5732 HRESULT hr;
5733 WORD old_fpucw;
5735 old_fpucw = d3d_fpu_setup();
5736 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5737 set_fpu_control_word(old_fpucw);
5739 return hr;
5742 /*****************************************************************************
5743 * IDirect3DDevice7::BeginStateBlock
5745 * Begins recording to a stateblock
5747 * Version 7
5749 * Returns:
5750 * D3D_OK on success
5751 * For details see IWineD3DDevice::BeginStateBlock
5753 *****************************************************************************/
5754 static HRESULT
5755 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5757 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5758 HRESULT hr;
5759 TRACE("(%p)->(): Relay!\n", This);
5761 EnterCriticalSection(&ddraw_cs);
5762 hr = IWineD3DDevice_BeginStateBlock(This->wineD3DDevice);
5763 LeaveCriticalSection(&ddraw_cs);
5764 return hr_ddraw_from_wined3d(hr);
5767 static HRESULT WINAPI
5768 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5770 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5773 static HRESULT WINAPI
5774 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5776 HRESULT hr;
5777 WORD old_fpucw;
5779 old_fpucw = d3d_fpu_setup();
5780 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5781 set_fpu_control_word(old_fpucw);
5783 return hr;
5786 /*****************************************************************************
5787 * IDirect3DDevice7::EndStateBlock
5789 * Stops recording to a state block and returns the created stateblock
5790 * handle.
5792 * Version 7
5794 * Params:
5795 * BlockHandle: Address to store the stateblock's handle to
5797 * Returns:
5798 * D3D_OK on success
5799 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5800 * See IWineD3DDevice::EndStateBlock for more details
5802 *****************************************************************************/
5803 static HRESULT
5804 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5805 DWORD *BlockHandle)
5807 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5808 HRESULT hr;
5809 TRACE("(%p)->(%p): Relay!\n", This, BlockHandle);
5811 if(!BlockHandle)
5813 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5814 return DDERR_INVALIDPARAMS;
5817 EnterCriticalSection(&ddraw_cs);
5818 *BlockHandle = IDirect3DDeviceImpl_CreateHandle(This);
5819 if(!*BlockHandle)
5821 ERR("Cannot get a handle number for the stateblock\n");
5822 LeaveCriticalSection(&ddraw_cs);
5823 return DDERR_OUTOFMEMORY;
5825 This->Handles[*BlockHandle - 1].type = DDrawHandle_StateBlock;
5826 hr = IWineD3DDevice_EndStateBlock(This->wineD3DDevice,
5827 (IWineD3DStateBlock **) &This->Handles[*BlockHandle - 1].ptr);
5828 LeaveCriticalSection(&ddraw_cs);
5829 return hr_ddraw_from_wined3d(hr);
5832 static HRESULT WINAPI
5833 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5834 DWORD *BlockHandle)
5836 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5839 static HRESULT WINAPI
5840 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5841 DWORD *BlockHandle)
5843 HRESULT hr;
5844 WORD old_fpucw;
5846 old_fpucw = d3d_fpu_setup();
5847 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5848 set_fpu_control_word(old_fpucw);
5850 return hr;
5853 /*****************************************************************************
5854 * IDirect3DDevice7::PreLoad
5856 * Allows the app to signal that a texture will be used soon, to allow
5857 * the Direct3DDevice to load it to the video card in the meantime.
5859 * Version 7
5861 * Params:
5862 * Texture: The texture to preload
5864 * Returns:
5865 * D3D_OK on success
5866 * DDERR_INVALIDPARAMS if Texture is NULL
5867 * See IWineD3DSurface::PreLoad for details
5869 *****************************************************************************/
5870 static HRESULT
5871 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5872 IDirectDrawSurface7 *Texture)
5874 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5875 IDirectDrawSurfaceImpl *surf = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, Texture);
5877 TRACE("(%p)->(%p): Relay!\n", This, surf);
5879 if(!Texture)
5880 return DDERR_INVALIDPARAMS;
5882 EnterCriticalSection(&ddraw_cs);
5883 IWineD3DSurface_PreLoad(surf->WineD3DSurface);
5884 LeaveCriticalSection(&ddraw_cs);
5885 return D3D_OK;
5888 static HRESULT WINAPI
5889 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5890 IDirectDrawSurface7 *Texture)
5892 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5895 static HRESULT WINAPI
5896 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5897 IDirectDrawSurface7 *Texture)
5899 HRESULT hr;
5900 WORD old_fpucw;
5902 old_fpucw = d3d_fpu_setup();
5903 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5904 set_fpu_control_word(old_fpucw);
5906 return hr;
5909 /*****************************************************************************
5910 * IDirect3DDevice7::ApplyStateBlock
5912 * Activates the state stored in a state block handle.
5914 * Params:
5915 * BlockHandle: The stateblock handle to activate
5917 * Returns:
5918 * D3D_OK on success
5919 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5921 *****************************************************************************/
5922 static HRESULT
5923 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5924 DWORD BlockHandle)
5926 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5927 HRESULT hr;
5928 TRACE("(%p)->(%08x): Relay!\n", This, BlockHandle);
5930 EnterCriticalSection(&ddraw_cs);
5931 if(!BlockHandle || BlockHandle > This->numHandles)
5933 WARN("Out of range handle %d, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5934 LeaveCriticalSection(&ddraw_cs);
5935 return D3DERR_INVALIDSTATEBLOCK;
5937 if(This->Handles[BlockHandle - 1].type != DDrawHandle_StateBlock)
5939 WARN("Handle %d is not a stateblock, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5940 LeaveCriticalSection(&ddraw_cs);
5941 return D3DERR_INVALIDSTATEBLOCK;
5944 hr = IWineD3DStateBlock_Apply((IWineD3DStateBlock *) This->Handles[BlockHandle - 1].ptr);
5945 LeaveCriticalSection(&ddraw_cs);
5946 return hr_ddraw_from_wined3d(hr);
5949 static HRESULT WINAPI
5950 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5951 DWORD BlockHandle)
5953 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5956 static HRESULT WINAPI
5957 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5958 DWORD BlockHandle)
5960 HRESULT hr;
5961 WORD old_fpucw;
5963 old_fpucw = d3d_fpu_setup();
5964 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5965 set_fpu_control_word(old_fpucw);
5967 return hr;
5970 /*****************************************************************************
5971 * IDirect3DDevice7::CaptureStateBlock
5973 * Updates a stateblock's values to the values currently set for the device
5975 * Version 7
5977 * Params:
5978 * BlockHandle: Stateblock to update
5980 * Returns:
5981 * D3D_OK on success
5982 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5983 * See IWineD3DDevice::CaptureStateBlock for more details
5985 *****************************************************************************/
5986 static HRESULT
5987 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5988 DWORD BlockHandle)
5990 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5991 HRESULT hr;
5992 TRACE("(%p)->(%08x): Relay!\n", This, BlockHandle);
5994 EnterCriticalSection(&ddraw_cs);
5995 if(BlockHandle == 0 || BlockHandle > This->numHandles)
5997 WARN("Out of range handle %d, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5998 LeaveCriticalSection(&ddraw_cs);
5999 return D3DERR_INVALIDSTATEBLOCK;
6001 if(This->Handles[BlockHandle - 1].type != DDrawHandle_StateBlock)
6003 WARN("Handle %d is not a stateblock, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
6004 LeaveCriticalSection(&ddraw_cs);
6005 return D3DERR_INVALIDSTATEBLOCK;
6008 hr = IWineD3DStateBlock_Capture((IWineD3DStateBlock *) This->Handles[BlockHandle - 1].ptr);
6009 LeaveCriticalSection(&ddraw_cs);
6010 return hr_ddraw_from_wined3d(hr);
6013 static HRESULT WINAPI
6014 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
6015 DWORD BlockHandle)
6017 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
6020 static HRESULT WINAPI
6021 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
6022 DWORD BlockHandle)
6024 HRESULT hr;
6025 WORD old_fpucw;
6027 old_fpucw = d3d_fpu_setup();
6028 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
6029 set_fpu_control_word(old_fpucw);
6031 return hr;
6034 /*****************************************************************************
6035 * IDirect3DDevice7::DeleteStateBlock
6037 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
6039 * Version 7
6041 * Params:
6042 * BlockHandle: Stateblock handle to delete
6044 * Returns:
6045 * D3D_OK on success
6046 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
6048 *****************************************************************************/
6049 static HRESULT
6050 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
6051 DWORD BlockHandle)
6053 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6054 ULONG ref;
6055 TRACE("(%p)->(%08x): Relay!\n", This, BlockHandle);
6057 EnterCriticalSection(&ddraw_cs);
6058 if(BlockHandle == 0 || BlockHandle > This->numHandles)
6060 WARN("Out of range handle %d, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
6061 LeaveCriticalSection(&ddraw_cs);
6062 return D3DERR_INVALIDSTATEBLOCK;
6064 if(This->Handles[BlockHandle - 1].type != DDrawHandle_StateBlock)
6066 WARN("Handle %d is not a stateblock, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
6067 LeaveCriticalSection(&ddraw_cs);
6068 return D3DERR_INVALIDSTATEBLOCK;
6071 ref = IWineD3DStateBlock_Release((IWineD3DStateBlock *) This->Handles[BlockHandle - 1].ptr);
6072 if(ref)
6074 ERR("Something is still holding the stateblock %p(Handle %d). Ref = %d\n", This->Handles[BlockHandle - 1].ptr, BlockHandle, ref);
6076 This->Handles[BlockHandle - 1].ptr = NULL;
6077 This->Handles[BlockHandle - 1].type = DDrawHandle_Unknown;
6079 LeaveCriticalSection(&ddraw_cs);
6080 return D3D_OK;
6083 static HRESULT WINAPI
6084 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
6085 DWORD BlockHandle)
6087 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
6090 static HRESULT WINAPI
6091 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
6092 DWORD BlockHandle)
6094 HRESULT hr;
6095 WORD old_fpucw;
6097 old_fpucw = d3d_fpu_setup();
6098 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
6099 set_fpu_control_word(old_fpucw);
6101 return hr;
6104 /*****************************************************************************
6105 * IDirect3DDevice7::CreateStateBlock
6107 * Creates a new state block handle.
6109 * Version 7
6111 * Params:
6112 * Type: The state block type
6113 * BlockHandle: Address to write the created handle to
6115 * Returns:
6116 * D3D_OK on success
6117 * DDERR_INVALIDPARAMS if BlockHandle is NULL
6119 *****************************************************************************/
6120 static HRESULT
6121 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
6122 D3DSTATEBLOCKTYPE Type,
6123 DWORD *BlockHandle)
6125 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6126 HRESULT hr;
6127 TRACE("(%p)->(%08x,%p)!\n", This, Type, BlockHandle);
6129 if(!BlockHandle)
6131 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
6132 return DDERR_INVALIDPARAMS;
6134 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
6135 Type != D3DSBT_VERTEXSTATE ) {
6136 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
6137 return DDERR_INVALIDPARAMS;
6140 EnterCriticalSection(&ddraw_cs);
6141 *BlockHandle = IDirect3DDeviceImpl_CreateHandle(This);
6142 if(!*BlockHandle)
6144 ERR("Cannot get a handle number for the stateblock\n");
6145 LeaveCriticalSection(&ddraw_cs);
6146 return DDERR_OUTOFMEMORY;
6148 This->Handles[*BlockHandle - 1].type = DDrawHandle_StateBlock;
6150 /* The D3DSTATEBLOCKTYPE enum is fine here */
6151 hr = IWineD3DDevice_CreateStateBlock(This->wineD3DDevice,
6152 Type,
6153 (IWineD3DStateBlock **) &This->Handles[*BlockHandle - 1].ptr,
6154 NULL /* Parent, hope that works */);
6155 LeaveCriticalSection(&ddraw_cs);
6156 return hr_ddraw_from_wined3d(hr);
6159 static HRESULT WINAPI
6160 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
6161 D3DSTATEBLOCKTYPE Type,
6162 DWORD *BlockHandle)
6164 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6167 static HRESULT WINAPI
6168 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
6169 D3DSTATEBLOCKTYPE Type,
6170 DWORD *BlockHandle)
6172 HRESULT hr;
6173 WORD old_fpucw;
6175 old_fpucw = d3d_fpu_setup();
6176 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6177 set_fpu_control_word(old_fpucw);
6179 return hr;
6182 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6183 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
6184 IDirectDrawSurfaceImpl *src)
6186 IDirectDrawSurfaceImpl *src_level, *dest_level;
6187 IDirectDrawSurface7 *temp;
6188 DDSURFACEDESC2 ddsd;
6189 BOOL levelFound; /* at least one suitable sublevel in dest found */
6191 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
6192 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
6193 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
6195 levelFound = FALSE;
6197 src_level = src;
6198 dest_level = dest;
6200 for (;src_level && dest_level;)
6202 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6203 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6205 levelFound = TRUE;
6207 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6208 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6209 IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(dest_level, IDirectDrawSurface7), &ddsd.ddsCaps, &temp);
6211 if (dest_level != dest) IDirectDrawSurface7_Release(ICOM_INTERFACE(dest_level, IDirectDrawSurface7));
6213 dest_level = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, temp);
6216 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6217 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6218 IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(src_level, IDirectDrawSurface7), &ddsd.ddsCaps, &temp);
6220 if (src_level != src) IDirectDrawSurface7_Release(ICOM_INTERFACE(src_level, IDirectDrawSurface7));
6222 src_level = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, temp);
6225 if (src_level && src_level != src) IDirectDrawSurface7_Release(ICOM_INTERFACE(src_level, IDirectDrawSurface7));
6226 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(ICOM_INTERFACE(dest_level, IDirectDrawSurface7));
6228 return !dest_level && levelFound;
6231 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6232 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
6233 IDirectDrawSurfaceImpl *dest,
6234 IDirectDrawSurfaceImpl *src,
6235 POINT *DestPoint,
6236 RECT *SrcRect)
6238 IDirectDrawSurfaceImpl *src_level, *dest_level;
6239 IDirectDrawSurface7 *temp;
6240 DDSURFACEDESC2 ddsd;
6241 POINT point;
6242 RECT rect;
6243 HRESULT hr;
6244 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
6245 DWORD ckeyflag;
6246 DDCOLORKEY ddckey;
6247 BOOL palette_missing = FALSE;
6249 /* Copy palette, if possible. */
6250 IDirectDrawSurface7_GetPalette(ICOM_INTERFACE(src, IDirectDrawSurface7), &pal_src);
6251 IDirectDrawSurface7_GetPalette(ICOM_INTERFACE(dest, IDirectDrawSurface7), &pal);
6253 if (pal_src != NULL && pal != NULL)
6255 PALETTEENTRY palent[256];
6257 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
6258 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
6261 if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
6262 DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
6264 palette_missing = TRUE;
6267 if (pal) IDirectDrawPalette_Release(pal);
6268 if (pal_src) IDirectDrawPalette_Release(pal_src);
6270 /* Copy colorkeys, if present. */
6271 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6273 hr = IDirectDrawSurface7_GetColorKey(ICOM_INTERFACE(src, IDirectDrawSurface7), ckeyflag, &ddckey);
6275 if (SUCCEEDED(hr))
6277 IDirectDrawSurface7_SetColorKey(ICOM_INTERFACE(dest, IDirectDrawSurface7), ckeyflag, &ddckey);
6281 src_level = src;
6282 dest_level = dest;
6284 point = *DestPoint;
6285 rect = *SrcRect;
6287 for (;src_level && dest_level;)
6289 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6290 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6292 /* Try UpdateSurface that may perform a more direct opengl loading. But skip this is destination is paletted texture and has no palette.
6293 * Some games like Sacrifice set palette after Load, and it is a waste of effort to try to load texture without palette and generates
6294 * warnings in wined3d. */
6295 if (!palette_missing)
6296 hr = IWineD3DDevice_UpdateSurface(device->wineD3DDevice, src_level->WineD3DSurface, &rect, dest_level->WineD3DSurface,
6297 &point);
6299 if (palette_missing || FAILED(hr))
6301 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
6302 IWineD3DSurface_BltFast(dest_level->WineD3DSurface,
6303 point.x, point.y,
6304 src_level->WineD3DSurface, &rect, 0);
6307 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6308 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6309 IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(dest_level, IDirectDrawSurface7), &ddsd.ddsCaps, &temp);
6311 if (dest_level != dest) IDirectDrawSurface7_Release(ICOM_INTERFACE(dest_level, IDirectDrawSurface7));
6313 dest_level = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, temp);
6316 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6317 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6318 IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(src_level, IDirectDrawSurface7), &ddsd.ddsCaps, &temp);
6320 if (src_level != src) IDirectDrawSurface7_Release(ICOM_INTERFACE(src_level, IDirectDrawSurface7));
6322 src_level = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, temp);
6324 point.x /= 2;
6325 point.y /= 2;
6327 rect.top /= 2;
6328 rect.left /= 2;
6329 rect.right = (rect.right + 1) / 2;
6330 rect.bottom = (rect.bottom + 1) / 2;
6333 if (src_level && src_level != src) IDirectDrawSurface7_Release(ICOM_INTERFACE(src_level, IDirectDrawSurface7));
6334 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(ICOM_INTERFACE(dest_level, IDirectDrawSurface7));
6337 /*****************************************************************************
6338 * IDirect3DDevice7::Load
6340 * Loads a rectangular area from the source into the destination texture.
6341 * It can also copy the source to the faces of a cubic environment map
6343 * Version 7
6345 * Params:
6346 * DestTex: Destination texture
6347 * DestPoint: Point in the destination where the source image should be
6348 * written to
6349 * SrcTex: Source texture
6350 * SrcRect: Source rectangle
6351 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6352 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6353 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6355 * Returns:
6356 * D3D_OK on success
6357 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6360 *****************************************************************************/
6362 static HRESULT
6363 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6364 IDirectDrawSurface7 *DestTex,
6365 POINT *DestPoint,
6366 IDirectDrawSurface7 *SrcTex,
6367 RECT *SrcRect,
6368 DWORD Flags)
6370 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6371 IDirectDrawSurfaceImpl *dest = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, DestTex);
6372 IDirectDrawSurfaceImpl *src = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, SrcTex);
6373 POINT destpoint;
6374 RECT srcrect;
6375 TRACE("(%p)->(%p,%p,%p,%p,%08x)\n", This, dest, DestPoint, src, SrcRect, Flags);
6377 if( (!src) || (!dest) )
6378 return DDERR_INVALIDPARAMS;
6380 EnterCriticalSection(&ddraw_cs);
6382 if (SrcRect) srcrect = *SrcRect;
6383 else
6385 srcrect.left = srcrect.top = 0;
6386 srcrect.right = src->surface_desc.dwWidth;
6387 srcrect.bottom = src->surface_desc.dwHeight;
6390 if (DestPoint) destpoint = *DestPoint;
6391 else
6393 destpoint.x = destpoint.y = 0;
6395 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6396 * destination can be a subset of mip levels, in which case actual coordinates used
6397 * for it may be divided. If any dimension of dest is larger than source, it can't be
6398 * mip level subset, so an error can be returned early.
6400 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6401 srcrect.right > src->surface_desc.dwWidth ||
6402 srcrect.bottom > src->surface_desc.dwHeight ||
6403 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6404 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6405 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6406 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6408 LeaveCriticalSection(&ddraw_cs);
6409 return DDERR_INVALIDPARAMS;
6412 /* Must be top level surfaces. */
6413 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6414 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6416 LeaveCriticalSection(&ddraw_cs);
6417 return DDERR_INVALIDPARAMS;
6420 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6422 DWORD src_face_flag, dest_face_flag;
6423 IDirectDrawSurfaceImpl *src_face, *dest_face;
6424 IDirectDrawSurface7 *temp;
6425 DDSURFACEDESC2 ddsd;
6426 int i;
6428 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6430 LeaveCriticalSection(&ddraw_cs);
6431 return DDERR_INVALIDPARAMS;
6434 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6435 * time it's actual surface loading. */
6436 for (i = 0; i < 2; i++)
6438 dest_face = dest;
6439 src_face = src;
6441 for (;dest_face && src_face;)
6443 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6444 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6446 if (src_face_flag == dest_face_flag)
6448 if (i == 0)
6450 /* Destination mip levels must be subset of source mip levels. */
6451 if (!is_mip_level_subset(dest_face, src_face))
6453 LeaveCriticalSection(&ddraw_cs);
6454 return DDERR_INVALIDPARAMS;
6457 else if (Flags & dest_face_flag)
6459 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6462 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6464 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6465 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6466 IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(src, IDirectDrawSurface7), &ddsd.ddsCaps, &temp);
6468 if (src_face != src) IDirectDrawSurface7_Release(ICOM_INTERFACE(src_face, IDirectDrawSurface7));
6470 src_face = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, temp);
6472 else
6474 if (src_face != src) IDirectDrawSurface7_Release(ICOM_INTERFACE(src_face, IDirectDrawSurface7));
6476 src_face = NULL;
6480 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6482 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6483 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6484 IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(dest, IDirectDrawSurface7), &ddsd.ddsCaps, &temp);
6486 if (dest_face != dest) IDirectDrawSurface7_Release(ICOM_INTERFACE(dest_face, IDirectDrawSurface7));
6488 dest_face = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, temp);
6490 else
6492 if (dest_face != dest) IDirectDrawSurface7_Release(ICOM_INTERFACE(dest_face, IDirectDrawSurface7));
6494 dest_face = NULL;
6498 if (i == 0)
6500 /* Native returns error if src faces are not subset of dest faces. */
6501 if (src_face)
6503 LeaveCriticalSection(&ddraw_cs);
6504 return DDERR_INVALIDPARAMS;
6509 LeaveCriticalSection(&ddraw_cs);
6510 return D3D_OK;
6512 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6514 LeaveCriticalSection(&ddraw_cs);
6515 return DDERR_INVALIDPARAMS;
6518 /* Handle non cube map textures. */
6520 /* Destination mip levels must be subset of source mip levels. */
6521 if (!is_mip_level_subset(dest, src))
6523 LeaveCriticalSection(&ddraw_cs);
6524 return DDERR_INVALIDPARAMS;
6527 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6529 LeaveCriticalSection(&ddraw_cs);
6530 return D3D_OK;
6533 static HRESULT WINAPI
6534 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6535 IDirectDrawSurface7 *DestTex,
6536 POINT *DestPoint,
6537 IDirectDrawSurface7 *SrcTex,
6538 RECT *SrcRect,
6539 DWORD Flags)
6541 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6544 static HRESULT WINAPI
6545 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6546 IDirectDrawSurface7 *DestTex,
6547 POINT *DestPoint,
6548 IDirectDrawSurface7 *SrcTex,
6549 RECT *SrcRect,
6550 DWORD Flags)
6552 HRESULT hr;
6553 WORD old_fpucw;
6555 old_fpucw = d3d_fpu_setup();
6556 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6557 set_fpu_control_word(old_fpucw);
6559 return hr;
6562 /*****************************************************************************
6563 * IDirect3DDevice7::LightEnable
6565 * Enables or disables a light
6567 * Version 7, IDirect3DLight uses this method too.
6569 * Params:
6570 * LightIndex: The index of the light to enable / disable
6571 * Enable: Enable or disable the light
6573 * Returns:
6574 * D3D_OK on success
6575 * For more details, see IWineD3DDevice::SetLightEnable
6577 *****************************************************************************/
6578 static HRESULT
6579 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6580 DWORD LightIndex,
6581 BOOL Enable)
6583 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6584 HRESULT hr;
6585 TRACE("(%p)->(%08x,%d): Relay!\n", This, LightIndex, Enable);
6587 EnterCriticalSection(&ddraw_cs);
6588 hr = IWineD3DDevice_SetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6589 LeaveCriticalSection(&ddraw_cs);
6590 return hr_ddraw_from_wined3d(hr);
6593 static HRESULT WINAPI
6594 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6595 DWORD LightIndex,
6596 BOOL Enable)
6598 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6601 static HRESULT WINAPI
6602 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6603 DWORD LightIndex,
6604 BOOL Enable)
6606 HRESULT hr;
6607 WORD old_fpucw;
6609 old_fpucw = d3d_fpu_setup();
6610 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6611 set_fpu_control_word(old_fpucw);
6613 return hr;
6616 /*****************************************************************************
6617 * IDirect3DDevice7::GetLightEnable
6619 * Retrieves if the light with the given index is enabled or not
6621 * Version 7
6623 * Params:
6624 * LightIndex: Index of desired light
6625 * Enable: Pointer to a BOOL which contains the result
6627 * Returns:
6628 * D3D_OK on success
6629 * DDERR_INVALIDPARAMS if Enable is NULL
6630 * See IWineD3DDevice::GetLightEnable for more details
6632 *****************************************************************************/
6633 static HRESULT
6634 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6635 DWORD LightIndex,
6636 BOOL* Enable)
6638 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6639 HRESULT hr;
6640 TRACE("(%p)->(%08x,%p): Relay\n", This, LightIndex, Enable);
6642 if(!Enable)
6643 return DDERR_INVALIDPARAMS;
6645 EnterCriticalSection(&ddraw_cs);
6646 hr = IWineD3DDevice_GetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6647 LeaveCriticalSection(&ddraw_cs);
6648 return hr_ddraw_from_wined3d(hr);
6651 static HRESULT WINAPI
6652 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6653 DWORD LightIndex,
6654 BOOL* Enable)
6656 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6659 static HRESULT WINAPI
6660 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6661 DWORD LightIndex,
6662 BOOL* Enable)
6664 HRESULT hr;
6665 WORD old_fpucw;
6667 old_fpucw = d3d_fpu_setup();
6668 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6669 set_fpu_control_word(old_fpucw);
6671 return hr;
6674 /*****************************************************************************
6675 * IDirect3DDevice7::SetClipPlane
6677 * Sets custom clipping plane
6679 * Version 7
6681 * Params:
6682 * Index: The index of the clipping plane
6683 * PlaneEquation: An equation defining the clipping plane
6685 * Returns:
6686 * D3D_OK on success
6687 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6688 * See IWineD3DDevice::SetClipPlane for more details
6690 *****************************************************************************/
6691 static HRESULT
6692 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6693 DWORD Index,
6694 D3DVALUE* PlaneEquation)
6696 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6697 HRESULT hr;
6698 TRACE("(%p)->(%08x,%p): Relay!\n", This, Index, PlaneEquation);
6700 if(!PlaneEquation)
6701 return DDERR_INVALIDPARAMS;
6703 EnterCriticalSection(&ddraw_cs);
6704 hr = IWineD3DDevice_SetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6705 LeaveCriticalSection(&ddraw_cs);
6706 return hr;
6709 static HRESULT WINAPI
6710 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6711 DWORD Index,
6712 D3DVALUE* PlaneEquation)
6714 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6717 static HRESULT WINAPI
6718 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6719 DWORD Index,
6720 D3DVALUE* PlaneEquation)
6722 HRESULT hr;
6723 WORD old_fpucw;
6725 old_fpucw = d3d_fpu_setup();
6726 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6727 set_fpu_control_word(old_fpucw);
6729 return hr;
6732 /*****************************************************************************
6733 * IDirect3DDevice7::GetClipPlane
6735 * Returns the clipping plane with a specific index
6737 * Params:
6738 * Index: The index of the desired plane
6739 * PlaneEquation: Address to store the plane equation to
6741 * Returns:
6742 * D3D_OK on success
6743 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6744 * See IWineD3DDevice::GetClipPlane for more details
6746 *****************************************************************************/
6747 static HRESULT
6748 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6749 DWORD Index,
6750 D3DVALUE* PlaneEquation)
6752 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6753 HRESULT hr;
6754 TRACE("(%p)->(%d,%p): Relay!\n", This, Index, PlaneEquation);
6756 if(!PlaneEquation)
6757 return DDERR_INVALIDPARAMS;
6759 EnterCriticalSection(&ddraw_cs);
6760 hr = IWineD3DDevice_GetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6761 LeaveCriticalSection(&ddraw_cs);
6762 return hr;
6765 static HRESULT WINAPI
6766 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6767 DWORD Index,
6768 D3DVALUE* PlaneEquation)
6770 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6773 static HRESULT WINAPI
6774 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6775 DWORD Index,
6776 D3DVALUE* PlaneEquation)
6778 HRESULT hr;
6779 WORD old_fpucw;
6781 old_fpucw = d3d_fpu_setup();
6782 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6783 set_fpu_control_word(old_fpucw);
6785 return hr;
6788 /*****************************************************************************
6789 * IDirect3DDevice7::GetInfo
6791 * Retrieves some information about the device. The DirectX sdk says that
6792 * this version returns S_FALSE for all retail builds of DirectX, that's what
6793 * this implementation does.
6795 * Params:
6796 * DevInfoID: Information type requested
6797 * DevInfoStruct: Pointer to a structure to store the info to
6798 * Size: Size of the structure
6800 * Returns:
6801 * S_FALSE, because it's a non-debug driver
6803 *****************************************************************************/
6804 static HRESULT WINAPI
6805 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6806 DWORD DevInfoID,
6807 void *DevInfoStruct,
6808 DWORD Size)
6810 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6811 TRACE("(%p)->(%08x,%p,%08x)\n", This, DevInfoID, DevInfoStruct, Size);
6813 if (TRACE_ON(d3d7))
6815 TRACE(" info requested : ");
6816 switch (DevInfoID)
6818 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6819 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6820 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6821 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6825 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6828 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6829 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6830 * are not duplicated.
6832 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6833 * has already been setup for optimal d3d operation.
6835 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6836 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6837 * by Sacrifice (game). */
6838 const IDirect3DDevice7Vtbl IDirect3DDevice7_FPUSetup_Vtbl =
6840 /*** IUnknown Methods ***/
6841 IDirect3DDeviceImpl_7_QueryInterface,
6842 IDirect3DDeviceImpl_7_AddRef,
6843 IDirect3DDeviceImpl_7_Release,
6844 /*** IDirect3DDevice7 ***/
6845 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6846 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6847 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6848 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6849 IDirect3DDeviceImpl_7_GetDirect3D,
6850 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6851 IDirect3DDeviceImpl_7_GetRenderTarget,
6852 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6853 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6854 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6855 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6856 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6857 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6858 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6859 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6860 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6861 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6862 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6863 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6864 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6865 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6866 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6867 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6868 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6869 IDirect3DDeviceImpl_7_SetClipStatus,
6870 IDirect3DDeviceImpl_7_GetClipStatus,
6871 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6872 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6873 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6874 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6875 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6876 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6877 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6878 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6879 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6880 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6881 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6882 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6883 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6884 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6885 IDirect3DDeviceImpl_7_Load_FPUSetup,
6886 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6887 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6888 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6889 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6890 IDirect3DDeviceImpl_7_GetInfo
6893 const IDirect3DDevice7Vtbl IDirect3DDevice7_FPUPreserve_Vtbl =
6895 /*** IUnknown Methods ***/
6896 IDirect3DDeviceImpl_7_QueryInterface,
6897 IDirect3DDeviceImpl_7_AddRef,
6898 IDirect3DDeviceImpl_7_Release,
6899 /*** IDirect3DDevice7 ***/
6900 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6901 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6902 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6903 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6904 IDirect3DDeviceImpl_7_GetDirect3D,
6905 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6906 IDirect3DDeviceImpl_7_GetRenderTarget,
6907 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6908 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6909 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6910 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6911 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6912 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6913 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6914 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6915 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6916 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6917 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6918 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6919 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6920 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6921 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6922 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6923 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6924 IDirect3DDeviceImpl_7_SetClipStatus,
6925 IDirect3DDeviceImpl_7_GetClipStatus,
6926 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6927 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6928 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6929 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6930 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6931 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6932 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6933 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6934 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6935 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6936 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6937 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6938 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6939 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6940 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6941 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6942 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6943 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6944 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6945 IDirect3DDeviceImpl_7_GetInfo
6948 const IDirect3DDevice3Vtbl IDirect3DDevice3_Vtbl =
6950 /*** IUnknown Methods ***/
6951 Thunk_IDirect3DDeviceImpl_3_QueryInterface,
6952 Thunk_IDirect3DDeviceImpl_3_AddRef,
6953 Thunk_IDirect3DDeviceImpl_3_Release,
6954 /*** IDirect3DDevice3 ***/
6955 IDirect3DDeviceImpl_3_GetCaps,
6956 IDirect3DDeviceImpl_3_GetStats,
6957 IDirect3DDeviceImpl_3_AddViewport,
6958 IDirect3DDeviceImpl_3_DeleteViewport,
6959 IDirect3DDeviceImpl_3_NextViewport,
6960 Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
6961 Thunk_IDirect3DDeviceImpl_3_BeginScene,
6962 Thunk_IDirect3DDeviceImpl_3_EndScene,
6963 Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
6964 IDirect3DDeviceImpl_3_SetCurrentViewport,
6965 IDirect3DDeviceImpl_3_GetCurrentViewport,
6966 Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
6967 Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
6968 IDirect3DDeviceImpl_3_Begin,
6969 IDirect3DDeviceImpl_3_BeginIndexed,
6970 IDirect3DDeviceImpl_3_Vertex,
6971 IDirect3DDeviceImpl_3_Index,
6972 IDirect3DDeviceImpl_3_End,
6973 IDirect3DDeviceImpl_3_GetRenderState,
6974 IDirect3DDeviceImpl_3_SetRenderState,
6975 IDirect3DDeviceImpl_3_GetLightState,
6976 IDirect3DDeviceImpl_3_SetLightState,
6977 Thunk_IDirect3DDeviceImpl_3_SetTransform,
6978 Thunk_IDirect3DDeviceImpl_3_GetTransform,
6979 Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
6980 Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
6981 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6982 Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
6983 Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
6984 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6985 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6986 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6987 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6988 Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6989 Thunk_IDirect3DDeviceImpl_3_GetTexture,
6990 IDirect3DDeviceImpl_3_SetTexture,
6991 Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
6992 Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
6993 Thunk_IDirect3DDeviceImpl_3_ValidateDevice
6996 const IDirect3DDevice2Vtbl IDirect3DDevice2_Vtbl =
6998 /*** IUnknown Methods ***/
6999 Thunk_IDirect3DDeviceImpl_2_QueryInterface,
7000 Thunk_IDirect3DDeviceImpl_2_AddRef,
7001 Thunk_IDirect3DDeviceImpl_2_Release,
7002 /*** IDirect3DDevice2 ***/
7003 Thunk_IDirect3DDeviceImpl_2_GetCaps,
7004 IDirect3DDeviceImpl_2_SwapTextureHandles,
7005 Thunk_IDirect3DDeviceImpl_2_GetStats,
7006 Thunk_IDirect3DDeviceImpl_2_AddViewport,
7007 Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
7008 Thunk_IDirect3DDeviceImpl_2_NextViewport,
7009 IDirect3DDeviceImpl_2_EnumTextureFormats,
7010 Thunk_IDirect3DDeviceImpl_2_BeginScene,
7011 Thunk_IDirect3DDeviceImpl_2_EndScene,
7012 Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
7013 Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
7014 Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
7015 Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
7016 Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
7017 Thunk_IDirect3DDeviceImpl_2_Begin,
7018 Thunk_IDirect3DDeviceImpl_2_BeginIndexed,
7019 Thunk_IDirect3DDeviceImpl_2_Vertex,
7020 Thunk_IDirect3DDeviceImpl_2_Index,
7021 Thunk_IDirect3DDeviceImpl_2_End,
7022 Thunk_IDirect3DDeviceImpl_2_GetRenderState,
7023 Thunk_IDirect3DDeviceImpl_2_SetRenderState,
7024 Thunk_IDirect3DDeviceImpl_2_GetLightState,
7025 Thunk_IDirect3DDeviceImpl_2_SetLightState,
7026 Thunk_IDirect3DDeviceImpl_2_SetTransform,
7027 Thunk_IDirect3DDeviceImpl_2_GetTransform,
7028 Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
7029 Thunk_IDirect3DDeviceImpl_2_DrawPrimitive,
7030 Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
7031 Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
7032 Thunk_IDirect3DDeviceImpl_2_GetClipStatus
7035 const IDirect3DDeviceVtbl IDirect3DDevice1_Vtbl =
7037 /*** IUnknown Methods ***/
7038 Thunk_IDirect3DDeviceImpl_1_QueryInterface,
7039 Thunk_IDirect3DDeviceImpl_1_AddRef,
7040 Thunk_IDirect3DDeviceImpl_1_Release,
7041 /*** IDirect3DDevice1 ***/
7042 IDirect3DDeviceImpl_1_Initialize,
7043 Thunk_IDirect3DDeviceImpl_1_GetCaps,
7044 Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
7045 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
7046 Thunk_IDirect3DDeviceImpl_1_GetStats,
7047 IDirect3DDeviceImpl_1_Execute,
7048 Thunk_IDirect3DDeviceImpl_1_AddViewport,
7049 Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
7050 Thunk_IDirect3DDeviceImpl_1_NextViewport,
7051 IDirect3DDeviceImpl_1_Pick,
7052 IDirect3DDeviceImpl_1_GetPickRecords,
7053 Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
7054 IDirect3DDeviceImpl_1_CreateMatrix,
7055 IDirect3DDeviceImpl_1_SetMatrix,
7056 IDirect3DDeviceImpl_1_GetMatrix,
7057 IDirect3DDeviceImpl_1_DeleteMatrix,
7058 Thunk_IDirect3DDeviceImpl_1_BeginScene,
7059 Thunk_IDirect3DDeviceImpl_1_EndScene,
7060 Thunk_IDirect3DDeviceImpl_1_GetDirect3D
7063 /*****************************************************************************
7064 * IDirect3DDeviceImpl_CreateHandle
7066 * Not called from the VTable
7068 * Some older interface versions operate with handles, which are basically
7069 * DWORDs which identify an interface, for example
7070 * IDirect3DDevice::SetRenderState with DIRECT3DRENDERSTATE_TEXTUREHANDLE
7072 * Those handle could be just casts to the interface pointers or vice versa,
7073 * but that is not 64 bit safe and would mean blindly derefering a DWORD
7074 * passed by the app. Instead there is a dynamic array in the device which
7075 * keeps a DWORD to pointer information and a type for the handle.
7077 * Basically this array only grows, when a handle is freed its pointer is
7078 * just set to NULL. There will be much more reads from the array than
7079 * insertion operations, so a dynamic array is fine.
7081 * Params:
7082 * This: D3DDevice implementation for which this handle should be created
7084 * Returns:
7085 * A free handle on success
7086 * 0 on failure
7088 *****************************************************************************/
7089 DWORD
7090 IDirect3DDeviceImpl_CreateHandle(IDirect3DDeviceImpl *This)
7092 DWORD i;
7093 struct HandleEntry *oldHandles = This->Handles;
7095 TRACE("(%p)\n", This);
7097 for(i = 0; i < This->numHandles; i++)
7099 if(This->Handles[i].ptr == NULL &&
7100 This->Handles[i].type == DDrawHandle_Unknown)
7102 TRACE("Reusing freed handle %d\n", i + 1);
7103 return i + 1;
7107 TRACE("Growing the handle array\n");
7109 This->numHandles++;
7110 This->Handles = HeapAlloc(GetProcessHeap(), 0, sizeof(struct HandleEntry) * This->numHandles);
7111 if(!This->Handles)
7113 ERR("Out of memory\n");
7114 This->Handles = oldHandles;
7115 This->numHandles--;
7116 return 0;
7118 if(oldHandles)
7120 memcpy(This->Handles, oldHandles, (This->numHandles - 1) * sizeof(struct HandleEntry));
7121 HeapFree(GetProcessHeap(), 0, oldHandles);
7124 TRACE("Returning %d\n", This->numHandles);
7125 return This->numHandles;
7128 /*****************************************************************************
7129 * IDirect3DDeviceImpl_UpdateDepthStencil
7131 * Checks the current render target for attached depth stencils and sets the
7132 * WineD3D depth stencil accordingly.
7134 * Returns:
7135 * The depth stencil state to set if creating the device
7137 *****************************************************************************/
7138 WINED3DZBUFFERTYPE
7139 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
7141 IDirectDrawSurface7 *depthStencil = NULL;
7142 IDirectDrawSurfaceImpl *dsi;
7143 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
7145 IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(This->target, IDirectDrawSurface7),
7146 &depthcaps,
7147 &depthStencil);
7148 if(!depthStencil)
7150 TRACE("Setting wined3d depth stencil to NULL\n");
7151 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
7152 NULL);
7153 return WINED3DZB_FALSE;
7156 dsi = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, depthStencil);
7157 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->WineD3DSurface);
7158 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
7159 dsi->WineD3DSurface);
7161 IDirectDrawSurface7_Release(depthStencil);
7162 return WINED3DZB_TRUE;