gameux: Add interface registration routines.
[wine/hramrach.git] / dlls / ddraw / device.c
blobf120bf3a7ea03b3b91734db6b3900720a7134dfc
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 return 0;
89 #endif
91 set_fpu_control_word(0x37f);
93 return oldcw;
96 /*****************************************************************************
97 * IUnknown Methods. Common for Version 1, 2, 3 and 7
98 *****************************************************************************/
100 /*****************************************************************************
101 * IDirect3DDevice7::QueryInterface
103 * Used to query other interfaces from a Direct3DDevice interface.
104 * It can return interface pointers to all Direct3DDevice versions as well
105 * as IDirectDraw and IDirect3D. For a link to QueryInterface
106 * rules see ddraw.c, IDirectDraw7::QueryInterface
108 * Exists in Version 1, 2, 3 and 7
110 * Params:
111 * refiid: Interface ID queried for
112 * obj: Used to return the interface pointer
114 * Returns:
115 * D3D_OK or E_NOINTERFACE
117 *****************************************************************************/
118 static HRESULT WINAPI
119 IDirect3DDeviceImpl_7_QueryInterface(IDirect3DDevice7 *iface,
120 REFIID refiid,
121 void **obj)
123 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
124 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(refiid), obj);
126 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
127 *obj = NULL;
129 if(!refiid)
130 return DDERR_INVALIDPARAMS;
132 if ( IsEqualGUID( &IID_IUnknown, refiid ) )
134 *obj = iface;
137 /* Check DirectDraw Interfac\x01s */
138 else if( IsEqualGUID( &IID_IDirectDraw7, refiid ) )
140 *obj = This->ddraw;
141 TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
143 else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
145 *obj = &This->ddraw->IDirectDraw4_vtbl;
146 TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
148 else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
150 *obj = &This->ddraw->IDirectDraw2_vtbl;
151 TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
153 else if( IsEqualGUID( &IID_IDirectDraw, refiid ) )
155 *obj = &This->ddraw->IDirectDraw_vtbl;
156 TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
159 /* Direct3D */
160 else if ( IsEqualGUID( &IID_IDirect3D , refiid ) )
162 *obj = &This->ddraw->IDirect3D_vtbl;
163 TRACE("(%p) Returning IDirect3D interface at %p\n", This, *obj);
165 else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) )
167 *obj = &This->ddraw->IDirect3D2_vtbl;
168 TRACE("(%p) Returning IDirect3D2 interface at %p\n", This, *obj);
170 else if ( IsEqualGUID( &IID_IDirect3D3 , refiid ) )
172 *obj = &This->ddraw->IDirect3D3_vtbl;
173 TRACE("(%p) Returning IDirect3D3 interface at %p\n", This, *obj);
175 else if ( IsEqualGUID( &IID_IDirect3D7 , refiid ) )
177 *obj = &This->ddraw->IDirect3D7_vtbl;
178 TRACE("(%p) Returning IDirect3D7 interface at %p\n", This, *obj);
181 /* Direct3DDevice */
182 else if ( IsEqualGUID( &IID_IDirect3DDevice , refiid ) )
184 *obj = &This->IDirect3DDevice_vtbl;
185 TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
187 else if ( IsEqualGUID( &IID_IDirect3DDevice2 , refiid ) ) {
188 *obj = &This->IDirect3DDevice2_vtbl;
189 TRACE("(%p) Returning IDirect3DDevice2 interface at %p\n", This, *obj);
191 else if ( IsEqualGUID( &IID_IDirect3DDevice3 , refiid ) ) {
192 *obj = &This->IDirect3DDevice3_vtbl;
193 TRACE("(%p) Returning IDirect3DDevice3 interface at %p\n", This, *obj);
195 else if ( IsEqualGUID( &IID_IDirect3DDevice7 , refiid ) ) {
196 *obj = This;
197 TRACE("(%p) Returning IDirect3DDevice7 interface at %p\n", This, *obj);
200 /* Unknown interface */
201 else
203 ERR("(%p)->(%s, %p): No interface found\n", This, debugstr_guid(refiid), obj);
204 return E_NOINTERFACE;
207 /* AddRef the returned interface */
208 IUnknown_AddRef( (IUnknown *) *obj);
209 return D3D_OK;
212 static HRESULT WINAPI
213 Thunk_IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface,
214 REFIID riid,
215 void **obj)
217 IDirect3DDeviceImpl *This = device_from_device3(iface);
218 TRACE_(ddraw_thunk)("(%p)->(%s,%p) thunking to IDirect3DDevice7 interface.\n", This, debugstr_guid(riid), obj);
219 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)This, riid, obj);
222 static HRESULT WINAPI
223 Thunk_IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface,
224 REFIID riid,
225 void **obj)
227 IDirect3DDeviceImpl *This = device_from_device2(iface);
228 TRACE_(ddraw_thunk)("(%p)->(%s,%p) thunking to IDirect3DDevice7 interface.\n", This, debugstr_guid(riid), obj);
229 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)This, riid, obj);
232 static HRESULT WINAPI
233 Thunk_IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface,
234 REFIID riid,
235 void **obp)
237 IDirect3DDeviceImpl *This = device_from_device1(iface);
238 TRACE_(ddraw_thunk)("(%p)->(%s,%p) thunking to IDirect3DDevice7 interface.\n", This, debugstr_guid(riid), obp);
239 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)This, riid, obp);
242 /*****************************************************************************
243 * IDirect3DDevice7::AddRef
245 * Increases the refcount....
246 * The most exciting Method, definitely
248 * Exists in Version 1, 2, 3 and 7
250 * Returns:
251 * The new refcount
253 *****************************************************************************/
254 static ULONG WINAPI
255 IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
257 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
258 ULONG ref = InterlockedIncrement(&This->ref);
260 TRACE("(%p) : incrementing from %u.\n", This, ref -1);
262 return ref;
265 static ULONG WINAPI
266 Thunk_IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
268 IDirect3DDeviceImpl *This = device_from_device3(iface);
269 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
270 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)This);
273 static ULONG WINAPI
274 Thunk_IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
276 IDirect3DDeviceImpl *This = device_from_device2(iface);
277 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
278 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)This);
281 static ULONG WINAPI
282 Thunk_IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
284 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", iface);
285 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device1(iface));
288 /*****************************************************************************
289 * IDirect3DDevice7::Release
291 * Decreases the refcount of the interface
292 * When the refcount is reduced to 0, the object is destroyed.
294 * Exists in Version 1, 2, 3 and 7
296 * Returns:d
297 * The new refcount
299 *****************************************************************************/
300 static ULONG WINAPI
301 IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
303 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
304 ULONG ref = InterlockedDecrement(&This->ref);
306 TRACE("(%p)->() decrementing from %u.\n", This, ref +1);
308 /* This method doesn't destroy the WineD3DDevice, because it's still in use for
309 * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
310 * when the render target is released
312 if (ref == 0)
314 IParent *IndexBufferParent;
315 DWORD i;
317 EnterCriticalSection(&ddraw_cs);
318 /* Free the index buffer. */
319 IWineD3DDevice_SetIndexBuffer(This->wineD3DDevice, NULL, WINED3DFMT_UNKNOWN);
320 IWineD3DBuffer_GetParent(This->indexbuffer,
321 (IUnknown **) &IndexBufferParent);
322 IParent_Release(IndexBufferParent); /* Once for the getParent */
323 if( IParent_Release(IndexBufferParent) != 0) /* And now to destroy it */
325 ERR(" (%p) Something is still holding the index buffer parent %p\n", This, IndexBufferParent);
328 /* There is no need to unset the vertex buffer here, IWineD3DDevice_Uninit3D will do that when
329 * destroying the primary stateblock. If a vertex buffer is destroyed while it is bound
330 * IDirect3DVertexBuffer::Release will unset it.
333 /* Restore the render targets */
334 if(This->OffScreenTarget)
336 WINED3DVIEWPORT vp;
338 vp.X = 0;
339 vp.Y = 0;
340 vp.Width = This->ddraw->d3d_target->surface_desc.dwWidth;
341 vp.Height = This->ddraw->d3d_target->surface_desc.dwHeight;
342 vp.MinZ = 0.0;
343 vp.MaxZ = 1.0;
344 IWineD3DDevice_SetViewport(This->wineD3DDevice,
345 &vp);
347 /* Set the device up to render to the front buffer since the back buffer will
348 * vanish soon.
350 IWineD3DDevice_SetRenderTarget(This->wineD3DDevice, 0,
351 This->ddraw->d3d_target->WineD3DSurface,
352 FALSE);
353 /* This->target is the offscreen target.
354 * This->ddraw->d3d_target is the target used by DDraw
356 TRACE("(%p) Release: Using %p as front buffer, %p as back buffer\n", This, This->ddraw->d3d_target, NULL);
357 IWineD3DDevice_SetFrontBackBuffers(This->wineD3DDevice,
358 This->ddraw->d3d_target->WineD3DSurface,
359 NULL);
362 /* Release the WineD3DDevice. This won't destroy it */
363 if(IWineD3DDevice_Release(This->wineD3DDevice) <= 0)
365 ERR(" (%p) The wineD3D device %p was destroyed unexpectedly. Prepare for trouble\n", This, This->wineD3DDevice);
368 /* The texture handles should be unset by now, but there might be some bits
369 * missing in our reference counting(needs test). Do a sanity check
371 for(i = 0; i < This->numHandles; i++)
373 if(This->Handles[i].ptr)
375 switch(This->Handles[i].type)
377 case DDrawHandle_Texture:
379 IDirectDrawSurfaceImpl *surf = This->Handles[i].ptr;
380 FIXME("Texture Handle %d not unset properly\n", i + 1);
381 surf->Handle = 0;
383 break;
385 case DDrawHandle_Material:
387 IDirect3DMaterialImpl *mat = This->Handles[i].ptr;
388 FIXME("Material handle %d not unset properly\n", i + 1);
389 mat->Handle = 0;
391 break;
393 case DDrawHandle_Matrix:
395 /* No fixme here because this might happen because of sloppy apps */
396 WARN("Leftover matrix handle %d, deleting\n", i + 1);
397 IDirect3DDevice_DeleteMatrix((IDirect3DDevice *)&This->IDirect3DDevice_vtbl, i + 1);
399 break;
401 case DDrawHandle_StateBlock:
403 /* No fixme here because this might happen because of sloppy apps */
404 WARN("Leftover stateblock handle %d, deleting\n", i + 1);
405 IDirect3DDevice7_DeleteStateBlock((IDirect3DDevice7 *)This, i + 1);
407 break;
409 default:
410 FIXME("Unknown handle %d not unset properly\n", i + 1);
415 HeapFree(GetProcessHeap(), 0, This->Handles);
417 TRACE("Releasing target %p %p\n", This->target, This->ddraw->d3d_target);
418 /* Release the render target and the WineD3D render target
419 * (See IDirect3D7::CreateDevice for more comments on this)
421 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->target);
422 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->ddraw->d3d_target);
423 TRACE("Target release done\n");
425 This->ddraw->d3ddevice = NULL;
427 /* Now free the structure */
428 HeapFree(GetProcessHeap(), 0, This);
429 LeaveCriticalSection(&ddraw_cs);
432 TRACE("Done\n");
433 return ref;
436 static ULONG WINAPI
437 Thunk_IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
439 IDirect3DDeviceImpl *This = device_from_device3(iface);
440 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
441 return IDirect3DDevice7_Release((IDirect3DDevice7 *)This);
444 static ULONG WINAPI
445 Thunk_IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
447 IDirect3DDeviceImpl *This = device_from_device2(iface);
448 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
449 return IDirect3DDevice7_Release((IDirect3DDevice7 *)This);
452 static ULONG WINAPI
453 Thunk_IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
455 IDirect3DDeviceImpl *This = device_from_device1(iface);
456 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
457 return IDirect3DDevice7_Release((IDirect3DDevice7 *)This);
460 /*****************************************************************************
461 * IDirect3DDevice Methods
462 *****************************************************************************/
464 /*****************************************************************************
465 * IDirect3DDevice::Initialize
467 * Initializes a Direct3DDevice. This implementation is a no-op, as all
468 * initialization is done at create time.
470 * Exists in Version 1
472 * Parameters:
473 * No idea what they mean, as the MSDN page is gone
475 * Returns: DD_OK
477 *****************************************************************************/
478 static HRESULT WINAPI
479 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
480 IDirect3D *Direct3D, GUID *guid,
481 D3DDEVICEDESC *Desc)
483 IDirect3DDeviceImpl *This = device_from_device1(iface);
485 /* It shouldn't be crucial, but print a FIXME, I'm interested if
486 * any game calls it and when
488 FIXME("(%p)->(%p,%p,%p): No-op!\n", This, Direct3D, guid, Desc);
490 return D3D_OK;
493 /*****************************************************************************
494 * IDirect3DDevice7::GetCaps
496 * Retrieves the device's capabilities
498 * This implementation is used for Version 7 only, the older versions have
499 * their own implementation.
501 * Parameters:
502 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
504 * Returns:
505 * D3D_OK on success
506 * D3DERR_* if a problem occurs. See WineD3D
508 *****************************************************************************/
509 static HRESULT
510 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
511 D3DDEVICEDESC7 *Desc)
513 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
514 D3DDEVICEDESC OldDesc;
515 TRACE("(%p)->(%p)\n", This, Desc);
517 /* Call the same function used by IDirect3D, this saves code */
518 return IDirect3DImpl_GetCaps(This->ddraw->wineD3D, &OldDesc, Desc);
521 static HRESULT WINAPI
522 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
523 D3DDEVICEDESC7 *Desc)
525 return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
528 static HRESULT WINAPI
529 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
530 D3DDEVICEDESC7 *Desc)
532 HRESULT hr;
533 WORD old_fpucw;
535 old_fpucw = d3d_fpu_setup();
536 hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
537 set_fpu_control_word(old_fpucw);
539 return hr;
541 /*****************************************************************************
542 * IDirect3DDevice3::GetCaps
544 * Retrieves the capabilities of the hardware device and the emulation
545 * device. For Wine, hardware and emulation are the same (it's all HW).
547 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
549 * Parameters:
550 * HWDesc: Structure to fill with the HW caps
551 * HelDesc: Structure to fill with the hardware emulation caps
553 * Returns:
554 * D3D_OK on success
555 * D3DERR_* if a problem occurs. See WineD3D
557 *****************************************************************************/
558 static HRESULT WINAPI
559 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
560 D3DDEVICEDESC *HWDesc,
561 D3DDEVICEDESC *HelDesc)
563 IDirect3DDeviceImpl *This = device_from_device3(iface);
564 D3DDEVICEDESC7 newDesc;
565 HRESULT hr;
566 TRACE("(%p)->(%p,%p)\n", iface, HWDesc, HelDesc);
568 hr = IDirect3DImpl_GetCaps(This->ddraw->wineD3D, HWDesc, &newDesc);
569 if(hr != D3D_OK) return hr;
571 *HelDesc = *HWDesc;
572 return D3D_OK;
575 static HRESULT WINAPI
576 Thunk_IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
577 D3DDEVICEDESC *D3DHWDevDesc,
578 D3DDEVICEDESC *D3DHELDevDesc)
580 IDirect3DDeviceImpl *This = device_from_device2(iface);
581 TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice3 interface.\n", This, D3DHWDevDesc, D3DHELDevDesc);
582 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
585 static HRESULT WINAPI
586 Thunk_IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
587 D3DDEVICEDESC *D3DHWDevDesc,
588 D3DDEVICEDESC *D3DHELDevDesc)
590 IDirect3DDeviceImpl *This = device_from_device1(iface);
591 TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice3 interface.\n", This, D3DHWDevDesc, D3DHELDevDesc);
592 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
595 /*****************************************************************************
596 * IDirect3DDevice2::SwapTextureHandles
598 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
600 * Parameters:
601 * Tex1, Tex2: The 2 Textures to swap
603 * Returns:
604 * D3D_OK
606 *****************************************************************************/
607 static HRESULT WINAPI
608 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
609 IDirect3DTexture2 *Tex1,
610 IDirect3DTexture2 *Tex2)
612 IDirect3DDeviceImpl *This = device_from_device2(iface);
613 DWORD swap;
614 IDirectDrawSurfaceImpl *surf1 = surface_from_texture2(Tex1);
615 IDirectDrawSurfaceImpl *surf2 = surface_from_texture2(Tex2);
616 TRACE("(%p)->(%p,%p)\n", This, surf1, surf2);
618 EnterCriticalSection(&ddraw_cs);
619 This->Handles[surf1->Handle - 1].ptr = surf2;
620 This->Handles[surf2->Handle - 1].ptr = surf1;
622 swap = surf2->Handle;
623 surf2->Handle = surf1->Handle;
624 surf1->Handle = swap;
625 LeaveCriticalSection(&ddraw_cs);
627 return D3D_OK;
630 static HRESULT WINAPI
631 Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
632 IDirect3DTexture *D3DTex1,
633 IDirect3DTexture *D3DTex2)
635 IDirect3DDeviceImpl *This = device_from_device1(iface);
636 IDirectDrawSurfaceImpl *surf1 = surface_from_texture1(D3DTex1);
637 IDirectDrawSurfaceImpl *surf2 = surface_from_texture1(D3DTex2);
638 IDirect3DTexture2 *t1 = surf1 ? (IDirect3DTexture2 *)&surf1->IDirect3DTexture2_vtbl : NULL;
639 IDirect3DTexture2 *t2 = surf2 ? (IDirect3DTexture2 *)&surf2->IDirect3DTexture2_vtbl : NULL;
640 TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice2 interface.\n", This, surf1, surf2);
641 return IDirect3DDevice2_SwapTextureHandles((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, t1, t2);
644 /*****************************************************************************
645 * IDirect3DDevice3::GetStats
647 * This method seems to retrieve some stats from the device.
648 * The MSDN documentation doesn't exist any more, but the D3DSTATS
649 * structure suggests that the amount of drawn primitives and processed
650 * vertices is returned.
652 * Exists in Version 1, 2 and 3
654 * Parameters:
655 * Stats: Pointer to a D3DSTATS structure to be filled
657 * Returns:
658 * D3D_OK on success
659 * DDERR_INVALIDPARAMS if Stats == NULL
661 *****************************************************************************/
662 static HRESULT WINAPI
663 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
664 D3DSTATS *Stats)
666 IDirect3DDeviceImpl *This = device_from_device3(iface);
667 FIXME("(%p)->(%p): Stub!\n", This, Stats);
669 if(!Stats)
670 return DDERR_INVALIDPARAMS;
672 /* Fill the Stats with 0 */
673 Stats->dwTrianglesDrawn = 0;
674 Stats->dwLinesDrawn = 0;
675 Stats->dwPointsDrawn = 0;
676 Stats->dwSpansDrawn = 0;
677 Stats->dwVerticesProcessed = 0;
679 return D3D_OK;
682 static HRESULT WINAPI
683 Thunk_IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface,
684 D3DSTATS *Stats)
686 IDirect3DDeviceImpl *This = device_from_device2(iface);
687 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, Stats);
688 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
691 static HRESULT WINAPI
692 Thunk_IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface,
693 D3DSTATS *Stats)
695 IDirect3DDeviceImpl *This = device_from_device1(iface);
696 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, Stats);
697 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
700 /*****************************************************************************
701 * IDirect3DDevice::CreateExecuteBuffer
703 * Creates an IDirect3DExecuteBuffer, used for rendering with a
704 * Direct3DDevice.
706 * Version 1 only.
708 * Params:
709 * Desc: Buffer description
710 * ExecuteBuffer: Address to return the Interface pointer at
711 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
712 * support
714 * Returns:
715 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
716 * DDERR_OUTOFMEMORY if we ran out of memory
717 * D3D_OK on success
719 *****************************************************************************/
720 static HRESULT WINAPI
721 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
722 D3DEXECUTEBUFFERDESC *Desc,
723 IDirect3DExecuteBuffer **ExecuteBuffer,
724 IUnknown *UnkOuter)
726 IDirect3DDeviceImpl *This = device_from_device1(iface);
727 IDirect3DExecuteBufferImpl* object;
728 TRACE("(%p)->(%p,%p,%p)!\n", This, Desc, ExecuteBuffer, UnkOuter);
730 if(UnkOuter)
731 return CLASS_E_NOAGGREGATION;
733 /* Allocate the new Execute Buffer */
734 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
735 if(!object)
737 ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
738 return DDERR_OUTOFMEMORY;
741 object->lpVtbl = &IDirect3DExecuteBuffer_Vtbl;
742 object->ref = 1;
743 object->d3ddev = This;
745 /* Initializes memory */
746 memcpy(&object->desc, Desc, Desc->dwSize);
748 /* No buffer given */
749 if ((object->desc.dwFlags & D3DDEB_LPDATA) == 0)
750 object->desc.lpData = NULL;
752 /* No buffer size given */
753 if ((object->desc.dwFlags & D3DDEB_BUFSIZE) == 0)
754 object->desc.dwBufferSize = 0;
756 /* Create buffer if asked */
757 if ((object->desc.lpData == NULL) && (object->desc.dwBufferSize > 0))
759 object->need_free = TRUE;
760 object->desc.lpData = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,object->desc.dwBufferSize);
761 if(!object->desc.lpData)
763 ERR("Out of memory when allocating the execute buffer data\n");
764 HeapFree(GetProcessHeap(), 0, object);
765 return DDERR_OUTOFMEMORY;
768 else
770 object->need_free = FALSE;
773 /* No vertices for the moment */
774 object->vertex_data = NULL;
776 object->desc.dwFlags |= D3DDEB_LPDATA;
778 object->indices = NULL;
779 object->nb_indices = 0;
781 *ExecuteBuffer = (IDirect3DExecuteBuffer *)object;
783 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
785 return D3D_OK;
788 /*****************************************************************************
789 * IDirect3DDevice::Execute
791 * Executes all the stuff in an execute buffer.
793 * Params:
794 * ExecuteBuffer: The buffer to execute
795 * Viewport: The viewport used for rendering
796 * Flags: Some flags
798 * Returns:
799 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
800 * D3D_OK on success
802 *****************************************************************************/
803 static HRESULT WINAPI
804 IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
805 IDirect3DExecuteBuffer *ExecuteBuffer,
806 IDirect3DViewport *Viewport,
807 DWORD Flags)
809 IDirect3DDeviceImpl *This = device_from_device1(iface);
810 IDirect3DExecuteBufferImpl *Direct3DExecuteBufferImpl = (IDirect3DExecuteBufferImpl *)ExecuteBuffer;
811 IDirect3DViewportImpl *Direct3DViewportImpl = (IDirect3DViewportImpl *)Viewport;
813 TRACE("(%p)->(%p,%p,%08x)\n", This, Direct3DExecuteBufferImpl, Direct3DViewportImpl, Flags);
815 if(!Direct3DExecuteBufferImpl)
816 return DDERR_INVALIDPARAMS;
818 /* Execute... */
819 EnterCriticalSection(&ddraw_cs);
820 IDirect3DExecuteBufferImpl_Execute(Direct3DExecuteBufferImpl, This, Direct3DViewportImpl);
821 LeaveCriticalSection(&ddraw_cs);
823 return D3D_OK;
826 /*****************************************************************************
827 * IDirect3DDevice3::AddViewport
829 * Add a Direct3DViewport to the device's viewport list. These viewports
830 * are wrapped to IDirect3DDevice7 viewports in viewport.c
832 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
833 * are the same interfaces.
835 * Params:
836 * Viewport: The viewport to add
838 * Returns:
839 * DDERR_INVALIDPARAMS if Viewport == NULL
840 * D3D_OK on success
842 *****************************************************************************/
843 static HRESULT WINAPI
844 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
845 IDirect3DViewport3 *Viewport)
847 IDirect3DDeviceImpl *This = device_from_device3(iface);
848 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
850 TRACE("(%p)->(%p)\n", This, vp);
852 /* Sanity check */
853 if(!vp)
854 return DDERR_INVALIDPARAMS;
856 EnterCriticalSection(&ddraw_cs);
857 vp->next = This->viewport_list;
858 This->viewport_list = vp;
859 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
860 so set active_device here. */
861 LeaveCriticalSection(&ddraw_cs);
863 return D3D_OK;
866 static HRESULT WINAPI
867 Thunk_IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
868 IDirect3DViewport2 *Direct3DViewport2)
870 IDirect3DDeviceImpl *This = device_from_device2(iface);
871 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
872 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
873 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
876 static HRESULT WINAPI
877 Thunk_IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
878 IDirect3DViewport *Direct3DViewport)
880 IDirect3DDeviceImpl *This = device_from_device1(iface);
881 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
882 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
883 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
886 /*****************************************************************************
887 * IDirect3DDevice3::DeleteViewport
889 * Deletes a Direct3DViewport from the device's viewport list.
891 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
892 * are equal.
894 * Params:
895 * Viewport: The viewport to delete
897 * Returns:
898 * D3D_OK on success
899 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
901 *****************************************************************************/
902 static HRESULT WINAPI
903 IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface,
904 IDirect3DViewport3 *Viewport)
906 IDirect3DDeviceImpl *This = device_from_device3(iface);
907 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *) Viewport;
908 IDirect3DViewportImpl *cur_viewport, *prev_viewport = NULL;
910 TRACE("(%p)->(%p)\n", This, vp);
912 EnterCriticalSection(&ddraw_cs);
913 cur_viewport = This->viewport_list;
914 while (cur_viewport != NULL)
916 if (cur_viewport == vp)
918 if (prev_viewport == NULL) This->viewport_list = cur_viewport->next;
919 else prev_viewport->next = cur_viewport->next;
920 /* TODO : add desactivate of the viewport and all associated lights... */
921 LeaveCriticalSection(&ddraw_cs);
922 return D3D_OK;
924 prev_viewport = cur_viewport;
925 cur_viewport = cur_viewport->next;
928 LeaveCriticalSection(&ddraw_cs);
929 return DDERR_INVALIDPARAMS;
932 static HRESULT WINAPI
933 Thunk_IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
934 IDirect3DViewport2 *Direct3DViewport2)
936 IDirect3DDeviceImpl *This = device_from_device2(iface);
937 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
938 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
939 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
942 static HRESULT WINAPI
943 Thunk_IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
944 IDirect3DViewport *Direct3DViewport)
946 IDirect3DDeviceImpl *This = device_from_device1(iface);
947 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
948 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
949 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
952 /*****************************************************************************
953 * IDirect3DDevice3::NextViewport
955 * Returns a viewport from the viewport list, depending on the
956 * passed viewport and the flags.
958 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
959 * are equal.
961 * Params:
962 * Viewport: Viewport to use for beginning the search
963 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
965 * Returns:
966 * D3D_OK on success
967 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
969 *****************************************************************************/
970 static HRESULT WINAPI
971 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
972 IDirect3DViewport3 *Viewport3,
973 IDirect3DViewport3 **lplpDirect3DViewport3,
974 DWORD Flags)
976 IDirect3DDeviceImpl *This = device_from_device3(iface);
977 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport3;
978 IDirect3DViewportImpl *res = NULL;
980 TRACE("(%p)->(%p,%p,%08x)\n", This, vp, lplpDirect3DViewport3, Flags);
982 if(!vp)
984 *lplpDirect3DViewport3 = NULL;
985 return DDERR_INVALIDPARAMS;
989 EnterCriticalSection(&ddraw_cs);
990 switch (Flags)
992 case D3DNEXT_NEXT:
994 res = vp->next;
996 break;
997 case D3DNEXT_HEAD:
999 res = This->viewport_list;
1001 break;
1002 case D3DNEXT_TAIL:
1004 IDirect3DViewportImpl *cur_viewport = This->viewport_list;
1005 if (cur_viewport != NULL)
1007 while (cur_viewport->next != NULL) cur_viewport = cur_viewport->next;
1009 res = cur_viewport;
1011 break;
1012 default:
1013 *lplpDirect3DViewport3 = NULL;
1014 LeaveCriticalSection(&ddraw_cs);
1015 return DDERR_INVALIDPARAMS;
1018 *lplpDirect3DViewport3 = (IDirect3DViewport3 *)res;
1019 LeaveCriticalSection(&ddraw_cs);
1020 return D3D_OK;
1023 static HRESULT WINAPI
1024 Thunk_IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
1025 IDirect3DViewport2 *Viewport2,
1026 IDirect3DViewport2 **lplpDirect3DViewport2,
1027 DWORD Flags)
1029 IDirect3DDeviceImpl *This = device_from_device2(iface);
1030 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport2;
1031 IDirect3DViewport3 *res;
1032 HRESULT hr;
1033 TRACE_(ddraw_thunk)("(%p)->(%p,%p,%08x) thunking to IDirect3DDevice3 interface.\n", This, vp, lplpDirect3DViewport2, Flags);
1034 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1035 (IDirect3DViewport3 *)vp, &res, Flags);
1036 *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
1037 return hr;
1040 static HRESULT WINAPI
1041 Thunk_IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
1042 IDirect3DViewport *Viewport,
1043 IDirect3DViewport **lplpDirect3DViewport,
1044 DWORD Flags)
1046 IDirect3DDeviceImpl *This = device_from_device1(iface);
1047 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
1048 IDirect3DViewport3 *res;
1049 HRESULT hr;
1050 TRACE_(ddraw_thunk)("(%p)->(%p,%p,%08x) thunking to IDirect3DDevice3 interface.\n", This, vp, lplpDirect3DViewport, Flags);
1051 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1052 (IDirect3DViewport3 *)vp, &res, Flags);
1053 *lplpDirect3DViewport = (IDirect3DViewport *)res;
1054 return hr;
1057 /*****************************************************************************
1058 * IDirect3DDevice::Pick
1060 * Executes an execute buffer without performing rendering. Instead, a
1061 * list of primitives that intersect with (x1,y1) of the passed rectangle
1062 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
1063 * this list.
1065 * Version 1 only
1067 * Params:
1068 * ExecuteBuffer: Buffer to execute
1069 * Viewport: Viewport to use for execution
1070 * Flags: None are defined, according to the SDK
1071 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
1072 * x2 and y2 are ignored.
1074 * Returns:
1075 * D3D_OK because it's a stub
1077 *****************************************************************************/
1078 static HRESULT WINAPI
1079 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
1080 IDirect3DExecuteBuffer *ExecuteBuffer,
1081 IDirect3DViewport *Viewport,
1082 DWORD Flags,
1083 D3DRECT *Rect)
1085 IDirect3DDeviceImpl *This = device_from_device1(iface);
1086 IDirect3DExecuteBufferImpl *execbuf = (IDirect3DExecuteBufferImpl *)ExecuteBuffer;
1087 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
1088 FIXME("(%p)->(%p,%p,%08x,%p): stub!\n", This, execbuf, vp, Flags, Rect);
1090 return D3D_OK;
1093 /*****************************************************************************
1094 * IDirect3DDevice::GetPickRecords
1096 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1098 * Version 1 only
1100 * Params:
1101 * Count: Pointer to a DWORD containing the numbers of pick records to
1102 * retrieve
1103 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1105 * Returns:
1106 * D3D_OK, because it's a stub
1108 *****************************************************************************/
1109 static HRESULT WINAPI
1110 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1111 DWORD *Count,
1112 D3DPICKRECORD *D3DPickRec)
1114 IDirect3DDeviceImpl *This = device_from_device1(iface);
1115 FIXME("(%p)->(%p,%p): stub!\n", This, Count, D3DPickRec);
1117 return D3D_OK;
1120 /*****************************************************************************
1121 * IDirect3DDevice7::EnumTextureformats
1123 * Enumerates the supported texture formats. It has a list of all possible
1124 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1125 * WineD3D supports it. If so, then it is passed to the app.
1127 * This is for Version 7 and 3, older versions have a different
1128 * callback function and their own implementation
1130 * Params:
1131 * Callback: Callback to call for each enumerated format
1132 * Arg: Argument to pass to the callback
1134 * Returns:
1135 * D3D_OK on success
1136 * DDERR_INVALIDPARAMS if Callback == NULL
1138 *****************************************************************************/
1139 static HRESULT
1140 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1141 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1142 void *Arg)
1144 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1145 HRESULT hr;
1146 WINED3DDISPLAYMODE mode;
1147 unsigned int i;
1149 WINED3DFORMAT FormatList[] = {
1150 /* 32 bit */
1151 WINED3DFMT_B8G8R8A8_UNORM,
1152 WINED3DFMT_B8G8R8X8_UNORM,
1153 /* 24 bit */
1154 WINED3DFMT_B8G8R8_UNORM,
1155 /* 16 Bit */
1156 WINED3DFMT_B5G5R5A1_UNORM,
1157 WINED3DFMT_B4G4R4A4_UNORM,
1158 WINED3DFMT_B5G6R5_UNORM,
1159 WINED3DFMT_B5G5R5X1_UNORM,
1160 /* 8 Bit */
1161 WINED3DFMT_B2G3R3_UNORM,
1162 WINED3DFMT_P8_UINT,
1163 /* FOURCC codes */
1164 WINED3DFMT_DXT1,
1165 WINED3DFMT_DXT3,
1166 WINED3DFMT_DXT5,
1169 WINED3DFORMAT BumpFormatList[] = {
1170 WINED3DFMT_R8G8_SNORM,
1171 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1172 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1173 WINED3DFMT_R8G8B8A8_SNORM,
1174 WINED3DFMT_R16G16_SNORM,
1175 WINED3DFMT_R10G11B11_SNORM,
1176 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1179 TRACE("(%p)->(%p,%p): Relay\n", This, Callback, Arg);
1181 if(!Callback)
1182 return DDERR_INVALIDPARAMS;
1184 EnterCriticalSection(&ddraw_cs);
1186 memset(&mode, 0, sizeof(mode));
1187 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1189 &mode);
1190 if(FAILED(hr)) {
1191 LeaveCriticalSection(&ddraw_cs);
1192 WARN("Cannot get the current adapter format\n");
1193 return hr;
1196 for(i = 0; i < sizeof(FormatList) / sizeof(WINED3DFORMAT); i++)
1198 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1199 WINED3DADAPTER_DEFAULT,
1200 WINED3DDEVTYPE_HAL,
1201 mode.Format,
1202 0 /* Usage */,
1203 WINED3DRTYPE_TEXTURE,
1204 FormatList[i],
1205 SURFACE_OPENGL);
1206 if(hr == D3D_OK)
1208 DDPIXELFORMAT pformat;
1210 memset(&pformat, 0, sizeof(pformat));
1211 pformat.dwSize = sizeof(pformat);
1212 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1214 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1215 hr = Callback(&pformat, Arg);
1216 if(hr != DDENUMRET_OK)
1218 TRACE("Format enumeration cancelled by application\n");
1219 LeaveCriticalSection(&ddraw_cs);
1220 return D3D_OK;
1225 for(i = 0; i < sizeof(BumpFormatList) / sizeof(WINED3DFORMAT); i++)
1227 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1228 WINED3DADAPTER_DEFAULT,
1229 WINED3DDEVTYPE_HAL,
1230 mode.Format,
1231 WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1232 WINED3DRTYPE_TEXTURE,
1233 BumpFormatList[i],
1234 SURFACE_OPENGL);
1235 if(hr == D3D_OK)
1237 DDPIXELFORMAT pformat;
1239 memset(&pformat, 0, sizeof(pformat));
1240 pformat.dwSize = sizeof(pformat);
1241 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1243 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1244 hr = Callback(&pformat, Arg);
1245 if(hr != DDENUMRET_OK)
1247 TRACE("Format enumeration cancelled by application\n");
1248 LeaveCriticalSection(&ddraw_cs);
1249 return D3D_OK;
1253 TRACE("End of enumeration\n");
1254 LeaveCriticalSection(&ddraw_cs);
1255 return D3D_OK;
1258 static HRESULT WINAPI
1259 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1260 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1261 void *Arg)
1263 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1266 static HRESULT WINAPI
1267 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1268 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1269 void *Arg)
1271 HRESULT hr;
1272 WORD old_fpucw;
1274 old_fpucw = d3d_fpu_setup();
1275 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1276 set_fpu_control_word(old_fpucw);
1278 return hr;
1281 static HRESULT WINAPI
1282 Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1283 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1284 void *Arg)
1286 IDirect3DDeviceImpl *This = device_from_device3(iface);
1287 TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice7 interface.\n", This, Callback, Arg);
1288 return IDirect3DDevice7_EnumTextureFormats((IDirect3DDevice7 *)This, Callback, Arg);
1291 /*****************************************************************************
1292 * IDirect3DDevice2::EnumTextureformats
1294 * EnumTextureFormats for Version 1 and 2, see
1295 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1297 * This version has a different callback and does not enumerate FourCC
1298 * formats
1300 *****************************************************************************/
1301 static HRESULT WINAPI
1302 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1303 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1304 void *Arg)
1306 IDirect3DDeviceImpl *This = device_from_device2(iface);
1307 HRESULT hr;
1308 unsigned int i;
1309 WINED3DDISPLAYMODE mode;
1311 WINED3DFORMAT FormatList[] = {
1312 /* 32 bit */
1313 WINED3DFMT_B8G8R8A8_UNORM,
1314 WINED3DFMT_B8G8R8X8_UNORM,
1315 /* 24 bit */
1316 WINED3DFMT_B8G8R8_UNORM,
1317 /* 16 Bit */
1318 WINED3DFMT_B5G5R5A1_UNORM,
1319 WINED3DFMT_B4G4R4A4_UNORM,
1320 WINED3DFMT_B5G6R5_UNORM,
1321 WINED3DFMT_B5G5R5X1_UNORM,
1322 /* 8 Bit */
1323 WINED3DFMT_B2G3R3_UNORM,
1324 WINED3DFMT_P8_UINT,
1325 /* FOURCC codes - Not in this version*/
1328 TRACE("(%p)->(%p,%p): Relay\n", This, Callback, Arg);
1330 if(!Callback)
1331 return DDERR_INVALIDPARAMS;
1333 EnterCriticalSection(&ddraw_cs);
1335 memset(&mode, 0, sizeof(mode));
1336 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1338 &mode);
1339 if(FAILED(hr)) {
1340 LeaveCriticalSection(&ddraw_cs);
1341 WARN("Cannot get the current adapter format\n");
1342 return hr;
1345 for(i = 0; i < sizeof(FormatList) / sizeof(WINED3DFORMAT); i++)
1347 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1348 0 /* Adapter */,
1349 WINED3DDEVTYPE_HAL,
1350 mode.Format,
1351 0 /* Usage */,
1352 WINED3DRTYPE_TEXTURE,
1353 FormatList[i],
1354 SURFACE_OPENGL);
1355 if(hr == D3D_OK)
1357 DDSURFACEDESC sdesc;
1359 memset(&sdesc, 0, sizeof(sdesc));
1360 sdesc.dwSize = sizeof(sdesc);
1361 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1362 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1363 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1364 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1366 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1367 hr = Callback(&sdesc, Arg);
1368 if(hr != DDENUMRET_OK)
1370 TRACE("Format enumeration cancelled by application\n");
1371 LeaveCriticalSection(&ddraw_cs);
1372 return D3D_OK;
1376 TRACE("End of enumeration\n");
1377 LeaveCriticalSection(&ddraw_cs);
1378 return D3D_OK;
1381 static HRESULT WINAPI
1382 Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1383 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1384 void *Arg)
1386 IDirect3DDeviceImpl *This = device_from_device1(iface);
1387 TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice2 interface.\n", This, Callback, Arg);
1388 return IDirect3DDevice2_EnumTextureFormats((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, Callback, Arg);
1391 /*****************************************************************************
1392 * IDirect3DDevice::CreateMatrix
1394 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1395 * allocated for the handle.
1397 * Version 1 only
1399 * Params
1400 * D3DMatHandle: Address to return the handle at
1402 * Returns:
1403 * D3D_OK on success
1404 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1406 *****************************************************************************/
1407 static HRESULT WINAPI
1408 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1410 IDirect3DDeviceImpl *This = device_from_device1(iface);
1411 D3DMATRIX *Matrix;
1412 TRACE("(%p)->(%p)\n", This, D3DMatHandle);
1414 if(!D3DMatHandle)
1415 return DDERR_INVALIDPARAMS;
1417 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1418 if(!Matrix)
1420 ERR("Out of memory when allocating a D3DMATRIX\n");
1421 return DDERR_OUTOFMEMORY;
1424 EnterCriticalSection(&ddraw_cs);
1425 *D3DMatHandle = IDirect3DDeviceImpl_CreateHandle(This);
1426 if(!(*D3DMatHandle))
1428 ERR("Failed to create a matrix handle\n");
1429 HeapFree(GetProcessHeap(), 0, Matrix);
1430 LeaveCriticalSection(&ddraw_cs);
1431 return DDERR_OUTOFMEMORY;
1433 This->Handles[*D3DMatHandle - 1].ptr = Matrix;
1434 This->Handles[*D3DMatHandle - 1].type = DDrawHandle_Matrix;
1435 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1437 LeaveCriticalSection(&ddraw_cs);
1438 return D3D_OK;
1441 /*****************************************************************************
1442 * IDirect3DDevice::SetMatrix
1444 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1445 * allocated for the handle
1447 * Version 1 only
1449 * Params:
1450 * D3DMatHandle: Handle to set the matrix to
1451 * D3DMatrix: Matrix to set
1453 * Returns:
1454 * D3D_OK on success
1455 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1456 * to set is NULL
1458 *****************************************************************************/
1459 static HRESULT WINAPI
1460 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1461 D3DMATRIXHANDLE D3DMatHandle,
1462 D3DMATRIX *D3DMatrix)
1464 IDirect3DDeviceImpl *This = device_from_device1(iface);
1465 TRACE("(%p)->(%08x,%p)\n", This, D3DMatHandle, D3DMatrix);
1467 if( (!D3DMatHandle) || (!D3DMatrix) )
1468 return DDERR_INVALIDPARAMS;
1470 EnterCriticalSection(&ddraw_cs);
1471 if(D3DMatHandle > This->numHandles)
1473 ERR("Handle %d out of range\n", D3DMatHandle);
1474 LeaveCriticalSection(&ddraw_cs);
1475 return DDERR_INVALIDPARAMS;
1477 else if(This->Handles[D3DMatHandle - 1].type != DDrawHandle_Matrix)
1479 ERR("Handle %d is not a matrix handle\n", D3DMatHandle);
1480 LeaveCriticalSection(&ddraw_cs);
1481 return DDERR_INVALIDPARAMS;
1484 if (TRACE_ON(d3d7))
1485 dump_D3DMATRIX(D3DMatrix);
1487 *((D3DMATRIX *) This->Handles[D3DMatHandle - 1].ptr) = *D3DMatrix;
1489 if(This->world == D3DMatHandle)
1491 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1492 WINED3DTS_WORLDMATRIX(0),
1493 (WINED3DMATRIX *) D3DMatrix);
1495 if(This->view == D3DMatHandle)
1497 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1498 WINED3DTS_VIEW,
1499 (WINED3DMATRIX *) D3DMatrix);
1501 if(This->proj == D3DMatHandle)
1503 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1504 WINED3DTS_PROJECTION,
1505 (WINED3DMATRIX *) D3DMatrix);
1508 LeaveCriticalSection(&ddraw_cs);
1509 return D3D_OK;
1512 /*****************************************************************************
1513 * IDirect3DDevice::SetMatrix
1515 * Returns the content of a D3DMATRIX handle
1517 * Version 1 only
1519 * Params:
1520 * D3DMatHandle: Matrix handle to read the content from
1521 * D3DMatrix: Address to store the content at
1523 * Returns:
1524 * D3D_OK on success
1525 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1527 *****************************************************************************/
1528 static HRESULT WINAPI
1529 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1530 D3DMATRIXHANDLE D3DMatHandle,
1531 D3DMATRIX *D3DMatrix)
1533 IDirect3DDeviceImpl *This = device_from_device1(iface);
1534 TRACE("(%p)->(%08x,%p)\n", This, D3DMatHandle, D3DMatrix);
1536 if(!D3DMatrix)
1537 return DDERR_INVALIDPARAMS;
1538 if(!D3DMatHandle)
1539 return DDERR_INVALIDPARAMS;
1541 EnterCriticalSection(&ddraw_cs);
1542 if(D3DMatHandle > This->numHandles)
1544 ERR("Handle %d out of range\n", D3DMatHandle);
1545 LeaveCriticalSection(&ddraw_cs);
1546 return DDERR_INVALIDPARAMS;
1548 else if(This->Handles[D3DMatHandle - 1].type != DDrawHandle_Matrix)
1550 ERR("Handle %d is not a matrix handle\n", D3DMatHandle);
1551 LeaveCriticalSection(&ddraw_cs);
1552 return DDERR_INVALIDPARAMS;
1555 /* The handle is simply a pointer to a D3DMATRIX structure */
1556 *D3DMatrix = *((D3DMATRIX *) This->Handles[D3DMatHandle - 1].ptr);
1558 LeaveCriticalSection(&ddraw_cs);
1559 return D3D_OK;
1562 /*****************************************************************************
1563 * IDirect3DDevice::DeleteMatrix
1565 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1567 * Version 1 only
1569 * Params:
1570 * D3DMatHandle: Handle to destroy
1572 * Returns:
1573 * D3D_OK on success
1574 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1576 *****************************************************************************/
1577 static HRESULT WINAPI
1578 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1579 D3DMATRIXHANDLE D3DMatHandle)
1581 IDirect3DDeviceImpl *This = device_from_device1(iface);
1582 TRACE("(%p)->(%08x)\n", This, D3DMatHandle);
1584 if(!D3DMatHandle)
1585 return DDERR_INVALIDPARAMS;
1587 EnterCriticalSection(&ddraw_cs);
1588 if(D3DMatHandle > This->numHandles)
1590 ERR("Handle %d out of range\n", D3DMatHandle);
1591 LeaveCriticalSection(&ddraw_cs);
1592 return DDERR_INVALIDPARAMS;
1594 else if(This->Handles[D3DMatHandle - 1].type != DDrawHandle_Matrix)
1596 ERR("Handle %d is not a matrix handle\n", D3DMatHandle);
1597 LeaveCriticalSection(&ddraw_cs);
1598 return DDERR_INVALIDPARAMS;
1601 HeapFree(GetProcessHeap(), 0, This->Handles[D3DMatHandle - 1].ptr);
1602 This->Handles[D3DMatHandle - 1].ptr = NULL;
1603 This->Handles[D3DMatHandle - 1].type = DDrawHandle_Unknown;
1605 LeaveCriticalSection(&ddraw_cs);
1606 return D3D_OK;
1609 /*****************************************************************************
1610 * IDirect3DDevice7::BeginScene
1612 * This method must be called before any rendering is performed.
1613 * IDirect3DDevice::EndScene has to be called after the scene is complete
1615 * Version 1, 2, 3 and 7
1617 * Returns:
1618 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1619 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1620 * started scene).
1622 *****************************************************************************/
1623 static HRESULT
1624 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1626 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1627 HRESULT hr;
1628 TRACE("(%p): Relay\n", This);
1630 EnterCriticalSection(&ddraw_cs);
1631 hr = IWineD3DDevice_BeginScene(This->wineD3DDevice);
1632 LeaveCriticalSection(&ddraw_cs);
1633 if(hr == WINED3D_OK) return D3D_OK;
1634 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1637 static HRESULT WINAPI
1638 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1640 return IDirect3DDeviceImpl_7_BeginScene(iface);
1643 static HRESULT WINAPI
1644 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1646 HRESULT hr;
1647 WORD old_fpucw;
1649 old_fpucw = d3d_fpu_setup();
1650 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1651 set_fpu_control_word(old_fpucw);
1653 return hr;
1656 static HRESULT WINAPI
1657 Thunk_IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1659 IDirect3DDeviceImpl *This = device_from_device3(iface);
1660 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1661 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)This);
1664 static HRESULT WINAPI
1665 Thunk_IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1667 IDirect3DDeviceImpl *This = device_from_device2(iface);
1668 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1669 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)This);
1672 static HRESULT WINAPI
1673 Thunk_IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1675 IDirect3DDeviceImpl *This = device_from_device1(iface);
1676 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1677 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)This);
1680 /*****************************************************************************
1681 * IDirect3DDevice7::EndScene
1683 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1684 * This method must be called after rendering is finished.
1686 * Version 1, 2, 3 and 7
1688 * Returns:
1689 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1690 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1691 * that only if the scene was already ended.
1693 *****************************************************************************/
1694 static HRESULT
1695 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1697 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1698 HRESULT hr;
1699 TRACE("(%p): Relay\n", This);
1701 EnterCriticalSection(&ddraw_cs);
1702 hr = IWineD3DDevice_EndScene(This->wineD3DDevice);
1703 LeaveCriticalSection(&ddraw_cs);
1704 if(hr == WINED3D_OK) return D3D_OK;
1705 else return D3DERR_SCENE_NOT_IN_SCENE;
1708 static HRESULT WINAPI DECLSPEC_HOTPATCH
1709 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1711 return IDirect3DDeviceImpl_7_EndScene(iface);
1714 static HRESULT WINAPI DECLSPEC_HOTPATCH
1715 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1717 HRESULT hr;
1718 WORD old_fpucw;
1720 old_fpucw = d3d_fpu_setup();
1721 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1722 set_fpu_control_word(old_fpucw);
1724 return hr;
1727 static HRESULT WINAPI DECLSPEC_HOTPATCH
1728 Thunk_IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1730 IDirect3DDeviceImpl *This = device_from_device3(iface);
1731 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1732 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)This);
1735 static HRESULT WINAPI DECLSPEC_HOTPATCH
1736 Thunk_IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1738 IDirect3DDeviceImpl *This = device_from_device2(iface);
1739 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1740 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)This);
1743 static HRESULT WINAPI DECLSPEC_HOTPATCH
1744 Thunk_IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1746 IDirect3DDeviceImpl *This = device_from_device1(iface);
1747 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1748 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)This);
1751 /*****************************************************************************
1752 * IDirect3DDevice7::GetDirect3D
1754 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1755 * this device.
1757 * Params:
1758 * Direct3D7: Address to store the interface pointer at
1760 * Returns:
1761 * D3D_OK on success
1762 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1764 *****************************************************************************/
1765 static HRESULT WINAPI
1766 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1767 IDirect3D7 **Direct3D7)
1769 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1770 TRACE("(%p)->(%p)\n", This, Direct3D7);
1772 if(!Direct3D7)
1773 return DDERR_INVALIDPARAMS;
1775 *Direct3D7 = (IDirect3D7 *)&This->ddraw->IDirect3D7_vtbl;
1776 IDirect3D7_AddRef(*Direct3D7);
1778 TRACE(" returning interface %p\n", *Direct3D7);
1779 return D3D_OK;
1782 static HRESULT WINAPI
1783 Thunk_IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1784 IDirect3D3 **Direct3D3)
1786 IDirect3DDeviceImpl *This = device_from_device3(iface);
1787 HRESULT ret;
1788 IDirect3D7 *ret_ptr;
1790 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Direct3D3);
1791 ret = IDirect3DDevice7_GetDirect3D((IDirect3DDevice7 *)This, &ret_ptr);
1792 if(ret != D3D_OK)
1793 return ret;
1794 *Direct3D3 = ret_ptr ? (IDirect3D3 *)&ddraw_from_d3d7(ret_ptr)->IDirect3D3_vtbl : NULL;
1795 TRACE(" returning interface %p\n", *Direct3D3);
1796 return D3D_OK;
1799 static HRESULT WINAPI
1800 Thunk_IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1801 IDirect3D2 **Direct3D2)
1803 IDirect3DDeviceImpl *This = device_from_device2(iface);
1804 HRESULT ret;
1805 IDirect3D7 *ret_ptr;
1807 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Direct3D2);
1808 ret = IDirect3DDevice7_GetDirect3D((IDirect3DDevice7 *)This, &ret_ptr);
1809 if(ret != D3D_OK)
1810 return ret;
1811 *Direct3D2 = ret_ptr ? (IDirect3D2 *)&ddraw_from_d3d7(ret_ptr)->IDirect3D2_vtbl : NULL;
1812 TRACE(" returning interface %p\n", *Direct3D2);
1813 return D3D_OK;
1816 static HRESULT WINAPI
1817 Thunk_IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1818 IDirect3D **Direct3D)
1820 IDirect3DDeviceImpl *This = device_from_device1(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((IDirect3DDevice7 *)This, &ret_ptr);
1826 if(ret != D3D_OK)
1827 return ret;
1828 *Direct3D = ret_ptr ? (IDirect3D *)&ddraw_from_d3d7(ret_ptr)->IDirect3D_vtbl : NULL;
1829 TRACE(" returning interface %p\n", *Direct3D);
1830 return D3D_OK;
1833 /*****************************************************************************
1834 * IDirect3DDevice3::SetCurrentViewport
1836 * Sets a Direct3DViewport as the current viewport.
1837 * For the thunks note that all viewport interface versions are equal
1839 * Params:
1840 * Direct3DViewport3: The viewport to set
1842 * Version 2 and 3
1844 * Returns:
1845 * D3D_OK on success
1846 * (Is a NULL viewport valid?)
1848 *****************************************************************************/
1849 static HRESULT WINAPI
1850 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1851 IDirect3DViewport3 *Direct3DViewport3)
1853 IDirect3DDeviceImpl *This = device_from_device3(iface);
1854 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport3;
1855 TRACE("(%p)->(%p)\n", This, Direct3DViewport3);
1857 EnterCriticalSection(&ddraw_cs);
1858 /* Do nothing if the specified viewport is the same as the current one */
1859 if (This->current_viewport == vp )
1861 LeaveCriticalSection(&ddraw_cs);
1862 return D3D_OK;
1865 /* Should check if the viewport was added or not */
1867 /* Release previous viewport and AddRef the new one */
1868 if (This->current_viewport)
1870 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1871 (IDirect3DViewport3 *)This->current_viewport);
1872 IDirect3DViewport3_Release((IDirect3DViewport3 *)This->current_viewport);
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 IDirect3DDeviceImpl *This = device_from_device2(iface);
1892 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
1893 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
1894 return IDirect3DDevice3_SetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1895 (IDirect3DViewport3 *)vp);
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 IDirect3DDeviceImpl *This = device_from_device3(iface);
1918 TRACE("(%p)->(%p)\n", This, Direct3DViewport3);
1920 if(!Direct3DViewport3)
1921 return DDERR_INVALIDPARAMS;
1923 EnterCriticalSection(&ddraw_cs);
1924 *Direct3DViewport3 = (IDirect3DViewport3 *)This->current_viewport;
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 IDirect3DDeviceImpl *This = device_from_device2(iface);
1940 HRESULT hr;
1941 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, Direct3DViewport2);
1942 hr = IDirect3DDevice3_GetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1943 (IDirect3DViewport3 **)Direct3DViewport2);
1944 if(hr != D3D_OK) return hr;
1945 return D3D_OK;
1948 /*****************************************************************************
1949 * IDirect3DDevice7::SetRenderTarget
1951 * Sets the render target for the Direct3DDevice.
1952 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1953 * IDirectDrawSurface3 == IDirectDrawSurface
1955 * Version 2, 3 and 7
1957 * Params:
1958 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1959 * render target
1960 * Flags: Some flags
1962 * Returns:
1963 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1965 *****************************************************************************/
1966 static HRESULT
1967 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1968 IDirectDrawSurface7 *NewTarget,
1969 DWORD Flags)
1971 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1972 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewTarget;
1973 HRESULT hr;
1974 TRACE("(%p)->(%p,%08x): Relay\n", This, NewTarget, Flags);
1976 EnterCriticalSection(&ddraw_cs);
1977 /* Flags: Not used */
1979 if(This->target == Target)
1981 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1982 LeaveCriticalSection(&ddraw_cs);
1983 return D3D_OK;
1986 hr = IWineD3DDevice_SetRenderTarget(This->wineD3DDevice,
1988 Target ? Target->WineD3DSurface : NULL,
1989 FALSE);
1990 if(hr != D3D_OK)
1992 LeaveCriticalSection(&ddraw_cs);
1993 return hr;
1995 IDirectDrawSurface7_AddRef(NewTarget);
1996 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->target);
1997 This->target = Target;
1998 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1999 LeaveCriticalSection(&ddraw_cs);
2000 return D3D_OK;
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 IDirect3DDeviceImpl *This = device_from_device3(iface);
2032 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
2033 TRACE_(ddraw_thunk)("(%p)->(%p,%08x) thunking to IDirect3DDevice7 interface.\n", This, Target, Flags);
2034 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
2037 static HRESULT WINAPI
2038 Thunk_IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
2039 IDirectDrawSurface *NewRenderTarget,
2040 DWORD Flags)
2042 IDirect3DDeviceImpl *This = device_from_device2(iface);
2043 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
2044 TRACE_(ddraw_thunk)("(%p)->(%p,%08x) thunking to IDirect3DDevice7 interface.\n", This, Target, Flags);
2045 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
2048 /*****************************************************************************
2049 * IDirect3DDevice7::GetRenderTarget
2051 * Returns the current render target.
2052 * This is handled locally, because the WineD3D render target's parent
2053 * is an IParent
2055 * Version 2, 3 and 7
2057 * Params:
2058 * RenderTarget: Address to store the surface interface pointer
2060 * Returns:
2061 * D3D_OK on success
2062 * DDERR_INVALIDPARAMS if RenderTarget == NULL
2064 *****************************************************************************/
2065 static HRESULT WINAPI
2066 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
2067 IDirectDrawSurface7 **RenderTarget)
2069 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2070 TRACE("(%p)->(%p): Relay\n", This, RenderTarget);
2072 if(!RenderTarget)
2073 return DDERR_INVALIDPARAMS;
2075 EnterCriticalSection(&ddraw_cs);
2076 *RenderTarget = (IDirectDrawSurface7 *)This->target;
2077 IDirectDrawSurface7_AddRef(*RenderTarget);
2079 LeaveCriticalSection(&ddraw_cs);
2080 return D3D_OK;
2083 static HRESULT WINAPI
2084 Thunk_IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
2085 IDirectDrawSurface4 **RenderTarget)
2087 IDirect3DDeviceImpl *This = device_from_device3(iface);
2088 HRESULT hr;
2089 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, RenderTarget);
2090 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
2091 if(hr != D3D_OK) return hr;
2092 return D3D_OK;
2095 static HRESULT WINAPI
2096 Thunk_IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
2097 IDirectDrawSurface **RenderTarget)
2099 IDirect3DDeviceImpl *This = device_from_device2(iface);
2100 HRESULT hr;
2101 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, RenderTarget);
2102 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
2103 if(hr != D3D_OK) return hr;
2104 *RenderTarget = *RenderTarget ?
2105 (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)*RenderTarget)->IDirectDrawSurface3_vtbl : NULL;
2106 return D3D_OK;
2109 /*****************************************************************************
2110 * IDirect3DDevice3::Begin
2112 * Begins a description block of vertices. This is similar to glBegin()
2113 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2114 * described with IDirect3DDevice::Vertex are drawn.
2116 * Version 2 and 3
2118 * Params:
2119 * PrimitiveType: The type of primitives to draw
2120 * VertexTypeDesc: A flexible vertex format description of the vertices
2121 * Flags: Some flags..
2123 * Returns:
2124 * D3D_OK on success
2126 *****************************************************************************/
2127 static HRESULT WINAPI
2128 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2129 D3DPRIMITIVETYPE PrimitiveType,
2130 DWORD VertexTypeDesc,
2131 DWORD Flags)
2133 IDirect3DDeviceImpl *This = device_from_device3(iface);
2134 TRACE("(%p)->(%d,%d,%08x)\n", This, PrimitiveType, VertexTypeDesc, Flags);
2136 EnterCriticalSection(&ddraw_cs);
2137 This->primitive_type = PrimitiveType;
2138 This->vertex_type = VertexTypeDesc;
2139 This->render_flags = Flags;
2140 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2141 This->nb_vertices = 0;
2142 LeaveCriticalSection(&ddraw_cs);
2144 return D3D_OK;
2147 static HRESULT WINAPI
2148 Thunk_IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface,
2149 D3DPRIMITIVETYPE d3dpt,
2150 D3DVERTEXTYPE dwVertexTypeDesc,
2151 DWORD dwFlags)
2153 DWORD FVF;
2154 IDirect3DDeviceImpl *This = device_from_device2(iface);
2155 TRACE_(ddraw_thunk)("(%p/%p)->(%08x,%08x,%08x): Thunking to IDirect3DDevice3\n", This, iface, d3dpt, dwVertexTypeDesc, dwFlags);
2157 switch(dwVertexTypeDesc)
2159 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2160 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2161 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2162 default:
2163 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2164 return DDERR_INVALIDPARAMS; /* Should never happen */
2167 return IDirect3DDevice3_Begin((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, d3dpt, FVF, dwFlags);
2170 /*****************************************************************************
2171 * IDirect3DDevice3::BeginIndexed
2173 * Draws primitives based on vertices in a vertex array which are specified
2174 * by indices.
2176 * Version 2 and 3
2178 * Params:
2179 * PrimitiveType: Primitive type to draw
2180 * VertexType: A FVF description of the vertex format
2181 * Vertices: pointer to an array containing the vertices
2182 * NumVertices: The number of vertices in the vertex array
2183 * Flags: Some flags ...
2185 * Returns:
2186 * D3D_OK, because it's a stub
2188 *****************************************************************************/
2189 static HRESULT WINAPI
2190 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2191 D3DPRIMITIVETYPE PrimitiveType,
2192 DWORD VertexType,
2193 void *Vertices,
2194 DWORD NumVertices,
2195 DWORD Flags)
2197 IDirect3DDeviceImpl *This = device_from_device3(iface);
2198 FIXME("(%p)->(%08x,%08x,%p,%08x,%08x): stub!\n", This, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2199 return D3D_OK;
2203 static HRESULT WINAPI
2204 Thunk_IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2205 D3DPRIMITIVETYPE d3dptPrimitiveType,
2206 D3DVERTEXTYPE d3dvtVertexType,
2207 void *lpvVertices,
2208 DWORD dwNumVertices,
2209 DWORD dwFlags)
2211 DWORD FVF;
2212 IDirect3DDeviceImpl *This = device_from_device2(iface);
2213 TRACE_(ddraw_thunk)("(%p/%p)->(%08x,%08x,%p,%08x,%08x): Thunking to IDirect3DDevice3\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2215 switch(d3dvtVertexType)
2217 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2218 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2219 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2220 default:
2221 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2222 return DDERR_INVALIDPARAMS; /* Should never happen */
2225 return IDirect3DDevice3_BeginIndexed((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2226 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2229 /*****************************************************************************
2230 * IDirect3DDevice3::Vertex
2232 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2233 * drawn vertices in a vertex buffer. If the buffer is too small, its
2234 * size is increased.
2236 * Version 2 and 3
2238 * Params:
2239 * Vertex: Pointer to the vertex
2241 * Returns:
2242 * D3D_OK, on success
2243 * DDERR_INVALIDPARAMS if Vertex is NULL
2245 *****************************************************************************/
2246 static HRESULT WINAPI
2247 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2248 void *Vertex)
2250 IDirect3DDeviceImpl *This = device_from_device3(iface);
2251 TRACE("(%p)->(%p)\n", This, Vertex);
2253 if(!Vertex)
2254 return DDERR_INVALIDPARAMS;
2256 EnterCriticalSection(&ddraw_cs);
2257 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2259 BYTE *old_buffer;
2260 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2261 old_buffer = This->vertex_buffer;
2262 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2263 if (old_buffer)
2265 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2266 HeapFree(GetProcessHeap(), 0, old_buffer);
2270 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2272 LeaveCriticalSection(&ddraw_cs);
2273 return D3D_OK;
2276 static HRESULT WINAPI
2277 Thunk_IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface,
2278 void *lpVertexType)
2280 IDirect3DDeviceImpl *This = device_from_device2(iface);
2281 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, lpVertexType);
2282 return IDirect3DDevice3_Vertex((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, lpVertexType);
2285 /*****************************************************************************
2286 * IDirect3DDevice3::Index
2288 * Specifies an index to a vertex to be drawn. The vertex array has to
2289 * be specified with BeginIndexed first.
2291 * Parameters:
2292 * VertexIndex: The index of the vertex to draw
2294 * Returns:
2295 * D3D_OK because it's a stub
2297 *****************************************************************************/
2298 static HRESULT WINAPI
2299 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2300 WORD VertexIndex)
2302 IDirect3DDeviceImpl *This = device_from_device3(iface);
2303 FIXME("(%p)->(%04x): stub!\n", This, VertexIndex);
2304 return D3D_OK;
2307 static HRESULT WINAPI
2308 Thunk_IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface,
2309 WORD wVertexIndex)
2311 IDirect3DDeviceImpl *This = device_from_device2(iface);
2312 TRACE_(ddraw_thunk)("(%p)->(%04x) thunking to IDirect3DDevice3 interface.\n", This, wVertexIndex);
2313 return IDirect3DDevice3_Index((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, wVertexIndex);
2316 /*****************************************************************************
2317 * IDirect3DDevice3::End
2319 * Ends a draw begun with IDirect3DDevice3::Begin or
2320 * IDirect3DDevice::BeginIndexed. The vertices specified with
2321 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2322 * the IDirect3DDevice7::DrawPrimitive method. So far only
2323 * non-indexed mode is supported
2325 * Version 2 and 3
2327 * Params:
2328 * Flags: Some flags, as usual. Don't know which are defined
2330 * Returns:
2331 * The return value of IDirect3DDevice7::DrawPrimitive
2333 *****************************************************************************/
2334 static HRESULT WINAPI
2335 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2336 DWORD Flags)
2338 IDirect3DDeviceImpl *This = device_from_device3(iface);
2339 TRACE("(%p)->(%08x)\n", This, Flags);
2341 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This, This->primitive_type,
2342 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2345 static HRESULT WINAPI
2346 Thunk_IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface,
2347 DWORD dwFlags)
2349 IDirect3DDeviceImpl *This = device_from_device2(iface);
2350 TRACE_(ddraw_thunk)("(%p)->(%08x) thunking to IDirect3DDevice3 interface.\n", This, dwFlags);
2351 return IDirect3DDevice3_End((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, dwFlags);
2354 /*****************************************************************************
2355 * IDirect3DDevice7::GetRenderState
2357 * Returns the value of a render state. The possible render states are
2358 * defined in include/d3dtypes.h
2360 * Version 2, 3 and 7
2362 * Params:
2363 * RenderStateType: Render state to return the current setting of
2364 * Value: Address to store the value at
2366 * Returns:
2367 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2368 * DDERR_INVALIDPARAMS if Value == NULL
2370 *****************************************************************************/
2371 static HRESULT
2372 IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2373 D3DRENDERSTATETYPE RenderStateType,
2374 DWORD *Value)
2376 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2377 HRESULT hr;
2378 TRACE("(%p)->(%08x,%p): Relay\n", This, RenderStateType, Value);
2380 if(!Value)
2381 return DDERR_INVALIDPARAMS;
2383 EnterCriticalSection(&ddraw_cs);
2384 switch(RenderStateType)
2386 case D3DRENDERSTATE_TEXTUREMAG:
2388 WINED3DTEXTUREFILTERTYPE tex_mag;
2390 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2391 0, WINED3DSAMP_MAGFILTER,
2392 &tex_mag);
2394 switch (tex_mag)
2396 case WINED3DTEXF_POINT:
2397 *Value = D3DFILTER_NEAREST;
2398 break;
2399 case WINED3DTEXF_LINEAR:
2400 *Value = D3DFILTER_LINEAR;
2401 break;
2402 default:
2403 ERR("Unhandled texture mag %d !\n",tex_mag);
2404 *Value = 0;
2406 break;
2409 case D3DRENDERSTATE_TEXTUREMIN:
2411 WINED3DTEXTUREFILTERTYPE tex_min;
2412 WINED3DTEXTUREFILTERTYPE tex_mip;
2414 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2415 0, WINED3DSAMP_MINFILTER, &tex_min);
2416 if (FAILED(hr))
2418 LeaveCriticalSection(&ddraw_cs);
2419 return hr;
2421 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2422 0, WINED3DSAMP_MIPFILTER, &tex_mip);
2424 switch (tex_min)
2426 case WINED3DTEXF_POINT:
2427 switch (tex_mip)
2429 case WINED3DTEXF_NONE:
2430 *Value = D3DFILTER_NEAREST;
2431 break;
2432 case WINED3DTEXF_POINT:
2433 *Value = D3DFILTER_MIPNEAREST;
2434 break;
2435 case WINED3DTEXF_LINEAR:
2436 *Value = D3DFILTER_LINEARMIPNEAREST;
2437 break;
2438 default:
2439 ERR("Unhandled mip filter %#x.\n", tex_mip);
2440 *Value = D3DFILTER_NEAREST;
2441 break;
2443 break;
2444 case WINED3DTEXF_LINEAR:
2445 switch (tex_mip)
2447 case WINED3DTEXF_NONE:
2448 *Value = D3DFILTER_LINEAR;
2449 break;
2450 case WINED3DTEXF_POINT:
2451 *Value = D3DFILTER_MIPLINEAR;
2452 break;
2453 case WINED3DTEXF_LINEAR:
2454 *Value = D3DFILTER_LINEARMIPLINEAR;
2455 break;
2456 default:
2457 ERR("Unhandled mip filter %#x.\n", tex_mip);
2458 *Value = D3DFILTER_LINEAR;
2459 break;
2461 break;
2462 default:
2463 ERR("Unhandled texture min filter %#x.\n",tex_min);
2464 *Value = D3DFILTER_NEAREST;
2465 break;
2467 break;
2470 case D3DRENDERSTATE_TEXTUREADDRESS:
2471 case D3DRENDERSTATE_TEXTUREADDRESSU:
2472 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2473 0, WINED3DSAMP_ADDRESSU,
2474 Value);
2475 break;
2476 case D3DRENDERSTATE_TEXTUREADDRESSV:
2477 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2478 0, WINED3DSAMP_ADDRESSV,
2479 Value);
2480 break;
2482 case D3DRENDERSTATE_BORDERCOLOR:
2483 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2484 hr = E_NOTIMPL;
2485 break;
2487 default:
2488 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2489 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2491 FIXME("Unhandled stipple pattern render state (%#x).\n",
2492 RenderStateType);
2493 hr = E_NOTIMPL;
2494 break;
2496 hr = IWineD3DDevice_GetRenderState(This->wineD3DDevice,
2497 RenderStateType,
2498 Value);
2500 LeaveCriticalSection(&ddraw_cs);
2501 return hr;
2504 static HRESULT WINAPI
2505 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2506 D3DRENDERSTATETYPE RenderStateType,
2507 DWORD *Value)
2509 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2512 static HRESULT WINAPI
2513 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2514 D3DRENDERSTATETYPE RenderStateType,
2515 DWORD *Value)
2517 HRESULT hr;
2518 WORD old_fpucw;
2520 old_fpucw = d3d_fpu_setup();
2521 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2522 set_fpu_control_word(old_fpucw);
2524 return hr;
2527 static HRESULT WINAPI
2528 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2529 D3DRENDERSTATETYPE dwRenderStateType,
2530 DWORD *lpdwRenderState)
2532 IDirect3DDeviceImpl *This = device_from_device3(iface);
2533 HRESULT hr;
2534 TRACE("(%p)->(%08x,%p)\n", This, dwRenderStateType, lpdwRenderState);
2536 switch(dwRenderStateType)
2538 case D3DRENDERSTATE_TEXTUREHANDLE:
2540 /* This state is wrapped to SetTexture in SetRenderState, so
2541 * it has to be wrapped to GetTexture here
2543 IWineD3DBaseTexture *tex = NULL;
2544 *lpdwRenderState = 0;
2546 EnterCriticalSection(&ddraw_cs);
2548 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2550 &tex);
2552 if(hr == WINED3D_OK && tex)
2554 IDirectDrawSurface7 *parent = NULL;
2555 hr = IWineD3DBaseTexture_GetParent(tex,
2556 (IUnknown **) &parent);
2557 if(parent)
2559 /* The parent of the texture is the IDirectDrawSurface7 interface
2560 * of the ddraw surface
2562 IDirectDrawSurfaceImpl *texImpl = (IDirectDrawSurfaceImpl *)parent;
2563 *lpdwRenderState = texImpl->Handle;
2564 IDirectDrawSurface7_Release(parent);
2566 IWineD3DBaseTexture_Release(tex);
2569 LeaveCriticalSection(&ddraw_cs);
2571 return hr;
2574 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2576 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2577 the mapping to get the value. */
2578 DWORD colorop, colorarg1, colorarg2;
2579 DWORD alphaop, alphaarg1, alphaarg2;
2581 EnterCriticalSection(&ddraw_cs);
2583 This->legacyTextureBlending = TRUE;
2585 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, &colorop);
2586 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, &colorarg1);
2587 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, &colorarg2);
2588 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, &alphaop);
2589 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2590 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2592 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2593 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2595 *lpdwRenderState = D3DTBLEND_DECAL;
2597 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2598 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2600 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2602 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2603 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2605 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2607 else
2609 HRESULT hr;
2610 BOOL tex_alpha = FALSE;
2611 IWineD3DBaseTexture *tex = NULL;
2612 WINED3DSURFACE_DESC desc;
2613 DDPIXELFORMAT ddfmt;
2615 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2617 &tex);
2619 if(hr == WINED3D_OK && tex)
2621 hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2622 if (SUCCEEDED(hr))
2624 ddfmt.dwSize = sizeof(ddfmt);
2625 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2626 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2629 IWineD3DBaseTexture_Release(tex);
2632 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2633 alphaop == (tex_alpha ? WINED3DTOP_SELECTARG1 : WINED3DTOP_SELECTARG2) &&
2634 alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2636 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2639 *lpdwRenderState = D3DTBLEND_MODULATE;
2642 LeaveCriticalSection(&ddraw_cs);
2644 return D3D_OK;
2647 default:
2648 return IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, dwRenderStateType, lpdwRenderState);
2652 static HRESULT WINAPI
2653 Thunk_IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2654 D3DRENDERSTATETYPE dwRenderStateType,
2655 DWORD *lpdwRenderState)
2657 IDirect3DDeviceImpl *This = device_from_device2(iface);
2658 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice3 interface.\n", This, dwRenderStateType, lpdwRenderState);
2659 return IDirect3DDevice3_GetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2660 dwRenderStateType, lpdwRenderState);
2663 /*****************************************************************************
2664 * IDirect3DDevice7::SetRenderState
2666 * Sets a render state. The possible render states are defined in
2667 * include/d3dtypes.h
2669 * Version 2, 3 and 7
2671 * Params:
2672 * RenderStateType: State to set
2673 * Value: Value to assign to that state
2675 * Returns:
2676 * D3D_OK on success,
2677 * for details see IWineD3DDevice::SetRenderState
2679 *****************************************************************************/
2680 static HRESULT
2681 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2682 D3DRENDERSTATETYPE RenderStateType,
2683 DWORD Value)
2685 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2686 HRESULT hr;
2687 TRACE("(%p)->(%08x,%d): Relay\n", This, RenderStateType, Value);
2689 EnterCriticalSection(&ddraw_cs);
2690 /* Some render states need special care */
2691 switch(RenderStateType)
2694 * The ddraw texture filter mapping works like this:
2695 * D3DFILTER_NEAREST Point min/mag, no mip
2696 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2697 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2699 * D3DFILTER_LINEAR Linear min/mag, no mip
2700 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2701 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2703 * This is the opposite of the GL naming convention,
2704 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2706 case D3DRENDERSTATE_TEXTUREMAG:
2708 WINED3DTEXTUREFILTERTYPE tex_mag;
2710 switch (Value)
2712 case D3DFILTER_NEAREST:
2713 case D3DFILTER_MIPNEAREST:
2714 case D3DFILTER_LINEARMIPNEAREST:
2715 tex_mag = WINED3DTEXF_POINT;
2716 break;
2717 case D3DFILTER_LINEAR:
2718 case D3DFILTER_MIPLINEAR:
2719 case D3DFILTER_LINEARMIPLINEAR:
2720 tex_mag = WINED3DTEXF_LINEAR;
2721 break;
2722 default:
2723 tex_mag = WINED3DTEXF_POINT;
2724 ERR("Unhandled texture mag %d !\n",Value);
2725 break;
2728 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2729 0, WINED3DSAMP_MAGFILTER,
2730 tex_mag);
2731 break;
2734 case D3DRENDERSTATE_TEXTUREMIN:
2736 WINED3DTEXTUREFILTERTYPE tex_min;
2737 WINED3DTEXTUREFILTERTYPE tex_mip;
2739 switch ((D3DTEXTUREFILTER) Value)
2741 case D3DFILTER_NEAREST:
2742 tex_min = WINED3DTEXF_POINT;
2743 tex_mip = WINED3DTEXF_NONE;
2744 break;
2745 case D3DFILTER_LINEAR:
2746 tex_min = WINED3DTEXF_LINEAR;
2747 tex_mip = WINED3DTEXF_NONE;
2748 break;
2749 case D3DFILTER_MIPNEAREST:
2750 tex_min = WINED3DTEXF_POINT;
2751 tex_mip = WINED3DTEXF_POINT;
2752 break;
2753 case D3DFILTER_MIPLINEAR:
2754 tex_min = WINED3DTEXF_LINEAR;
2755 tex_mip = WINED3DTEXF_POINT;
2756 break;
2757 case D3DFILTER_LINEARMIPNEAREST:
2758 tex_min = WINED3DTEXF_POINT;
2759 tex_mip = WINED3DTEXF_LINEAR;
2760 break;
2761 case D3DFILTER_LINEARMIPLINEAR:
2762 tex_min = WINED3DTEXF_LINEAR;
2763 tex_mip = WINED3DTEXF_LINEAR;
2764 break;
2766 default:
2767 ERR("Unhandled texture min %d !\n",Value);
2768 tex_min = WINED3DTEXF_POINT;
2769 tex_mip = WINED3DTEXF_NONE;
2770 break;
2773 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2774 0, WINED3DSAMP_MIPFILTER, tex_mip);
2775 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2776 0, WINED3DSAMP_MINFILTER,
2777 tex_min);
2778 break;
2781 case D3DRENDERSTATE_TEXTUREADDRESS:
2782 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2783 0, WINED3DSAMP_ADDRESSV,
2784 Value);
2785 /* Drop through */
2786 case D3DRENDERSTATE_TEXTUREADDRESSU:
2787 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2788 0, WINED3DSAMP_ADDRESSU,
2789 Value);
2790 break;
2791 case D3DRENDERSTATE_TEXTUREADDRESSV:
2792 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2793 0, WINED3DSAMP_ADDRESSV,
2794 Value);
2795 break;
2797 case D3DRENDERSTATE_BORDERCOLOR:
2798 /* This should probably just forward to the corresponding sampler
2799 * state. Needs tests. */
2800 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2801 hr = E_NOTIMPL;
2802 break;
2804 default:
2805 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2806 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2808 FIXME("Unhandled stipple pattern render state (%#x).\n",
2809 RenderStateType);
2810 hr = E_NOTIMPL;
2811 break;
2814 hr = IWineD3DDevice_SetRenderState(This->wineD3DDevice,
2815 RenderStateType,
2816 Value);
2817 break;
2819 LeaveCriticalSection(&ddraw_cs);
2820 return hr;
2823 static HRESULT WINAPI
2824 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2825 D3DRENDERSTATETYPE RenderStateType,
2826 DWORD Value)
2828 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2831 static HRESULT WINAPI
2832 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2833 D3DRENDERSTATETYPE RenderStateType,
2834 DWORD Value)
2836 HRESULT hr;
2837 WORD old_fpucw;
2839 old_fpucw = d3d_fpu_setup();
2840 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2841 set_fpu_control_word(old_fpucw);
2843 return hr;
2846 static HRESULT WINAPI
2847 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2848 D3DRENDERSTATETYPE RenderStateType,
2849 DWORD Value)
2851 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2852 for this state can be directly mapped to texture stage colorop and alphaop, but
2853 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2854 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2855 alphaarg when needed.
2857 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2859 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2860 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2861 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2862 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2863 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2864 in device - TRUE if the app is using TEXTUREMAPBLEND.
2866 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2867 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2868 unless some broken game will be found that cares. */
2870 HRESULT hr;
2871 IDirect3DDeviceImpl *This = device_from_device3(iface);
2872 TRACE("(%p)->(%08x,%d)\n", This, RenderStateType, Value);
2874 EnterCriticalSection(&ddraw_cs);
2876 switch(RenderStateType)
2878 case D3DRENDERSTATE_TEXTUREHANDLE:
2880 if(Value == 0)
2882 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
2884 NULL);
2885 break;
2888 if(Value > This->numHandles)
2890 FIXME("Specified handle %d out of range\n", Value);
2891 hr = DDERR_INVALIDPARAMS;
2892 break;
2894 if(This->Handles[Value - 1].type != DDrawHandle_Texture)
2896 FIXME("Handle %d isn't a texture handle\n", Value);
2897 hr = DDERR_INVALIDPARAMS;
2898 break;
2900 else
2902 IDirectDrawSurfaceImpl *surf = This->Handles[Value - 1].ptr;
2903 IDirect3DTexture2 *tex = surf ? (IDirect3DTexture2 *)&surf->IDirect3DTexture2_vtbl : NULL;
2904 hr = IDirect3DDevice3_SetTexture(iface, 0, tex);
2905 break;
2909 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2911 This->legacyTextureBlending = TRUE;
2913 switch ( (D3DTEXTUREBLEND) Value)
2915 case D3DTBLEND_MODULATE:
2917 BOOL tex_alpha = FALSE;
2918 IWineD3DBaseTexture *tex = NULL;
2919 WINED3DSURFACE_DESC desc;
2920 DDPIXELFORMAT ddfmt;
2922 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2924 &tex);
2926 if(hr == WINED3D_OK && tex)
2928 memset(&desc, 0, sizeof(desc));
2929 hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2930 if (SUCCEEDED(hr))
2932 ddfmt.dwSize = sizeof(ddfmt);
2933 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2934 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2937 IWineD3DBaseTexture_Release(tex);
2940 if (tex_alpha)
2941 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2942 else
2943 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2944 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2945 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2946 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2947 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2948 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2950 break;
2953 case D3DTBLEND_ADD:
2954 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2955 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2956 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2957 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2958 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2959 break;
2961 case D3DTBLEND_MODULATEALPHA:
2962 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2963 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2964 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2965 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2966 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2967 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2968 break;
2970 case D3DTBLEND_COPY:
2971 case D3DTBLEND_DECAL:
2972 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2973 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2974 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2975 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2976 break;
2978 case D3DTBLEND_DECALALPHA:
2979 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2980 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2981 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2982 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2983 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2984 break;
2986 default:
2987 ERR("Unhandled texture environment %d !\n",Value);
2990 hr = D3D_OK;
2991 break;
2994 default:
2995 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, RenderStateType, Value);
2996 break;
2999 LeaveCriticalSection(&ddraw_cs);
3001 return hr;
3004 static HRESULT WINAPI
3005 Thunk_IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
3006 D3DRENDERSTATETYPE RenderStateType,
3007 DWORD Value)
3009 IDirect3DDeviceImpl *This = device_from_device2(iface);
3010 TRACE_(ddraw_thunk)("(%p)->(%08x,%d) thunking to IDirect3DDevice3 interface.\n", This, RenderStateType, Value);
3011 return IDirect3DDevice3_SetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, RenderStateType, Value);
3014 /*****************************************************************************
3015 * Direct3DDevice3::SetLightState
3017 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
3018 * light states are forwarded to Direct3DDevice7 render states
3020 * Version 2 and 3
3022 * Params:
3023 * LightStateType: The light state to change
3024 * Value: The value to assign to that light state
3026 * Returns:
3027 * D3D_OK on success
3028 * DDERR_INVALIDPARAMS if the parameters were incorrect
3029 * Also check IDirect3DDevice7::SetRenderState
3031 *****************************************************************************/
3032 static HRESULT WINAPI
3033 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
3034 D3DLIGHTSTATETYPE LightStateType,
3035 DWORD Value)
3037 IDirect3DDeviceImpl *This = device_from_device3(iface);
3038 HRESULT hr;
3040 TRACE("(%p)->(%08x,%08x)\n", This, LightStateType, Value);
3042 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3044 TRACE("Unexpected Light State Type\n");
3045 return DDERR_INVALIDPARAMS;
3048 EnterCriticalSection(&ddraw_cs);
3049 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3051 IDirect3DMaterialImpl *mat;
3053 if(Value == 0) mat = NULL;
3054 else if(Value > This->numHandles)
3056 ERR("Material handle out of range(%d)\n", Value);
3057 LeaveCriticalSection(&ddraw_cs);
3058 return DDERR_INVALIDPARAMS;
3060 else if(This->Handles[Value - 1].type != DDrawHandle_Material)
3062 ERR("Invalid handle %d\n", Value);
3063 LeaveCriticalSection(&ddraw_cs);
3064 return DDERR_INVALIDPARAMS;
3066 else
3068 mat = This->Handles[Value - 1].ptr;
3071 if (mat != NULL)
3073 TRACE(" activating material %p.\n", mat);
3074 mat->activate(mat);
3076 else
3078 FIXME(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
3080 This->material = Value;
3082 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3084 switch (Value)
3086 case D3DCOLOR_MONO:
3087 ERR("DDCOLOR_MONO should not happen!\n");
3088 break;
3089 case D3DCOLOR_RGB:
3090 /* We are already in this mode */
3091 TRACE("Setting color model to RGB (no-op).\n");
3092 break;
3093 default:
3094 ERR("Unknown color model!\n");
3095 LeaveCriticalSection(&ddraw_cs);
3096 return DDERR_INVALIDPARAMS;
3099 else
3101 D3DRENDERSTATETYPE rs;
3102 switch (LightStateType)
3104 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3105 rs = D3DRENDERSTATE_AMBIENT;
3106 break;
3107 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3108 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3109 break;
3110 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3111 rs = D3DRENDERSTATE_FOGSTART;
3112 break;
3113 case D3DLIGHTSTATE_FOGEND: /* 6 */
3114 rs = D3DRENDERSTATE_FOGEND;
3115 break;
3116 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3117 rs = D3DRENDERSTATE_FOGDENSITY;
3118 break;
3119 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3120 rs = D3DRENDERSTATE_COLORVERTEX;
3121 break;
3122 default:
3123 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3124 LeaveCriticalSection(&ddraw_cs);
3125 return DDERR_INVALIDPARAMS;
3128 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, rs, Value);
3129 LeaveCriticalSection(&ddraw_cs);
3130 return hr;
3133 LeaveCriticalSection(&ddraw_cs);
3134 return D3D_OK;
3137 static HRESULT WINAPI
3138 Thunk_IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3139 D3DLIGHTSTATETYPE LightStateType,
3140 DWORD Value)
3142 IDirect3DDeviceImpl *This = device_from_device2(iface);
3143 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x) thunking to IDirect3DDevice3 interface.\n", This, LightStateType, Value);
3144 return IDirect3DDevice3_SetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3147 /*****************************************************************************
3148 * IDirect3DDevice3::GetLightState
3150 * Returns the current setting of a light state. The state is read from
3151 * the Direct3DDevice7 render state.
3153 * Version 2 and 3
3155 * Params:
3156 * LightStateType: The light state to return
3157 * Value: The address to store the light state setting at
3159 * Returns:
3160 * D3D_OK on success
3161 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3162 * Also see IDirect3DDevice7::GetRenderState
3164 *****************************************************************************/
3165 static HRESULT WINAPI
3166 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3167 D3DLIGHTSTATETYPE LightStateType,
3168 DWORD *Value)
3170 IDirect3DDeviceImpl *This = device_from_device3(iface);
3171 HRESULT hr;
3173 TRACE("(%p)->(%08x,%p)\n", This, LightStateType, Value);
3175 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3177 TRACE("Unexpected Light State Type\n");
3178 return DDERR_INVALIDPARAMS;
3181 if(!Value)
3182 return DDERR_INVALIDPARAMS;
3184 EnterCriticalSection(&ddraw_cs);
3185 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3187 *Value = This->material;
3189 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3191 *Value = D3DCOLOR_RGB;
3193 else
3195 D3DRENDERSTATETYPE rs;
3196 switch (LightStateType)
3198 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3199 rs = D3DRENDERSTATE_AMBIENT;
3200 break;
3201 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3202 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3203 break;
3204 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3205 rs = D3DRENDERSTATE_FOGSTART;
3206 break;
3207 case D3DLIGHTSTATE_FOGEND: /* 6 */
3208 rs = D3DRENDERSTATE_FOGEND;
3209 break;
3210 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3211 rs = D3DRENDERSTATE_FOGDENSITY;
3212 break;
3213 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3214 rs = D3DRENDERSTATE_COLORVERTEX;
3215 break;
3216 default:
3217 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3218 LeaveCriticalSection(&ddraw_cs);
3219 return DDERR_INVALIDPARAMS;
3222 hr = IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, rs, Value);
3223 LeaveCriticalSection(&ddraw_cs);
3224 return hr;
3227 LeaveCriticalSection(&ddraw_cs);
3228 return D3D_OK;
3231 static HRESULT WINAPI
3232 Thunk_IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3233 D3DLIGHTSTATETYPE LightStateType,
3234 DWORD *Value)
3236 IDirect3DDeviceImpl *This = device_from_device2(iface);
3237 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice3 interface.\n", This, LightStateType, Value);
3238 return IDirect3DDevice3_GetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3241 /*****************************************************************************
3242 * IDirect3DDevice7::SetTransform
3244 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3245 * in include/d3dtypes.h.
3246 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3247 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3248 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3250 * Version 2, 3 and 7
3252 * Params:
3253 * TransformStateType: transform state to set
3254 * Matrix: Matrix to assign to the state
3256 * Returns:
3257 * D3D_OK on success
3258 * DDERR_INVALIDPARAMS if Matrix == NULL
3259 * For details see IWineD3DDevice::SetTransform
3261 *****************************************************************************/
3262 static HRESULT
3263 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3264 D3DTRANSFORMSTATETYPE TransformStateType,
3265 D3DMATRIX *Matrix)
3267 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3268 D3DTRANSFORMSTATETYPE type;
3269 HRESULT hr;
3270 TRACE("(%p)->(%08x,%p): Relay\n", This, TransformStateType, Matrix);
3272 switch(TransformStateType)
3274 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3275 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3276 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3277 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3278 default: type = TransformStateType;
3281 if(!Matrix)
3282 return DDERR_INVALIDPARAMS;
3284 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3285 EnterCriticalSection(&ddraw_cs);
3286 hr = IWineD3DDevice_SetTransform(This->wineD3DDevice,
3287 type,
3288 (WINED3DMATRIX*) Matrix);
3289 LeaveCriticalSection(&ddraw_cs);
3290 return hr;
3293 static HRESULT WINAPI
3294 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3295 D3DTRANSFORMSTATETYPE TransformStateType,
3296 D3DMATRIX *Matrix)
3298 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3301 static HRESULT WINAPI
3302 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3303 D3DTRANSFORMSTATETYPE TransformStateType,
3304 D3DMATRIX *Matrix)
3306 HRESULT hr;
3307 WORD old_fpucw;
3309 old_fpucw = d3d_fpu_setup();
3310 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3311 set_fpu_control_word(old_fpucw);
3313 return hr;
3316 static HRESULT WINAPI
3317 Thunk_IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3318 D3DTRANSFORMSTATETYPE TransformStateType,
3319 D3DMATRIX *D3DMatrix)
3321 IDirect3DDeviceImpl *This = device_from_device3(iface);
3322 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3323 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3326 static HRESULT WINAPI
3327 Thunk_IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3328 D3DTRANSFORMSTATETYPE TransformStateType,
3329 D3DMATRIX *D3DMatrix)
3331 IDirect3DDeviceImpl *This = device_from_device2(iface);
3332 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3333 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3336 /*****************************************************************************
3337 * IDirect3DDevice7::GetTransform
3339 * Returns the matrix assigned to a transform state
3340 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3341 * SetTransform
3343 * Params:
3344 * TransformStateType: State to read the matrix from
3345 * Matrix: Address to store the matrix at
3347 * Returns:
3348 * D3D_OK on success
3349 * DDERR_INVALIDPARAMS if Matrix == NULL
3350 * For details, see IWineD3DDevice::GetTransform
3352 *****************************************************************************/
3353 static HRESULT
3354 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3355 D3DTRANSFORMSTATETYPE TransformStateType,
3356 D3DMATRIX *Matrix)
3358 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3359 D3DTRANSFORMSTATETYPE type;
3360 HRESULT hr;
3361 TRACE("(%p)->(%08x,%p): Relay\n", This, TransformStateType, Matrix);
3363 switch(TransformStateType)
3365 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3366 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3367 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3368 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3369 default: type = TransformStateType;
3372 if(!Matrix)
3373 return DDERR_INVALIDPARAMS;
3375 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3376 EnterCriticalSection(&ddraw_cs);
3377 hr = IWineD3DDevice_GetTransform(This->wineD3DDevice, type, (WINED3DMATRIX*) Matrix);
3378 LeaveCriticalSection(&ddraw_cs);
3379 return hr;
3382 static HRESULT WINAPI
3383 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3384 D3DTRANSFORMSTATETYPE TransformStateType,
3385 D3DMATRIX *Matrix)
3387 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3390 static HRESULT WINAPI
3391 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3392 D3DTRANSFORMSTATETYPE TransformStateType,
3393 D3DMATRIX *Matrix)
3395 HRESULT hr;
3396 WORD old_fpucw;
3398 old_fpucw = d3d_fpu_setup();
3399 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3400 set_fpu_control_word(old_fpucw);
3402 return hr;
3405 static HRESULT WINAPI
3406 Thunk_IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3407 D3DTRANSFORMSTATETYPE TransformStateType,
3408 D3DMATRIX *D3DMatrix)
3410 IDirect3DDeviceImpl *This = device_from_device3(iface);
3411 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3412 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3415 static HRESULT WINAPI
3416 Thunk_IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3417 D3DTRANSFORMSTATETYPE TransformStateType,
3418 D3DMATRIX *D3DMatrix)
3420 IDirect3DDeviceImpl *This = device_from_device2(iface);
3421 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3422 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3425 /*****************************************************************************
3426 * IDirect3DDevice7::MultiplyTransform
3428 * Multiplies the already-set transform matrix of a transform state
3429 * with another matrix. For the world matrix, see SetTransform
3431 * Version 2, 3 and 7
3433 * Params:
3434 * TransformStateType: Transform state to multiply
3435 * D3DMatrix Matrix to multiply with.
3437 * Returns
3438 * D3D_OK on success
3439 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3440 * For details, see IWineD3DDevice::MultiplyTransform
3442 *****************************************************************************/
3443 static HRESULT
3444 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3445 D3DTRANSFORMSTATETYPE TransformStateType,
3446 D3DMATRIX *D3DMatrix)
3448 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3449 HRESULT hr;
3450 D3DTRANSFORMSTATETYPE type;
3451 TRACE("(%p)->(%08x,%p): Relay\n", This, TransformStateType, D3DMatrix);
3453 switch(TransformStateType)
3455 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3456 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3457 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3458 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3459 default: type = TransformStateType;
3462 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3463 EnterCriticalSection(&ddraw_cs);
3464 hr = IWineD3DDevice_MultiplyTransform(This->wineD3DDevice,
3465 type,
3466 (WINED3DMATRIX*) D3DMatrix);
3467 LeaveCriticalSection(&ddraw_cs);
3468 return hr;
3471 static HRESULT WINAPI
3472 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3473 D3DTRANSFORMSTATETYPE TransformStateType,
3474 D3DMATRIX *D3DMatrix)
3476 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3479 static HRESULT WINAPI
3480 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3481 D3DTRANSFORMSTATETYPE TransformStateType,
3482 D3DMATRIX *D3DMatrix)
3484 HRESULT hr;
3485 WORD old_fpucw;
3487 old_fpucw = d3d_fpu_setup();
3488 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3489 set_fpu_control_word(old_fpucw);
3491 return hr;
3494 static HRESULT WINAPI
3495 Thunk_IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3496 D3DTRANSFORMSTATETYPE TransformStateType,
3497 D3DMATRIX *D3DMatrix)
3499 IDirect3DDeviceImpl *This = device_from_device3(iface);
3500 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3501 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3504 static HRESULT WINAPI
3505 Thunk_IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3506 D3DTRANSFORMSTATETYPE TransformStateType,
3507 D3DMATRIX *D3DMatrix)
3509 IDirect3DDeviceImpl *This = device_from_device2(iface);
3510 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3511 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3514 /*****************************************************************************
3515 * IDirect3DDevice7::DrawPrimitive
3517 * Draws primitives based on vertices in an application-provided pointer
3519 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3520 * an FVF format for D3D7
3522 * Params:
3523 * PrimitiveType: The type of the primitives to draw
3524 * Vertex type: Flexible vertex format vertex description
3525 * Vertices: Pointer to the vertex array
3526 * VertexCount: The number of vertices to draw
3527 * Flags: As usual a few flags
3529 * Returns:
3530 * D3D_OK on success
3531 * DDERR_INVALIDPARAMS if Vertices is NULL
3532 * For details, see IWineD3DDevice::DrawPrimitiveUP
3534 *****************************************************************************/
3535 static HRESULT
3536 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3537 D3DPRIMITIVETYPE PrimitiveType,
3538 DWORD VertexType,
3539 void *Vertices,
3540 DWORD VertexCount,
3541 DWORD Flags)
3543 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3544 UINT stride;
3545 HRESULT hr;
3546 TRACE("(%p)->(%08x,%08x,%p,%08x,%08x): Relay!\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3548 if(!Vertices)
3549 return DDERR_INVALIDPARAMS;
3551 /* Get the stride */
3552 stride = get_flexible_vertex_size(VertexType);
3554 /* Set the FVF */
3555 EnterCriticalSection(&ddraw_cs);
3556 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice, ddraw_find_decl(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 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3565 hr = IWineD3DDevice_DrawPrimitiveUP(This->wineD3DDevice, VertexCount, Vertices, stride);
3566 LeaveCriticalSection(&ddraw_cs);
3567 return hr;
3570 static HRESULT WINAPI
3571 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3572 D3DPRIMITIVETYPE PrimitiveType,
3573 DWORD VertexType,
3574 void *Vertices,
3575 DWORD VertexCount,
3576 DWORD Flags)
3578 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3581 static HRESULT WINAPI
3582 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3583 D3DPRIMITIVETYPE PrimitiveType,
3584 DWORD VertexType,
3585 void *Vertices,
3586 DWORD VertexCount,
3587 DWORD Flags)
3589 HRESULT hr;
3590 WORD old_fpucw;
3592 old_fpucw = d3d_fpu_setup();
3593 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3594 set_fpu_control_word(old_fpucw);
3596 return hr;
3599 static HRESULT WINAPI
3600 Thunk_IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3601 D3DPRIMITIVETYPE PrimitiveType,
3602 DWORD VertexType,
3603 void *Vertices,
3604 DWORD VertexCount,
3605 DWORD Flags)
3607 IDirect3DDeviceImpl *This = device_from_device3(iface);
3608 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3609 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This,
3610 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3613 static HRESULT WINAPI
3614 Thunk_IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3615 D3DPRIMITIVETYPE PrimitiveType,
3616 D3DVERTEXTYPE VertexType,
3617 void *Vertices,
3618 DWORD VertexCount,
3619 DWORD Flags)
3621 IDirect3DDeviceImpl *This = device_from_device2(iface);
3622 DWORD FVF;
3623 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3625 switch(VertexType)
3627 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3628 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3629 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3630 default:
3631 ERR("Unexpected vertex type %d\n", VertexType);
3632 return DDERR_INVALIDPARAMS; /* Should never happen */
3635 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This, PrimitiveType, FVF, Vertices, VertexCount, Flags);
3638 /*****************************************************************************
3639 * IDirect3DDevice7::DrawIndexedPrimitive
3641 * Draws vertices from an application-provided pointer, based on the index
3642 * numbers in a WORD array.
3644 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3645 * an FVF format for D3D7
3647 * Params:
3648 * PrimitiveType: The primitive type to draw
3649 * VertexType: The FVF vertex description
3650 * Vertices: Pointer to the vertex array
3651 * VertexCount: ?
3652 * Indices: Pointer to the index array
3653 * IndexCount: Number of indices = Number of vertices to draw
3654 * Flags: As usual, some flags
3656 * Returns:
3657 * D3D_OK on success
3658 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3659 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3661 *****************************************************************************/
3662 static HRESULT
3663 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3664 D3DPRIMITIVETYPE PrimitiveType,
3665 DWORD VertexType,
3666 void *Vertices,
3667 DWORD VertexCount,
3668 WORD *Indices,
3669 DWORD IndexCount,
3670 DWORD Flags)
3672 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3673 HRESULT hr;
3674 TRACE("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x): Relay!\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3676 /* Set the D3DDevice's FVF */
3677 EnterCriticalSection(&ddraw_cs);
3678 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice, ddraw_find_decl(This->ddraw, VertexType));
3679 if(FAILED(hr))
3681 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3682 LeaveCriticalSection(&ddraw_cs);
3683 return hr;
3686 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3687 hr = IWineD3DDevice_DrawIndexedPrimitiveUP(This->wineD3DDevice, IndexCount, Indices,
3688 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3689 LeaveCriticalSection(&ddraw_cs);
3690 return hr;
3693 static HRESULT WINAPI
3694 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3695 D3DPRIMITIVETYPE PrimitiveType,
3696 DWORD VertexType,
3697 void *Vertices,
3698 DWORD VertexCount,
3699 WORD *Indices,
3700 DWORD IndexCount,
3701 DWORD Flags)
3703 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3706 static HRESULT WINAPI
3707 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3708 D3DPRIMITIVETYPE PrimitiveType,
3709 DWORD VertexType,
3710 void *Vertices,
3711 DWORD VertexCount,
3712 WORD *Indices,
3713 DWORD IndexCount,
3714 DWORD Flags)
3716 HRESULT hr;
3717 WORD old_fpucw;
3719 old_fpucw = d3d_fpu_setup();
3720 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3721 set_fpu_control_word(old_fpucw);
3723 return hr;
3726 static HRESULT WINAPI
3727 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3728 D3DPRIMITIVETYPE PrimitiveType,
3729 DWORD VertexType,
3730 void *Vertices,
3731 DWORD VertexCount,
3732 WORD *Indices,
3733 DWORD IndexCount,
3734 DWORD Flags)
3736 IDirect3DDeviceImpl *This = device_from_device3(iface);
3737 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3738 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)This,
3739 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3742 static HRESULT WINAPI
3743 Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3744 D3DPRIMITIVETYPE PrimitiveType,
3745 D3DVERTEXTYPE VertexType,
3746 void *Vertices,
3747 DWORD VertexCount,
3748 WORD *Indices,
3749 DWORD IndexCount,
3750 DWORD Flags)
3752 DWORD FVF;
3753 IDirect3DDeviceImpl *This = device_from_device2(iface);
3754 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3756 switch(VertexType)
3758 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3759 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3760 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3761 default:
3762 ERR("Unexpected vertex type %d\n", VertexType);
3763 return DDERR_INVALIDPARAMS; /* Should never happen */
3766 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)This,
3767 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3770 /*****************************************************************************
3771 * IDirect3DDevice7::SetClipStatus
3773 * Sets the clip status. This defines things as clipping conditions and
3774 * the extents of the clipping region.
3776 * Version 2, 3 and 7
3778 * Params:
3779 * ClipStatus:
3781 * Returns:
3782 * D3D_OK because it's a stub
3783 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3785 *****************************************************************************/
3786 static HRESULT WINAPI
3787 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3788 D3DCLIPSTATUS *ClipStatus)
3790 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3791 FIXME("(%p)->(%p): Stub!\n", This, ClipStatus);
3793 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3794 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3796 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3797 return D3D_OK;
3800 static HRESULT WINAPI
3801 Thunk_IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3802 D3DCLIPSTATUS *ClipStatus)
3804 IDirect3DDeviceImpl *This = device_from_device3(iface);
3805 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3806 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)This, ClipStatus);
3809 static HRESULT WINAPI
3810 Thunk_IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3811 D3DCLIPSTATUS *ClipStatus)
3813 IDirect3DDeviceImpl *This = device_from_device2(iface);
3814 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3815 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)This, ClipStatus);
3818 /*****************************************************************************
3819 * IDirect3DDevice7::GetClipStatus
3821 * Returns the clip status
3823 * Params:
3824 * ClipStatus: Address to write the clip status to
3826 * Returns:
3827 * D3D_OK because it's a stub
3829 *****************************************************************************/
3830 static HRESULT WINAPI
3831 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3832 D3DCLIPSTATUS *ClipStatus)
3834 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3835 FIXME("(%p)->(%p): Stub!\n", This, ClipStatus);
3837 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3838 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3839 return D3D_OK;
3842 static HRESULT WINAPI
3843 Thunk_IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3844 D3DCLIPSTATUS *ClipStatus)
3846 IDirect3DDeviceImpl *This = device_from_device3(iface);
3847 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3848 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)This, ClipStatus);
3851 static HRESULT WINAPI
3852 Thunk_IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3853 D3DCLIPSTATUS *ClipStatus)
3855 IDirect3DDeviceImpl *This = device_from_device2(iface);
3856 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3857 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)This, ClipStatus);
3860 /*****************************************************************************
3861 * IDirect3DDevice::DrawPrimitiveStrided
3863 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3865 * Version 3 and 7
3867 * Params:
3868 * PrimitiveType: The primitive type to draw
3869 * VertexType: The FVF description of the vertices to draw (for the stride??)
3870 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3871 * the vertex data locations
3872 * VertexCount: The number of vertices to draw
3873 * Flags: Some flags
3875 * Returns:
3876 * D3D_OK, because it's a stub
3877 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3878 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3880 *****************************************************************************/
3881 static HRESULT
3882 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3883 D3DPRIMITIVETYPE PrimitiveType,
3884 DWORD VertexType,
3885 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3886 DWORD VertexCount,
3887 DWORD Flags)
3889 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3890 WineDirect3DVertexStridedData WineD3DStrided;
3891 DWORD i;
3892 HRESULT hr;
3894 TRACE("(%p)->(%08x,%08x,%p,%08x,%08x): stub!\n", This, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3896 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3897 /* Get the strided data right. the wined3d structure is a bit bigger
3898 * Watch out: The contents of the strided data are determined by the fvf,
3899 * not by the members set in D3DDrawPrimStrideData. So it's valid
3900 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3901 * not set in the fvf.
3903 if(VertexType & D3DFVF_POSITION_MASK)
3905 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3906 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3907 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3908 if (VertexType & D3DFVF_XYZRHW)
3910 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3911 WineD3DStrided.position_transformed = TRUE;
3912 } else
3913 WineD3DStrided.position_transformed = FALSE;
3916 if(VertexType & D3DFVF_NORMAL)
3918 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3919 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3920 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3923 if(VertexType & D3DFVF_DIFFUSE)
3925 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3926 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3927 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3930 if(VertexType & D3DFVF_SPECULAR)
3932 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3933 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3934 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3937 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3939 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3941 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3942 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3943 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3944 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3945 default: ERR("Unexpected texture coordinate size %d\n",
3946 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3948 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3949 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3952 /* WineD3D doesn't need the FVF here */
3953 EnterCriticalSection(&ddraw_cs);
3954 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3955 hr = IWineD3DDevice_DrawPrimitiveStrided(This->wineD3DDevice, VertexCount, &WineD3DStrided);
3956 LeaveCriticalSection(&ddraw_cs);
3957 return hr;
3960 static HRESULT WINAPI
3961 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3962 D3DPRIMITIVETYPE PrimitiveType,
3963 DWORD VertexType,
3964 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3965 DWORD VertexCount,
3966 DWORD Flags)
3968 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3971 static HRESULT WINAPI
3972 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3973 D3DPRIMITIVETYPE PrimitiveType,
3974 DWORD VertexType,
3975 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3976 DWORD VertexCount,
3977 DWORD Flags)
3979 HRESULT hr;
3980 WORD old_fpucw;
3982 old_fpucw = d3d_fpu_setup();
3983 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3984 set_fpu_control_word(old_fpucw);
3986 return hr;
3989 static HRESULT WINAPI
3990 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3991 D3DPRIMITIVETYPE PrimitiveType,
3992 DWORD VertexType,
3993 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3994 DWORD VertexCount,
3995 DWORD Flags)
3997 IDirect3DDeviceImpl *This = device_from_device3(iface);
3998 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3999 return IDirect3DDevice7_DrawPrimitiveStrided((IDirect3DDevice7 *)This,
4000 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4003 /*****************************************************************************
4004 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
4006 * Draws primitives specified by strided data locations based on indices
4008 * Version 3 and 7
4010 * Params:
4011 * PrimitiveType:
4013 * Returns:
4014 * D3D_OK, because it's a stub
4015 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
4016 * (DDERR_INVALIDPARAMS if Indices is NULL)
4017 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
4019 *****************************************************************************/
4020 static HRESULT
4021 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
4022 D3DPRIMITIVETYPE PrimitiveType,
4023 DWORD VertexType,
4024 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4025 DWORD VertexCount,
4026 WORD *Indices,
4027 DWORD IndexCount,
4028 DWORD Flags)
4030 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4031 WineDirect3DVertexStridedData WineD3DStrided;
4032 DWORD i;
4033 HRESULT hr;
4035 TRACE("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x)\n", This, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4037 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
4038 /* Get the strided data right. the wined3d structure is a bit bigger
4039 * Watch out: The contents of the strided data are determined by the fvf,
4040 * not by the members set in D3DDrawPrimStrideData. So it's valid
4041 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
4042 * not set in the fvf.
4044 if(VertexType & D3DFVF_POSITION_MASK)
4046 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
4047 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
4048 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
4049 if (VertexType & D3DFVF_XYZRHW)
4051 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
4052 WineD3DStrided.position_transformed = TRUE;
4053 } else
4054 WineD3DStrided.position_transformed = FALSE;
4057 if(VertexType & D3DFVF_NORMAL)
4059 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
4060 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
4061 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
4064 if(VertexType & D3DFVF_DIFFUSE)
4066 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
4067 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
4068 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
4071 if(VertexType & D3DFVF_SPECULAR)
4073 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
4074 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
4075 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
4078 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
4080 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
4082 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
4083 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
4084 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
4085 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
4086 default: ERR("Unexpected texture coordinate size %d\n",
4087 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4089 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4090 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4093 /* WineD3D doesn't need the FVF here */
4094 EnterCriticalSection(&ddraw_cs);
4095 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4096 hr = IWineD3DDevice_DrawIndexedPrimitiveStrided(This->wineD3DDevice,
4097 IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
4098 LeaveCriticalSection(&ddraw_cs);
4099 return hr;
4102 static HRESULT WINAPI
4103 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4104 D3DPRIMITIVETYPE PrimitiveType,
4105 DWORD VertexType,
4106 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4107 DWORD VertexCount,
4108 WORD *Indices,
4109 DWORD IndexCount,
4110 DWORD Flags)
4112 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4115 static HRESULT WINAPI
4116 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4117 D3DPRIMITIVETYPE PrimitiveType,
4118 DWORD VertexType,
4119 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4120 DWORD VertexCount,
4121 WORD *Indices,
4122 DWORD IndexCount,
4123 DWORD Flags)
4125 HRESULT hr;
4126 WORD old_fpucw;
4128 old_fpucw = d3d_fpu_setup();
4129 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4130 set_fpu_control_word(old_fpucw);
4132 return hr;
4135 static HRESULT WINAPI
4136 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4137 D3DPRIMITIVETYPE PrimitiveType,
4138 DWORD VertexType,
4139 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4140 DWORD VertexCount,
4141 WORD *Indices,
4142 DWORD IndexCount,
4143 DWORD Flags)
4145 IDirect3DDeviceImpl *This = device_from_device3(iface);
4146 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4147 return IDirect3DDevice7_DrawIndexedPrimitiveStrided((IDirect3DDevice7 *)This, PrimitiveType,
4148 VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4151 /*****************************************************************************
4152 * IDirect3DDevice7::DrawPrimitiveVB
4154 * Draws primitives from a vertex buffer to the screen.
4156 * Version 3 and 7
4158 * Params:
4159 * PrimitiveType: Type of primitive to be rendered.
4160 * D3DVertexBuf: Source Vertex Buffer
4161 * StartVertex: Index of the first vertex from the buffer to be rendered
4162 * NumVertices: Number of vertices to be rendered
4163 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4165 * Return values
4166 * D3D_OK on success
4167 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4169 *****************************************************************************/
4170 static HRESULT
4171 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4172 D3DPRIMITIVETYPE PrimitiveType,
4173 IDirect3DVertexBuffer7 *D3DVertexBuf,
4174 DWORD StartVertex,
4175 DWORD NumVertices,
4176 DWORD Flags)
4178 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4179 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4180 HRESULT hr;
4181 DWORD stride;
4183 TRACE("(%p)->(%08x,%p,%08x,%08x,%08x)\n", This, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4185 /* Sanity checks */
4186 if(!vb)
4188 ERR("(%p) No Vertex buffer specified\n", This);
4189 return DDERR_INVALIDPARAMS;
4191 stride = get_flexible_vertex_size(vb->fvf);
4193 EnterCriticalSection(&ddraw_cs);
4194 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4195 vb->wineD3DVertexDeclaration);
4196 if(FAILED(hr))
4198 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4199 LeaveCriticalSection(&ddraw_cs);
4200 return hr;
4203 /* Set the vertex stream source */
4204 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4205 0 /* StreamNumber */,
4206 vb->wineD3DVertexBuffer,
4207 0 /* StartVertex - we pass this to DrawPrimitive */,
4208 stride);
4209 if(hr != D3D_OK)
4211 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4212 LeaveCriticalSection(&ddraw_cs);
4213 return hr;
4216 /* Now draw the primitives */
4217 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4218 hr = IWineD3DDevice_DrawPrimitive(This->wineD3DDevice, StartVertex, NumVertices);
4219 LeaveCriticalSection(&ddraw_cs);
4220 return hr;
4223 static HRESULT WINAPI
4224 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4225 D3DPRIMITIVETYPE PrimitiveType,
4226 IDirect3DVertexBuffer7 *D3DVertexBuf,
4227 DWORD StartVertex,
4228 DWORD NumVertices,
4229 DWORD Flags)
4231 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4234 static HRESULT WINAPI
4235 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4236 D3DPRIMITIVETYPE PrimitiveType,
4237 IDirect3DVertexBuffer7 *D3DVertexBuf,
4238 DWORD StartVertex,
4239 DWORD NumVertices,
4240 DWORD Flags)
4242 HRESULT hr;
4243 WORD old_fpucw;
4245 old_fpucw = d3d_fpu_setup();
4246 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4247 set_fpu_control_word(old_fpucw);
4249 return hr;
4252 static HRESULT WINAPI
4253 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4254 D3DPRIMITIVETYPE PrimitiveType,
4255 IDirect3DVertexBuffer *D3DVertexBuf,
4256 DWORD StartVertex,
4257 DWORD NumVertices,
4258 DWORD Flags)
4260 IDirect3DDeviceImpl *This = device_from_device3(iface);
4261 IDirect3DVertexBufferImpl *vb = D3DVertexBuf ? vb_from_vb1(D3DVertexBuf) : NULL;
4262 TRACE_(ddraw_thunk)("(%p)->(%08x,%p,%08x,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, vb, StartVertex, NumVertices, Flags);
4263 return IDirect3DDevice7_DrawPrimitiveVB((IDirect3DDevice7 *)This, PrimitiveType,
4264 (IDirect3DVertexBuffer7 *)vb, StartVertex, NumVertices, Flags);
4268 /*****************************************************************************
4269 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4271 * Draws primitives from a vertex buffer to the screen
4273 * Params:
4274 * PrimitiveType: Type of primitive to be rendered.
4275 * D3DVertexBuf: Source Vertex Buffer
4276 * StartVertex: Index of the first vertex from the buffer to be rendered
4277 * NumVertices: Number of vertices to be rendered
4278 * Indices: Array of DWORDs used to index into the Vertices
4279 * IndexCount: Number of indices in Indices
4280 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4282 * Return values
4284 *****************************************************************************/
4285 static HRESULT
4286 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4287 D3DPRIMITIVETYPE PrimitiveType,
4288 IDirect3DVertexBuffer7 *D3DVertexBuf,
4289 DWORD StartVertex,
4290 DWORD NumVertices,
4291 WORD *Indices,
4292 DWORD IndexCount,
4293 DWORD Flags)
4295 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4296 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4297 DWORD stride = get_flexible_vertex_size(vb->fvf);
4298 WORD *LockedIndices;
4299 HRESULT hr;
4300 WINED3DBUFFER_DESC desc;
4302 TRACE("(%p)->(%08x,%p,%d,%d,%p,%d,%08x)\n", This, PrimitiveType, vb, StartVertex, NumVertices, Indices, IndexCount, Flags);
4304 /* Steps:
4305 * 1) Upload the Indices to the index buffer
4306 * 2) Set the index source
4307 * 3) Set the Vertex Buffer as the Stream source
4308 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4311 EnterCriticalSection(&ddraw_cs);
4313 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4314 vb->wineD3DVertexDeclaration);
4315 if(FAILED(hr))
4317 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4318 LeaveCriticalSection(&ddraw_cs);
4319 return hr;
4322 /* check that the buffer is large enough to hold the indices,
4323 * reallocate if necessary.
4325 hr = IWineD3DBuffer_GetDesc(This->indexbuffer, &desc);
4326 if(desc.Size < IndexCount * sizeof(WORD))
4328 UINT size = max(desc.Size * 2, IndexCount * sizeof(WORD));
4329 IWineD3DBuffer *buffer;
4330 IUnknown *parent;
4332 TRACE("Growing index buffer to %u bytes\n", size);
4334 IWineD3DBuffer_GetParent(This->indexbuffer, &parent);
4335 hr = IWineD3DDevice_CreateIndexBuffer(This->wineD3DDevice, size,
4336 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, &buffer, parent,
4337 &ddraw_null_wined3d_parent_ops);
4338 if(hr != D3D_OK)
4340 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4341 IParent_Release(parent);
4342 LeaveCriticalSection(&ddraw_cs);
4343 return hr;
4346 IWineD3DBuffer_Release(This->indexbuffer);
4347 This->indexbuffer = buffer;
4349 ((IParentImpl *)parent)->child = (IUnknown *)buffer;
4350 IParent_Release(parent);
4353 /* copy the index stream into the index buffer.
4354 * A new IWineD3DDevice method could be created
4355 * which takes an user pointer containing the indices
4356 * or a SetData-Method for the index buffer, which
4357 * overrides the index buffer data with our pointer.
4359 hr = IWineD3DBuffer_Map(This->indexbuffer,
4360 0 /* OffSetToLock */,
4361 IndexCount * sizeof(WORD),
4362 (BYTE **) &LockedIndices,
4363 0 /* Flags */);
4364 if(hr != D3D_OK)
4366 ERR("(%p) IWineD3DBuffer::Map failed with hr = %08x\n", This, hr);
4367 LeaveCriticalSection(&ddraw_cs);
4368 return hr;
4370 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4371 hr = IWineD3DBuffer_Unmap(This->indexbuffer);
4372 if(hr != D3D_OK)
4374 ERR("(%p) IWineD3DBuffer::Unmap failed with hr = %08x\n", This, hr);
4375 LeaveCriticalSection(&ddraw_cs);
4376 return hr;
4379 /* Set the index stream */
4380 IWineD3DDevice_SetBaseVertexIndex(This->wineD3DDevice, StartVertex);
4381 hr = IWineD3DDevice_SetIndexBuffer(This->wineD3DDevice, This->indexbuffer,
4382 WINED3DFMT_R16_UINT);
4384 /* Set the vertex stream source */
4385 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4386 0 /* StreamNumber */,
4387 vb->wineD3DVertexBuffer,
4388 0 /* offset, we pass this to DrawIndexedPrimitive */,
4389 stride);
4390 if(hr != D3D_OK)
4392 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4393 LeaveCriticalSection(&ddraw_cs);
4394 return hr;
4398 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4399 hr = IWineD3DDevice_DrawIndexedPrimitive(This->wineD3DDevice, 0 /* StartIndex */, IndexCount);
4401 LeaveCriticalSection(&ddraw_cs);
4402 return hr;
4405 static HRESULT WINAPI
4406 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4407 D3DPRIMITIVETYPE PrimitiveType,
4408 IDirect3DVertexBuffer7 *D3DVertexBuf,
4409 DWORD StartVertex,
4410 DWORD NumVertices,
4411 WORD *Indices,
4412 DWORD IndexCount,
4413 DWORD Flags)
4415 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4418 static HRESULT WINAPI
4419 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4420 D3DPRIMITIVETYPE PrimitiveType,
4421 IDirect3DVertexBuffer7 *D3DVertexBuf,
4422 DWORD StartVertex,
4423 DWORD NumVertices,
4424 WORD *Indices,
4425 DWORD IndexCount,
4426 DWORD Flags)
4428 HRESULT hr;
4429 WORD old_fpucw;
4431 old_fpucw = d3d_fpu_setup();
4432 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4433 set_fpu_control_word(old_fpucw);
4435 return hr;
4438 static HRESULT WINAPI
4439 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4440 D3DPRIMITIVETYPE PrimitiveType,
4441 IDirect3DVertexBuffer *D3DVertexBuf,
4442 WORD *Indices,
4443 DWORD IndexCount,
4444 DWORD Flags)
4446 IDirect3DDeviceImpl *This = device_from_device3(iface);
4447 IDirect3DVertexBufferImpl *VB = vb_from_vb1(D3DVertexBuf);
4448 TRACE_(ddraw_thunk)("(%p)->(%08x,%p,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VB, Indices, IndexCount, Flags);
4450 return IDirect3DDevice7_DrawIndexedPrimitiveVB((IDirect3DDevice7 *)This, PrimitiveType,
4451 (IDirect3DVertexBuffer7 *)VB, 0, IndexCount, Indices, IndexCount, Flags);
4454 /*****************************************************************************
4455 * IDirect3DDevice7::ComputeSphereVisibility
4457 * Calculates the visibility of spheres in the current viewport. The spheres
4458 * are passed in the Centers and Radii arrays, the results are passed back
4459 * in the ReturnValues array. Return values are either completely visible,
4460 * partially visible or completely invisible.
4461 * The return value consist of a combination of D3DCLIP_* flags, or it's
4462 * 0 if the sphere is completely visible(according to the SDK, not checked)
4464 * Version 3 and 7
4466 * Params:
4467 * Centers: Array containing the sphere centers
4468 * Radii: Array containing the sphere radii
4469 * NumSpheres: The number of centers and radii in the arrays
4470 * Flags: Some flags
4471 * ReturnValues: Array to write the results to
4473 * Returns:
4474 * D3D_OK
4475 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4476 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4477 * is singular)
4479 *****************************************************************************/
4481 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4483 float distance, norm;
4485 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4486 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4488 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4489 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4490 return 0;
4493 static HRESULT WINAPI
4494 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4495 D3DVECTOR *Centers,
4496 D3DVALUE *Radii,
4497 DWORD NumSpheres,
4498 DWORD Flags,
4499 DWORD *ReturnValues)
4501 D3DMATRIX m, temp;
4502 D3DVALUE origin_plane[6];
4503 D3DVECTOR vec[6];
4504 HRESULT hr;
4505 UINT i, j;
4507 TRACE("(%p)->(%p,%p,%08x,%08x,%p)\n", iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4509 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4510 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4511 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4512 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4513 multiply_matrix_D3D_way(&m, &m, &temp);
4515 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4516 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4517 multiply_matrix_D3D_way(&m, &m, &temp);
4519 /* Left plane */
4520 vec[0].u1.x = m._14 + m._11;
4521 vec[0].u2.y = m._24 + m._21;
4522 vec[0].u3.z = m._34 + m._31;
4523 origin_plane[0] = m._44 + m._41;
4525 /* Right plane */
4526 vec[1].u1.x = m._14 - m._11;
4527 vec[1].u2.y = m._24 - m._21;
4528 vec[1].u3.z = m._34 - m._31;
4529 origin_plane[1] = m._44 - m._41;
4531 /* Top plane */
4532 vec[2].u1.x = m._14 - m._12;
4533 vec[2].u2.y = m._24 - m._22;
4534 vec[2].u3.z = m._34 - m._32;
4535 origin_plane[2] = m._44 - m._42;
4537 /* Bottom plane */
4538 vec[3].u1.x = m._14 + m._12;
4539 vec[3].u2.y = m._24 + m._22;
4540 vec[3].u3.z = m._34 + m._32;
4541 origin_plane[3] = m._44 + m._42;
4543 /* Front plane */
4544 vec[4].u1.x = m._13;
4545 vec[4].u2.y = m._23;
4546 vec[4].u3.z = m._33;
4547 origin_plane[4] = m._43;
4549 /* Back plane*/
4550 vec[5].u1.x = m._14 - m._13;
4551 vec[5].u2.y = m._24 - m._23;
4552 vec[5].u3.z = m._34 - m._33;
4553 origin_plane[5] = m._44 - m._43;
4555 for(i=0; i<NumSpheres; i++)
4557 ReturnValues[i] = 0;
4558 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4561 return D3D_OK;
4564 static HRESULT WINAPI
4565 Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4566 D3DVECTOR *Centers,
4567 D3DVALUE *Radii,
4568 DWORD NumSpheres,
4569 DWORD Flags,
4570 DWORD *ReturnValues)
4572 IDirect3DDeviceImpl *This = device_from_device3(iface);
4573 TRACE_(ddraw_thunk)("(%p)->(%p,%p,%08x,%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, Centers, Radii, NumSpheres, Flags, ReturnValues);
4574 return IDirect3DDevice7_ComputeSphereVisibility((IDirect3DDevice7 *)This,
4575 Centers, Radii, NumSpheres, Flags, ReturnValues);
4578 /*****************************************************************************
4579 * IDirect3DDevice7::GetTexture
4581 * Returns the texture interface handle assigned to a texture stage.
4582 * The returned texture is AddRefed. This is taken from old ddraw,
4583 * not checked in Windows.
4585 * Version 3 and 7
4587 * Params:
4588 * Stage: Texture stage to read the texture from
4589 * Texture: Address to store the interface pointer at
4591 * Returns:
4592 * D3D_OK on success
4593 * DDERR_INVALIDPARAMS if Texture is NULL
4594 * For details, see IWineD3DDevice::GetTexture
4596 *****************************************************************************/
4597 static HRESULT
4598 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4599 DWORD Stage,
4600 IDirectDrawSurface7 **Texture)
4602 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4603 IWineD3DBaseTexture *Surf;
4604 HRESULT hr;
4605 TRACE("(%p)->(%d,%p): Relay\n", This, Stage, Texture);
4607 if(!Texture)
4609 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4610 return DDERR_INVALIDPARAMS;
4613 EnterCriticalSection(&ddraw_cs);
4614 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, Stage, &Surf);
4615 if( (hr != D3D_OK) || (!Surf) )
4617 *Texture = NULL;
4618 LeaveCriticalSection(&ddraw_cs);
4619 return hr;
4622 /* GetParent AddRef()s, which is perfectly OK.
4623 * We have passed the IDirectDrawSurface7 interface to WineD3D, so that's OK too.
4625 hr = IWineD3DBaseTexture_GetParent(Surf,
4626 (IUnknown **) Texture);
4627 LeaveCriticalSection(&ddraw_cs);
4628 return hr;
4631 static HRESULT WINAPI
4632 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4633 DWORD Stage,
4634 IDirectDrawSurface7 **Texture)
4636 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4639 static HRESULT WINAPI
4640 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4641 DWORD Stage,
4642 IDirectDrawSurface7 **Texture)
4644 HRESULT hr;
4645 WORD old_fpucw;
4647 old_fpucw = d3d_fpu_setup();
4648 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4649 set_fpu_control_word(old_fpucw);
4651 return hr;
4654 static HRESULT WINAPI
4655 Thunk_IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface,
4656 DWORD Stage,
4657 IDirect3DTexture2 **Texture2)
4659 IDirect3DDeviceImpl *This = device_from_device3(iface);
4660 HRESULT ret;
4661 IDirectDrawSurface7 *ret_val;
4663 TRACE_(ddraw_thunk)("(%p)->(%d,%p) thunking to IDirect3DDevice7 interface.\n", This, Stage, Texture2);
4664 ret = IDirect3DDevice7_GetTexture((IDirect3DDevice7 *)This, Stage, &ret_val);
4666 *Texture2 = ret_val ? (IDirect3DTexture2 *)&((IDirectDrawSurfaceImpl *)ret_val)->IDirect3DTexture2_vtbl : NULL;
4668 TRACE_(ddraw_thunk)(" returning interface %p.\n", *Texture2);
4670 return ret;
4673 /*****************************************************************************
4674 * IDirect3DDevice7::SetTexture
4676 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4678 * Version 3 and 7
4680 * Params:
4681 * Stage: The stage to assign the texture to
4682 * Texture: Interface pointer to the texture surface
4684 * Returns
4685 * D3D_OK on success
4686 * For details, see IWineD3DDevice::SetTexture
4688 *****************************************************************************/
4689 static HRESULT
4690 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4691 DWORD Stage,
4692 IDirectDrawSurface7 *Texture)
4694 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4695 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
4696 HRESULT hr;
4697 TRACE("(%p)->(%08x,%p): Relay!\n", This, Stage, surf);
4699 /* Texture may be NULL here */
4700 EnterCriticalSection(&ddraw_cs);
4701 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
4702 Stage,
4703 surf ? surf->wineD3DTexture : NULL);
4704 LeaveCriticalSection(&ddraw_cs);
4705 return hr;
4708 static HRESULT WINAPI
4709 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4710 DWORD Stage,
4711 IDirectDrawSurface7 *Texture)
4713 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4716 static HRESULT WINAPI
4717 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4718 DWORD Stage,
4719 IDirectDrawSurface7 *Texture)
4721 HRESULT hr;
4722 WORD old_fpucw;
4724 old_fpucw = d3d_fpu_setup();
4725 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4726 set_fpu_control_word(old_fpucw);
4728 return hr;
4731 static HRESULT WINAPI
4732 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4733 DWORD Stage,
4734 IDirect3DTexture2 *Texture2)
4736 IDirect3DDeviceImpl *This = device_from_device3(iface);
4737 IDirectDrawSurfaceImpl *tex = Texture2 ? surface_from_texture2(Texture2) : NULL;
4738 DWORD texmapblend;
4739 HRESULT hr;
4740 TRACE("(%p)->(%d,%p)\n", This, Stage, tex);
4742 EnterCriticalSection(&ddraw_cs);
4744 if (This->legacyTextureBlending)
4745 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4747 hr = IDirect3DDevice7_SetTexture((IDirect3DDevice7 *)This, Stage, (IDirectDrawSurface7 *)tex);
4749 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4751 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4752 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4753 BOOL tex_alpha = FALSE;
4754 IWineD3DBaseTexture *tex = NULL;
4755 WINED3DSURFACE_DESC desc;
4756 DDPIXELFORMAT ddfmt;
4757 HRESULT result;
4759 result = IWineD3DDevice_GetTexture(This->wineD3DDevice,
4761 &tex);
4763 if(result == WINED3D_OK && tex)
4765 memset(&desc, 0, sizeof(desc));
4766 result = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
4767 if (SUCCEEDED(result))
4769 ddfmt.dwSize = sizeof(ddfmt);
4770 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4771 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4774 IWineD3DBaseTexture_Release(tex);
4777 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4778 if (tex_alpha)
4779 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4780 else
4781 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4784 LeaveCriticalSection(&ddraw_cs);
4786 return hr;
4789 static const struct tss_lookup
4791 BOOL sampler_state;
4792 DWORD state;
4794 tss_lookup[] =
4796 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
4797 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
4798 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
4799 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
4800 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
4801 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
4802 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
4803 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4804 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4805 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4806 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4807 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4808 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
4809 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
4810 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
4811 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
4812 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
4813 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
4814 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
4815 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4816 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4817 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4818 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4819 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4820 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4823 /*****************************************************************************
4824 * IDirect3DDevice7::GetTextureStageState
4826 * Retrieves a state from a texture stage.
4828 * Version 3 and 7
4830 * Params:
4831 * Stage: The stage to retrieve the state from
4832 * TexStageStateType: The state type to retrieve
4833 * State: Address to store the state's value at
4835 * Returns:
4836 * D3D_OK on success
4837 * DDERR_INVALIDPARAMS if State is NULL
4838 * For details, see IWineD3DDevice::GetTextureStageState
4840 *****************************************************************************/
4841 static HRESULT
4842 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4843 DWORD Stage,
4844 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4845 DWORD *State)
4847 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4848 HRESULT hr;
4849 const struct tss_lookup *l = &tss_lookup[TexStageStateType];
4850 TRACE("(%p)->(%08x,%08x,%p): Relay!\n", This, Stage, TexStageStateType, State);
4852 if(!State)
4853 return DDERR_INVALIDPARAMS;
4855 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4857 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4858 *State = 0;
4859 return DD_OK;
4862 EnterCriticalSection(&ddraw_cs);
4864 if (l->sampler_state)
4866 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice, Stage, l->state, State);
4868 switch(TexStageStateType)
4870 /* Mipfilter is a sampler state with different values */
4871 case D3DTSS_MIPFILTER:
4873 switch(*State)
4875 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4876 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4877 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4878 default:
4879 ERR("Unexpected mipfilter value %#x\n", *State);
4880 *State = D3DTFP_NONE;
4881 break;
4883 break;
4886 /* Magfilter has slightly different values */
4887 case D3DTSS_MAGFILTER:
4889 switch(*State)
4891 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4892 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4893 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4894 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4895 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4896 default:
4897 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4898 *State = D3DTFG_POINT;
4899 break;
4901 break;
4904 default:
4905 break;
4908 else
4910 hr = IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
4913 LeaveCriticalSection(&ddraw_cs);
4914 return hr;
4917 static HRESULT WINAPI
4918 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4919 DWORD Stage,
4920 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4921 DWORD *State)
4923 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4926 static HRESULT WINAPI
4927 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4928 DWORD Stage,
4929 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4930 DWORD *State)
4932 HRESULT hr;
4933 WORD old_fpucw;
4935 old_fpucw = d3d_fpu_setup();
4936 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4937 set_fpu_control_word(old_fpucw);
4939 return hr;
4942 static HRESULT WINAPI
4943 Thunk_IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4944 DWORD Stage,
4945 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4946 DWORD *State)
4948 IDirect3DDeviceImpl *This = device_from_device3(iface);
4949 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, Stage, TexStageStateType, State);
4950 return IDirect3DDevice7_GetTextureStageState((IDirect3DDevice7 *)This, Stage, TexStageStateType, State);
4953 /*****************************************************************************
4954 * IDirect3DDevice7::SetTextureStageState
4956 * Sets a texture stage state. Some stage types need to be handled specially,
4957 * because they do not exist in WineD3D and were moved to another place
4959 * Version 3 and 7
4961 * Params:
4962 * Stage: The stage to modify
4963 * TexStageStateType: The state to change
4964 * State: The new value for the state
4966 * Returns:
4967 * D3D_OK on success
4968 * For details, see IWineD3DDevice::SetTextureStageState
4970 *****************************************************************************/
4971 static HRESULT
4972 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4973 DWORD Stage,
4974 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4975 DWORD State)
4977 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4978 const struct tss_lookup *l = &tss_lookup[TexStageStateType];
4979 HRESULT hr;
4980 TRACE("(%p)->(%08x,%08x,%08x): Relay!\n", This, Stage, TexStageStateType, State);
4982 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4984 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4985 return DD_OK;
4988 EnterCriticalSection(&ddraw_cs);
4990 if (l->sampler_state)
4992 switch(TexStageStateType)
4994 /* Mipfilter is a sampler state with different values */
4995 case D3DTSS_MIPFILTER:
4997 switch(State)
4999 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
5000 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
5001 case 0: /* Unchecked */
5002 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
5003 default:
5004 ERR("Unexpected mipfilter value %d\n", State);
5005 State = WINED3DTEXF_NONE;
5006 break;
5008 break;
5011 /* Magfilter has slightly different values */
5012 case D3DTSS_MAGFILTER:
5014 switch(State)
5016 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
5017 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
5018 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
5019 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
5020 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
5021 default:
5022 ERR("Unexpected d3d7 mag filter type %d\n", State);
5023 State = WINED3DTEXF_POINT;
5024 break;
5026 break;
5029 case D3DTSS_ADDRESS:
5030 IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, WINED3DSAMP_ADDRESSV, State);
5031 break;
5033 default:
5034 break;
5037 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, l->state, State);
5039 else
5041 hr = IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
5044 LeaveCriticalSection(&ddraw_cs);
5045 return hr;
5048 static HRESULT WINAPI
5049 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5050 DWORD Stage,
5051 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5052 DWORD State)
5054 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5057 static HRESULT WINAPI
5058 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5059 DWORD Stage,
5060 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5061 DWORD State)
5063 HRESULT hr;
5064 WORD old_fpucw;
5066 old_fpucw = d3d_fpu_setup();
5067 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5068 set_fpu_control_word(old_fpucw);
5070 return hr;
5073 static HRESULT WINAPI
5074 Thunk_IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
5075 DWORD Stage,
5076 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5077 DWORD State)
5079 IDirect3DDeviceImpl *This = device_from_device3(iface);
5080 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, Stage, TexStageStateType, State);
5081 return IDirect3DDevice7_SetTextureStageState((IDirect3DDevice7 *)This, Stage, TexStageStateType, State);
5084 /*****************************************************************************
5085 * IDirect3DDevice7::ValidateDevice
5087 * SDK: "Reports the device's ability to render the currently set
5088 * texture-blending operations in a single pass". Whatever that means
5089 * exactly...
5091 * Version 3 and 7
5093 * Params:
5094 * NumPasses: Address to write the number of necessary passes for the
5095 * desired effect to.
5097 * Returns:
5098 * D3D_OK on success
5099 * See IWineD3DDevice::ValidateDevice for more details
5101 *****************************************************************************/
5102 static HRESULT
5103 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
5104 DWORD *NumPasses)
5106 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5107 HRESULT hr;
5108 TRACE("(%p)->(%p): Relay\n", This, NumPasses);
5110 EnterCriticalSection(&ddraw_cs);
5111 hr = IWineD3DDevice_ValidateDevice(This->wineD3DDevice, NumPasses);
5112 LeaveCriticalSection(&ddraw_cs);
5113 return hr;
5116 static HRESULT WINAPI
5117 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
5118 DWORD *NumPasses)
5120 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5123 static HRESULT WINAPI
5124 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
5125 DWORD *NumPasses)
5127 HRESULT hr;
5128 WORD old_fpucw;
5130 old_fpucw = d3d_fpu_setup();
5131 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5132 set_fpu_control_word(old_fpucw);
5134 return hr;
5137 static HRESULT WINAPI
5138 Thunk_IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface,
5139 DWORD *Passes)
5141 IDirect3DDeviceImpl *This = device_from_device3(iface);
5142 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Passes);
5143 return IDirect3DDevice7_ValidateDevice((IDirect3DDevice7 *)This, Passes);
5146 /*****************************************************************************
5147 * IDirect3DDevice7::Clear
5149 * Fills the render target, the z buffer and the stencil buffer with a
5150 * clear color / value
5152 * Version 7 only
5154 * Params:
5155 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5156 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5157 * Flags: Some flags, as usual
5158 * Color: Clear color for the render target
5159 * Z: Clear value for the Z buffer
5160 * Stencil: Clear value to store in each stencil buffer entry
5162 * Returns:
5163 * D3D_OK on success
5164 * For details, see IWineD3DDevice::Clear
5166 *****************************************************************************/
5167 static HRESULT
5168 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
5169 DWORD Count,
5170 D3DRECT *Rects,
5171 DWORD Flags,
5172 D3DCOLOR Color,
5173 D3DVALUE Z,
5174 DWORD Stencil)
5176 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5177 HRESULT hr;
5178 TRACE("(%p)->(%08x,%p,%08x,%08x,%f,%08x): Relay\n", This, Count, Rects, Flags, Color, Z, Stencil);
5180 /* Note; D3DRECT is compatible with WINED3DRECT */
5181 EnterCriticalSection(&ddraw_cs);
5182 hr = IWineD3DDevice_Clear(This->wineD3DDevice, Count, (WINED3DRECT*) Rects, Flags, Color, Z, Stencil);
5183 LeaveCriticalSection(&ddraw_cs);
5184 return hr;
5187 static HRESULT WINAPI
5188 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5189 DWORD Count,
5190 D3DRECT *Rects,
5191 DWORD Flags,
5192 D3DCOLOR Color,
5193 D3DVALUE Z,
5194 DWORD Stencil)
5196 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5199 static HRESULT WINAPI
5200 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5201 DWORD Count,
5202 D3DRECT *Rects,
5203 DWORD Flags,
5204 D3DCOLOR Color,
5205 D3DVALUE Z,
5206 DWORD Stencil)
5208 HRESULT hr;
5209 WORD old_fpucw;
5211 old_fpucw = d3d_fpu_setup();
5212 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5213 set_fpu_control_word(old_fpucw);
5215 return hr;
5218 /*****************************************************************************
5219 * IDirect3DDevice7::SetViewport
5221 * Sets the current viewport.
5223 * Version 7 only, but IDirect3DViewport uses this call for older
5224 * versions
5226 * Params:
5227 * Data: The new viewport to set
5229 * Returns:
5230 * D3D_OK on success
5231 * DDERR_INVALIDPARAMS if Data is NULL
5232 * For more details, see IWineDDDevice::SetViewport
5234 *****************************************************************************/
5235 static HRESULT
5236 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5237 D3DVIEWPORT7 *Data)
5239 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5240 HRESULT hr;
5241 TRACE("(%p)->(%p) Relay!\n", This, Data);
5243 if(!Data)
5244 return DDERR_INVALIDPARAMS;
5246 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5247 EnterCriticalSection(&ddraw_cs);
5248 hr = IWineD3DDevice_SetViewport(This->wineD3DDevice,
5249 (WINED3DVIEWPORT*) Data);
5250 LeaveCriticalSection(&ddraw_cs);
5251 return hr;
5254 static HRESULT WINAPI
5255 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5256 D3DVIEWPORT7 *Data)
5258 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5261 static HRESULT WINAPI
5262 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5263 D3DVIEWPORT7 *Data)
5265 HRESULT hr;
5266 WORD old_fpucw;
5268 old_fpucw = d3d_fpu_setup();
5269 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5270 set_fpu_control_word(old_fpucw);
5272 return hr;
5275 /*****************************************************************************
5276 * IDirect3DDevice::GetViewport
5278 * Returns the current viewport
5280 * Version 7
5282 * Params:
5283 * Data: D3D7Viewport structure to write the viewport information to
5285 * Returns:
5286 * D3D_OK on success
5287 * DDERR_INVALIDPARAMS if Data is NULL
5288 * For more details, see IWineD3DDevice::GetViewport
5290 *****************************************************************************/
5291 static HRESULT
5292 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5293 D3DVIEWPORT7 *Data)
5295 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5296 HRESULT hr;
5297 TRACE("(%p)->(%p) Relay!\n", This, Data);
5299 if(!Data)
5300 return DDERR_INVALIDPARAMS;
5302 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5303 EnterCriticalSection(&ddraw_cs);
5304 hr = IWineD3DDevice_GetViewport(This->wineD3DDevice,
5305 (WINED3DVIEWPORT*) Data);
5307 LeaveCriticalSection(&ddraw_cs);
5308 return hr_ddraw_from_wined3d(hr);
5311 static HRESULT WINAPI
5312 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5313 D3DVIEWPORT7 *Data)
5315 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5318 static HRESULT WINAPI
5319 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5320 D3DVIEWPORT7 *Data)
5322 HRESULT hr;
5323 WORD old_fpucw;
5325 old_fpucw = d3d_fpu_setup();
5326 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5327 set_fpu_control_word(old_fpucw);
5329 return hr;
5332 /*****************************************************************************
5333 * IDirect3DDevice7::SetMaterial
5335 * Sets the Material
5337 * Version 7
5339 * Params:
5340 * Mat: The material to set
5342 * Returns:
5343 * D3D_OK on success
5344 * DDERR_INVALIDPARAMS if Mat is NULL.
5345 * For more details, see IWineD3DDevice::SetMaterial
5347 *****************************************************************************/
5348 static HRESULT
5349 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5350 D3DMATERIAL7 *Mat)
5352 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5353 HRESULT hr;
5354 TRACE("(%p)->(%p): Relay!\n", This, Mat);
5356 if (!Mat) return DDERR_INVALIDPARAMS;
5357 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5358 EnterCriticalSection(&ddraw_cs);
5359 hr = IWineD3DDevice_SetMaterial(This->wineD3DDevice,
5360 (WINED3DMATERIAL*) Mat);
5361 LeaveCriticalSection(&ddraw_cs);
5362 return hr_ddraw_from_wined3d(hr);
5365 static HRESULT WINAPI
5366 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5367 D3DMATERIAL7 *Mat)
5369 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5372 static HRESULT WINAPI
5373 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5374 D3DMATERIAL7 *Mat)
5376 HRESULT hr;
5377 WORD old_fpucw;
5379 old_fpucw = d3d_fpu_setup();
5380 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5381 set_fpu_control_word(old_fpucw);
5383 return hr;
5386 /*****************************************************************************
5387 * IDirect3DDevice7::GetMaterial
5389 * Returns the current material
5391 * Version 7
5393 * Params:
5394 * Mat: D3DMATERIAL7 structure to write the material parameters to
5396 * Returns:
5397 * D3D_OK on success
5398 * DDERR_INVALIDPARAMS if Mat is NULL
5399 * For more details, see IWineD3DDevice::GetMaterial
5401 *****************************************************************************/
5402 static HRESULT
5403 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5404 D3DMATERIAL7 *Mat)
5406 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5407 HRESULT hr;
5408 TRACE("(%p)->(%p): Relay!\n", This, Mat);
5410 EnterCriticalSection(&ddraw_cs);
5411 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5412 hr = IWineD3DDevice_GetMaterial(This->wineD3DDevice,
5413 (WINED3DMATERIAL*) Mat);
5414 LeaveCriticalSection(&ddraw_cs);
5415 return hr_ddraw_from_wined3d(hr);
5418 static HRESULT WINAPI
5419 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5420 D3DMATERIAL7 *Mat)
5422 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5425 static HRESULT WINAPI
5426 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5427 D3DMATERIAL7 *Mat)
5429 HRESULT hr;
5430 WORD old_fpucw;
5432 old_fpucw = d3d_fpu_setup();
5433 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5434 set_fpu_control_word(old_fpucw);
5436 return hr;
5439 /*****************************************************************************
5440 * IDirect3DDevice7::SetLight
5442 * Assigns a light to a light index, but doesn't activate it yet.
5444 * Version 7, IDirect3DLight uses this method for older versions
5446 * Params:
5447 * LightIndex: The index of the new light
5448 * Light: A D3DLIGHT7 structure describing the light
5450 * Returns:
5451 * D3D_OK on success
5452 * For more details, see IWineD3DDevice::SetLight
5454 *****************************************************************************/
5455 static HRESULT
5456 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5457 DWORD LightIndex,
5458 D3DLIGHT7 *Light)
5460 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5461 HRESULT hr;
5462 TRACE("(%p)->(%08x,%p): Relay!\n", This, LightIndex, Light);
5464 EnterCriticalSection(&ddraw_cs);
5465 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5466 hr = IWineD3DDevice_SetLight(This->wineD3DDevice,
5467 LightIndex,
5468 (WINED3DLIGHT*) Light);
5469 LeaveCriticalSection(&ddraw_cs);
5470 return hr_ddraw_from_wined3d(hr);
5473 static HRESULT WINAPI
5474 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5475 DWORD LightIndex,
5476 D3DLIGHT7 *Light)
5478 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5481 static HRESULT WINAPI
5482 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5483 DWORD LightIndex,
5484 D3DLIGHT7 *Light)
5486 HRESULT hr;
5487 WORD old_fpucw;
5489 old_fpucw = d3d_fpu_setup();
5490 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5491 set_fpu_control_word(old_fpucw);
5493 return hr;
5496 /*****************************************************************************
5497 * IDirect3DDevice7::GetLight
5499 * Returns the light assigned to a light index
5501 * Params:
5502 * Light: Structure to write the light information to
5504 * Returns:
5505 * D3D_OK on success
5506 * DDERR_INVALIDPARAMS if Light is NULL
5507 * For details, see IWineD3DDevice::GetLight
5509 *****************************************************************************/
5510 static HRESULT
5511 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5512 DWORD LightIndex,
5513 D3DLIGHT7 *Light)
5515 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5516 HRESULT rc;
5517 TRACE("(%p)->(%08x,%p): Relay!\n", This, LightIndex, Light);
5519 EnterCriticalSection(&ddraw_cs);
5520 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5521 rc = IWineD3DDevice_GetLight(This->wineD3DDevice,
5522 LightIndex,
5523 (WINED3DLIGHT*) Light);
5525 /* Translate the result. WineD3D returns other values than D3D7 */
5526 LeaveCriticalSection(&ddraw_cs);
5527 return hr_ddraw_from_wined3d(rc);
5530 static HRESULT WINAPI
5531 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5532 DWORD LightIndex,
5533 D3DLIGHT7 *Light)
5535 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5538 static HRESULT WINAPI
5539 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5540 DWORD LightIndex,
5541 D3DLIGHT7 *Light)
5543 HRESULT hr;
5544 WORD old_fpucw;
5546 old_fpucw = d3d_fpu_setup();
5547 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5548 set_fpu_control_word(old_fpucw);
5550 return hr;
5553 /*****************************************************************************
5554 * IDirect3DDevice7::BeginStateBlock
5556 * Begins recording to a stateblock
5558 * Version 7
5560 * Returns:
5561 * D3D_OK on success
5562 * For details see IWineD3DDevice::BeginStateBlock
5564 *****************************************************************************/
5565 static HRESULT
5566 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5568 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5569 HRESULT hr;
5570 TRACE("(%p)->(): Relay!\n", This);
5572 EnterCriticalSection(&ddraw_cs);
5573 hr = IWineD3DDevice_BeginStateBlock(This->wineD3DDevice);
5574 LeaveCriticalSection(&ddraw_cs);
5575 return hr_ddraw_from_wined3d(hr);
5578 static HRESULT WINAPI
5579 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5581 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5584 static HRESULT WINAPI
5585 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5587 HRESULT hr;
5588 WORD old_fpucw;
5590 old_fpucw = d3d_fpu_setup();
5591 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5592 set_fpu_control_word(old_fpucw);
5594 return hr;
5597 /*****************************************************************************
5598 * IDirect3DDevice7::EndStateBlock
5600 * Stops recording to a state block and returns the created stateblock
5601 * handle.
5603 * Version 7
5605 * Params:
5606 * BlockHandle: Address to store the stateblock's handle to
5608 * Returns:
5609 * D3D_OK on success
5610 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5611 * See IWineD3DDevice::EndStateBlock for more details
5613 *****************************************************************************/
5614 static HRESULT
5615 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5616 DWORD *BlockHandle)
5618 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5619 HRESULT hr;
5620 TRACE("(%p)->(%p): Relay!\n", This, BlockHandle);
5622 if(!BlockHandle)
5624 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5625 return DDERR_INVALIDPARAMS;
5628 EnterCriticalSection(&ddraw_cs);
5629 *BlockHandle = IDirect3DDeviceImpl_CreateHandle(This);
5630 if(!*BlockHandle)
5632 ERR("Cannot get a handle number for the stateblock\n");
5633 LeaveCriticalSection(&ddraw_cs);
5634 return DDERR_OUTOFMEMORY;
5636 This->Handles[*BlockHandle - 1].type = DDrawHandle_StateBlock;
5637 hr = IWineD3DDevice_EndStateBlock(This->wineD3DDevice,
5638 (IWineD3DStateBlock **) &This->Handles[*BlockHandle - 1].ptr);
5639 LeaveCriticalSection(&ddraw_cs);
5640 return hr_ddraw_from_wined3d(hr);
5643 static HRESULT WINAPI
5644 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5645 DWORD *BlockHandle)
5647 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5650 static HRESULT WINAPI
5651 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5652 DWORD *BlockHandle)
5654 HRESULT hr;
5655 WORD old_fpucw;
5657 old_fpucw = d3d_fpu_setup();
5658 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5659 set_fpu_control_word(old_fpucw);
5661 return hr;
5664 /*****************************************************************************
5665 * IDirect3DDevice7::PreLoad
5667 * Allows the app to signal that a texture will be used soon, to allow
5668 * the Direct3DDevice to load it to the video card in the meantime.
5670 * Version 7
5672 * Params:
5673 * Texture: The texture to preload
5675 * Returns:
5676 * D3D_OK on success
5677 * DDERR_INVALIDPARAMS if Texture is NULL
5678 * See IWineD3DSurface::PreLoad for details
5680 *****************************************************************************/
5681 static HRESULT
5682 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5683 IDirectDrawSurface7 *Texture)
5685 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5686 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
5688 TRACE("(%p)->(%p): Relay!\n", This, surf);
5690 if(!Texture)
5691 return DDERR_INVALIDPARAMS;
5693 EnterCriticalSection(&ddraw_cs);
5694 IWineD3DSurface_PreLoad(surf->WineD3DSurface);
5695 LeaveCriticalSection(&ddraw_cs);
5696 return D3D_OK;
5699 static HRESULT WINAPI
5700 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5701 IDirectDrawSurface7 *Texture)
5703 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5706 static HRESULT WINAPI
5707 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5708 IDirectDrawSurface7 *Texture)
5710 HRESULT hr;
5711 WORD old_fpucw;
5713 old_fpucw = d3d_fpu_setup();
5714 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5715 set_fpu_control_word(old_fpucw);
5717 return hr;
5720 /*****************************************************************************
5721 * IDirect3DDevice7::ApplyStateBlock
5723 * Activates the state stored in a state block handle.
5725 * Params:
5726 * BlockHandle: The stateblock handle to activate
5728 * Returns:
5729 * D3D_OK on success
5730 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5732 *****************************************************************************/
5733 static HRESULT
5734 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5735 DWORD BlockHandle)
5737 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5738 HRESULT hr;
5739 TRACE("(%p)->(%08x): Relay!\n", This, BlockHandle);
5741 EnterCriticalSection(&ddraw_cs);
5742 if(!BlockHandle || BlockHandle > This->numHandles)
5744 WARN("Out of range handle %d, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5745 LeaveCriticalSection(&ddraw_cs);
5746 return D3DERR_INVALIDSTATEBLOCK;
5748 if(This->Handles[BlockHandle - 1].type != DDrawHandle_StateBlock)
5750 WARN("Handle %d is not a stateblock, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5751 LeaveCriticalSection(&ddraw_cs);
5752 return D3DERR_INVALIDSTATEBLOCK;
5755 hr = IWineD3DStateBlock_Apply((IWineD3DStateBlock *) This->Handles[BlockHandle - 1].ptr);
5756 LeaveCriticalSection(&ddraw_cs);
5757 return hr_ddraw_from_wined3d(hr);
5760 static HRESULT WINAPI
5761 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5762 DWORD BlockHandle)
5764 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5767 static HRESULT WINAPI
5768 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5769 DWORD BlockHandle)
5771 HRESULT hr;
5772 WORD old_fpucw;
5774 old_fpucw = d3d_fpu_setup();
5775 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5776 set_fpu_control_word(old_fpucw);
5778 return hr;
5781 /*****************************************************************************
5782 * IDirect3DDevice7::CaptureStateBlock
5784 * Updates a stateblock's values to the values currently set for the device
5786 * Version 7
5788 * Params:
5789 * BlockHandle: Stateblock to update
5791 * Returns:
5792 * D3D_OK on success
5793 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5794 * See IWineD3DDevice::CaptureStateBlock for more details
5796 *****************************************************************************/
5797 static HRESULT
5798 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5799 DWORD BlockHandle)
5801 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5802 HRESULT hr;
5803 TRACE("(%p)->(%08x): Relay!\n", This, BlockHandle);
5805 EnterCriticalSection(&ddraw_cs);
5806 if(BlockHandle == 0 || BlockHandle > This->numHandles)
5808 WARN("Out of range handle %d, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5809 LeaveCriticalSection(&ddraw_cs);
5810 return D3DERR_INVALIDSTATEBLOCK;
5812 if(This->Handles[BlockHandle - 1].type != DDrawHandle_StateBlock)
5814 WARN("Handle %d is not a stateblock, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5815 LeaveCriticalSection(&ddraw_cs);
5816 return D3DERR_INVALIDSTATEBLOCK;
5819 hr = IWineD3DStateBlock_Capture((IWineD3DStateBlock *) This->Handles[BlockHandle - 1].ptr);
5820 LeaveCriticalSection(&ddraw_cs);
5821 return hr_ddraw_from_wined3d(hr);
5824 static HRESULT WINAPI
5825 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5826 DWORD BlockHandle)
5828 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5831 static HRESULT WINAPI
5832 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5833 DWORD BlockHandle)
5835 HRESULT hr;
5836 WORD old_fpucw;
5838 old_fpucw = d3d_fpu_setup();
5839 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5840 set_fpu_control_word(old_fpucw);
5842 return hr;
5845 /*****************************************************************************
5846 * IDirect3DDevice7::DeleteStateBlock
5848 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5850 * Version 7
5852 * Params:
5853 * BlockHandle: Stateblock handle to delete
5855 * Returns:
5856 * D3D_OK on success
5857 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5859 *****************************************************************************/
5860 static HRESULT
5861 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5862 DWORD BlockHandle)
5864 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5865 ULONG ref;
5866 TRACE("(%p)->(%08x): Relay!\n", This, BlockHandle);
5868 EnterCriticalSection(&ddraw_cs);
5869 if(BlockHandle == 0 || BlockHandle > This->numHandles)
5871 WARN("Out of range handle %d, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5872 LeaveCriticalSection(&ddraw_cs);
5873 return D3DERR_INVALIDSTATEBLOCK;
5875 if(This->Handles[BlockHandle - 1].type != DDrawHandle_StateBlock)
5877 WARN("Handle %d is not a stateblock, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5878 LeaveCriticalSection(&ddraw_cs);
5879 return D3DERR_INVALIDSTATEBLOCK;
5882 ref = IWineD3DStateBlock_Release((IWineD3DStateBlock *) This->Handles[BlockHandle - 1].ptr);
5883 if(ref)
5885 ERR("Something is still holding the stateblock %p(Handle %d). Ref = %d\n", This->Handles[BlockHandle - 1].ptr, BlockHandle, ref);
5887 This->Handles[BlockHandle - 1].ptr = NULL;
5888 This->Handles[BlockHandle - 1].type = DDrawHandle_Unknown;
5890 LeaveCriticalSection(&ddraw_cs);
5891 return D3D_OK;
5894 static HRESULT WINAPI
5895 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5896 DWORD BlockHandle)
5898 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5901 static HRESULT WINAPI
5902 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5903 DWORD BlockHandle)
5905 HRESULT hr;
5906 WORD old_fpucw;
5908 old_fpucw = d3d_fpu_setup();
5909 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5910 set_fpu_control_word(old_fpucw);
5912 return hr;
5915 /*****************************************************************************
5916 * IDirect3DDevice7::CreateStateBlock
5918 * Creates a new state block handle.
5920 * Version 7
5922 * Params:
5923 * Type: The state block type
5924 * BlockHandle: Address to write the created handle to
5926 * Returns:
5927 * D3D_OK on success
5928 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5930 *****************************************************************************/
5931 static HRESULT
5932 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5933 D3DSTATEBLOCKTYPE Type,
5934 DWORD *BlockHandle)
5936 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5937 HRESULT hr;
5938 TRACE("(%p)->(%08x,%p)!\n", This, Type, BlockHandle);
5940 if(!BlockHandle)
5942 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5943 return DDERR_INVALIDPARAMS;
5945 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5946 Type != D3DSBT_VERTEXSTATE ) {
5947 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5948 return DDERR_INVALIDPARAMS;
5951 EnterCriticalSection(&ddraw_cs);
5952 *BlockHandle = IDirect3DDeviceImpl_CreateHandle(This);
5953 if(!*BlockHandle)
5955 ERR("Cannot get a handle number for the stateblock\n");
5956 LeaveCriticalSection(&ddraw_cs);
5957 return DDERR_OUTOFMEMORY;
5959 This->Handles[*BlockHandle - 1].type = DDrawHandle_StateBlock;
5961 /* The D3DSTATEBLOCKTYPE enum is fine here */
5962 hr = IWineD3DDevice_CreateStateBlock(This->wineD3DDevice,
5963 Type,
5964 (IWineD3DStateBlock **) &This->Handles[*BlockHandle - 1].ptr,
5965 NULL /* Parent, hope that works */);
5966 LeaveCriticalSection(&ddraw_cs);
5967 return hr_ddraw_from_wined3d(hr);
5970 static HRESULT WINAPI
5971 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5972 D3DSTATEBLOCKTYPE Type,
5973 DWORD *BlockHandle)
5975 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5978 static HRESULT WINAPI
5979 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5980 D3DSTATEBLOCKTYPE Type,
5981 DWORD *BlockHandle)
5983 HRESULT hr;
5984 WORD old_fpucw;
5986 old_fpucw = d3d_fpu_setup();
5987 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5988 set_fpu_control_word(old_fpucw);
5990 return hr;
5993 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5994 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
5995 IDirectDrawSurfaceImpl *src)
5997 IDirectDrawSurfaceImpl *src_level, *dest_level;
5998 IDirectDrawSurface7 *temp;
5999 DDSURFACEDESC2 ddsd;
6000 BOOL levelFound; /* at least one suitable sublevel in dest found */
6002 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
6003 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
6004 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
6006 levelFound = FALSE;
6008 src_level = src;
6009 dest_level = dest;
6011 for (;src_level && dest_level;)
6013 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6014 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6016 levelFound = TRUE;
6018 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6019 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6020 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
6022 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6024 dest_level = (IDirectDrawSurfaceImpl *)temp;
6027 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6028 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6029 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
6031 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6033 src_level = (IDirectDrawSurfaceImpl *)temp;
6036 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6037 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6039 return !dest_level && levelFound;
6042 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6043 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
6044 IDirectDrawSurfaceImpl *dest,
6045 IDirectDrawSurfaceImpl *src,
6046 const POINT *DestPoint,
6047 const RECT *SrcRect)
6049 IDirectDrawSurfaceImpl *src_level, *dest_level;
6050 IDirectDrawSurface7 *temp;
6051 DDSURFACEDESC2 ddsd;
6052 POINT point;
6053 RECT rect;
6054 HRESULT hr;
6055 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
6056 DWORD ckeyflag;
6057 DDCOLORKEY ddckey;
6058 BOOL palette_missing = FALSE;
6060 /* Copy palette, if possible. */
6061 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)src, &pal_src);
6062 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)dest, &pal);
6064 if (pal_src != NULL && pal != NULL)
6066 PALETTEENTRY palent[256];
6068 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
6069 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
6072 if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
6073 DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
6075 palette_missing = TRUE;
6078 if (pal) IDirectDrawPalette_Release(pal);
6079 if (pal_src) IDirectDrawPalette_Release(pal_src);
6081 /* Copy colorkeys, if present. */
6082 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6084 hr = IDirectDrawSurface7_GetColorKey((IDirectDrawSurface7 *)src, ckeyflag, &ddckey);
6086 if (SUCCEEDED(hr))
6088 IDirectDrawSurface7_SetColorKey((IDirectDrawSurface7 *)dest, ckeyflag, &ddckey);
6092 src_level = src;
6093 dest_level = dest;
6095 point = *DestPoint;
6096 rect = *SrcRect;
6098 for (;src_level && dest_level;)
6100 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6101 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6103 /* Try UpdateSurface that may perform a more direct opengl loading. But skip this if destination is paletted texture and has no palette.
6104 * Some games like Sacrifice set palette after Load, and it is a waste of effort to try to load texture without palette and generates
6105 * warnings in wined3d. */
6106 if (!palette_missing)
6107 hr = IWineD3DDevice_UpdateSurface(device->wineD3DDevice, src_level->WineD3DSurface, &rect, dest_level->WineD3DSurface,
6108 &point);
6110 if (palette_missing || FAILED(hr))
6112 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
6113 IWineD3DSurface_BltFast(dest_level->WineD3DSurface,
6114 point.x, point.y,
6115 src_level->WineD3DSurface, &rect, 0);
6118 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6119 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6120 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
6122 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6124 dest_level = (IDirectDrawSurfaceImpl *)temp;
6127 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6128 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6129 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
6131 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6133 src_level = (IDirectDrawSurfaceImpl *)temp;
6135 point.x /= 2;
6136 point.y /= 2;
6138 rect.top /= 2;
6139 rect.left /= 2;
6140 rect.right = (rect.right + 1) / 2;
6141 rect.bottom = (rect.bottom + 1) / 2;
6144 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6145 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6148 /*****************************************************************************
6149 * IDirect3DDevice7::Load
6151 * Loads a rectangular area from the source into the destination texture.
6152 * It can also copy the source to the faces of a cubic environment map
6154 * Version 7
6156 * Params:
6157 * DestTex: Destination texture
6158 * DestPoint: Point in the destination where the source image should be
6159 * written to
6160 * SrcTex: Source texture
6161 * SrcRect: Source rectangle
6162 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6163 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6164 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6166 * Returns:
6167 * D3D_OK on success
6168 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6171 *****************************************************************************/
6173 static HRESULT
6174 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6175 IDirectDrawSurface7 *DestTex,
6176 POINT *DestPoint,
6177 IDirectDrawSurface7 *SrcTex,
6178 RECT *SrcRect,
6179 DWORD Flags)
6181 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6182 IDirectDrawSurfaceImpl *dest = (IDirectDrawSurfaceImpl *)DestTex;
6183 IDirectDrawSurfaceImpl *src = (IDirectDrawSurfaceImpl *)SrcTex;
6184 POINT destpoint;
6185 RECT srcrect;
6186 TRACE("(%p)->(%p,%p,%p,%p,%08x)\n", This, dest, DestPoint, src, SrcRect, Flags);
6188 if( (!src) || (!dest) )
6189 return DDERR_INVALIDPARAMS;
6191 EnterCriticalSection(&ddraw_cs);
6193 if (SrcRect) srcrect = *SrcRect;
6194 else
6196 srcrect.left = srcrect.top = 0;
6197 srcrect.right = src->surface_desc.dwWidth;
6198 srcrect.bottom = src->surface_desc.dwHeight;
6201 if (DestPoint) destpoint = *DestPoint;
6202 else
6204 destpoint.x = destpoint.y = 0;
6206 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6207 * destination can be a subset of mip levels, in which case actual coordinates used
6208 * for it may be divided. If any dimension of dest is larger than source, it can't be
6209 * mip level subset, so an error can be returned early.
6211 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6212 srcrect.right > src->surface_desc.dwWidth ||
6213 srcrect.bottom > src->surface_desc.dwHeight ||
6214 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6215 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6216 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6217 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6219 LeaveCriticalSection(&ddraw_cs);
6220 return DDERR_INVALIDPARAMS;
6223 /* Must be top level surfaces. */
6224 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6225 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6227 LeaveCriticalSection(&ddraw_cs);
6228 return DDERR_INVALIDPARAMS;
6231 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6233 DWORD src_face_flag, dest_face_flag;
6234 IDirectDrawSurfaceImpl *src_face, *dest_face;
6235 IDirectDrawSurface7 *temp;
6236 DDSURFACEDESC2 ddsd;
6237 int i;
6239 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6241 LeaveCriticalSection(&ddraw_cs);
6242 return DDERR_INVALIDPARAMS;
6245 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6246 * time it's actual surface loading. */
6247 for (i = 0; i < 2; i++)
6249 dest_face = dest;
6250 src_face = src;
6252 for (;dest_face && src_face;)
6254 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6255 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6257 if (src_face_flag == dest_face_flag)
6259 if (i == 0)
6261 /* Destination mip levels must be subset of source mip levels. */
6262 if (!is_mip_level_subset(dest_face, src_face))
6264 LeaveCriticalSection(&ddraw_cs);
6265 return DDERR_INVALIDPARAMS;
6268 else if (Flags & dest_face_flag)
6270 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6273 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6275 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6276 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6277 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src, &ddsd.ddsCaps, &temp);
6279 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6281 src_face = (IDirectDrawSurfaceImpl *)temp;
6283 else
6285 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6287 src_face = NULL;
6291 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6293 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6294 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6295 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest, &ddsd.ddsCaps, &temp);
6297 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6299 dest_face = (IDirectDrawSurfaceImpl *)temp;
6301 else
6303 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6305 dest_face = NULL;
6309 if (i == 0)
6311 /* Native returns error if src faces are not subset of dest faces. */
6312 if (src_face)
6314 LeaveCriticalSection(&ddraw_cs);
6315 return DDERR_INVALIDPARAMS;
6320 LeaveCriticalSection(&ddraw_cs);
6321 return D3D_OK;
6323 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6325 LeaveCriticalSection(&ddraw_cs);
6326 return DDERR_INVALIDPARAMS;
6329 /* Handle non cube map textures. */
6331 /* Destination mip levels must be subset of source mip levels. */
6332 if (!is_mip_level_subset(dest, src))
6334 LeaveCriticalSection(&ddraw_cs);
6335 return DDERR_INVALIDPARAMS;
6338 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6340 LeaveCriticalSection(&ddraw_cs);
6341 return D3D_OK;
6344 static HRESULT WINAPI
6345 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6346 IDirectDrawSurface7 *DestTex,
6347 POINT *DestPoint,
6348 IDirectDrawSurface7 *SrcTex,
6349 RECT *SrcRect,
6350 DWORD Flags)
6352 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6355 static HRESULT WINAPI
6356 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6357 IDirectDrawSurface7 *DestTex,
6358 POINT *DestPoint,
6359 IDirectDrawSurface7 *SrcTex,
6360 RECT *SrcRect,
6361 DWORD Flags)
6363 HRESULT hr;
6364 WORD old_fpucw;
6366 old_fpucw = d3d_fpu_setup();
6367 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6368 set_fpu_control_word(old_fpucw);
6370 return hr;
6373 /*****************************************************************************
6374 * IDirect3DDevice7::LightEnable
6376 * Enables or disables a light
6378 * Version 7, IDirect3DLight uses this method too.
6380 * Params:
6381 * LightIndex: The index of the light to enable / disable
6382 * Enable: Enable or disable the light
6384 * Returns:
6385 * D3D_OK on success
6386 * For more details, see IWineD3DDevice::SetLightEnable
6388 *****************************************************************************/
6389 static HRESULT
6390 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6391 DWORD LightIndex,
6392 BOOL Enable)
6394 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6395 HRESULT hr;
6396 TRACE("(%p)->(%08x,%d): Relay!\n", This, LightIndex, Enable);
6398 EnterCriticalSection(&ddraw_cs);
6399 hr = IWineD3DDevice_SetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6400 LeaveCriticalSection(&ddraw_cs);
6401 return hr_ddraw_from_wined3d(hr);
6404 static HRESULT WINAPI
6405 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6406 DWORD LightIndex,
6407 BOOL Enable)
6409 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6412 static HRESULT WINAPI
6413 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6414 DWORD LightIndex,
6415 BOOL Enable)
6417 HRESULT hr;
6418 WORD old_fpucw;
6420 old_fpucw = d3d_fpu_setup();
6421 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6422 set_fpu_control_word(old_fpucw);
6424 return hr;
6427 /*****************************************************************************
6428 * IDirect3DDevice7::GetLightEnable
6430 * Retrieves if the light with the given index is enabled or not
6432 * Version 7
6434 * Params:
6435 * LightIndex: Index of desired light
6436 * Enable: Pointer to a BOOL which contains the result
6438 * Returns:
6439 * D3D_OK on success
6440 * DDERR_INVALIDPARAMS if Enable is NULL
6441 * See IWineD3DDevice::GetLightEnable for more details
6443 *****************************************************************************/
6444 static HRESULT
6445 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6446 DWORD LightIndex,
6447 BOOL* Enable)
6449 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6450 HRESULT hr;
6451 TRACE("(%p)->(%08x,%p): Relay\n", This, LightIndex, Enable);
6453 if(!Enable)
6454 return DDERR_INVALIDPARAMS;
6456 EnterCriticalSection(&ddraw_cs);
6457 hr = IWineD3DDevice_GetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6458 LeaveCriticalSection(&ddraw_cs);
6459 return hr_ddraw_from_wined3d(hr);
6462 static HRESULT WINAPI
6463 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6464 DWORD LightIndex,
6465 BOOL* Enable)
6467 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6470 static HRESULT WINAPI
6471 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6472 DWORD LightIndex,
6473 BOOL* Enable)
6475 HRESULT hr;
6476 WORD old_fpucw;
6478 old_fpucw = d3d_fpu_setup();
6479 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6480 set_fpu_control_word(old_fpucw);
6482 return hr;
6485 /*****************************************************************************
6486 * IDirect3DDevice7::SetClipPlane
6488 * Sets custom clipping plane
6490 * Version 7
6492 * Params:
6493 * Index: The index of the clipping plane
6494 * PlaneEquation: An equation defining the clipping plane
6496 * Returns:
6497 * D3D_OK on success
6498 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6499 * See IWineD3DDevice::SetClipPlane for more details
6501 *****************************************************************************/
6502 static HRESULT
6503 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6504 DWORD Index,
6505 D3DVALUE* PlaneEquation)
6507 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6508 HRESULT hr;
6509 TRACE("(%p)->(%08x,%p): Relay!\n", This, Index, PlaneEquation);
6511 if(!PlaneEquation)
6512 return DDERR_INVALIDPARAMS;
6514 EnterCriticalSection(&ddraw_cs);
6515 hr = IWineD3DDevice_SetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6516 LeaveCriticalSection(&ddraw_cs);
6517 return hr;
6520 static HRESULT WINAPI
6521 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6522 DWORD Index,
6523 D3DVALUE* PlaneEquation)
6525 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6528 static HRESULT WINAPI
6529 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6530 DWORD Index,
6531 D3DVALUE* PlaneEquation)
6533 HRESULT hr;
6534 WORD old_fpucw;
6536 old_fpucw = d3d_fpu_setup();
6537 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6538 set_fpu_control_word(old_fpucw);
6540 return hr;
6543 /*****************************************************************************
6544 * IDirect3DDevice7::GetClipPlane
6546 * Returns the clipping plane with a specific index
6548 * Params:
6549 * Index: The index of the desired plane
6550 * PlaneEquation: Address to store the plane equation to
6552 * Returns:
6553 * D3D_OK on success
6554 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6555 * See IWineD3DDevice::GetClipPlane for more details
6557 *****************************************************************************/
6558 static HRESULT
6559 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6560 DWORD Index,
6561 D3DVALUE* PlaneEquation)
6563 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6564 HRESULT hr;
6565 TRACE("(%p)->(%d,%p): Relay!\n", This, Index, PlaneEquation);
6567 if(!PlaneEquation)
6568 return DDERR_INVALIDPARAMS;
6570 EnterCriticalSection(&ddraw_cs);
6571 hr = IWineD3DDevice_GetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6572 LeaveCriticalSection(&ddraw_cs);
6573 return hr;
6576 static HRESULT WINAPI
6577 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6578 DWORD Index,
6579 D3DVALUE* PlaneEquation)
6581 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6584 static HRESULT WINAPI
6585 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6586 DWORD Index,
6587 D3DVALUE* PlaneEquation)
6589 HRESULT hr;
6590 WORD old_fpucw;
6592 old_fpucw = d3d_fpu_setup();
6593 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6594 set_fpu_control_word(old_fpucw);
6596 return hr;
6599 /*****************************************************************************
6600 * IDirect3DDevice7::GetInfo
6602 * Retrieves some information about the device. The DirectX sdk says that
6603 * this version returns S_FALSE for all retail builds of DirectX, that's what
6604 * this implementation does.
6606 * Params:
6607 * DevInfoID: Information type requested
6608 * DevInfoStruct: Pointer to a structure to store the info to
6609 * Size: Size of the structure
6611 * Returns:
6612 * S_FALSE, because it's a non-debug driver
6614 *****************************************************************************/
6615 static HRESULT WINAPI
6616 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6617 DWORD DevInfoID,
6618 void *DevInfoStruct,
6619 DWORD Size)
6621 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6622 TRACE("(%p)->(%08x,%p,%08x)\n", This, DevInfoID, DevInfoStruct, Size);
6624 if (TRACE_ON(d3d7))
6626 TRACE(" info requested : ");
6627 switch (DevInfoID)
6629 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6630 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6631 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6632 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6636 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6639 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6640 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6641 * are not duplicated.
6643 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6644 * has already been setup for optimal d3d operation.
6646 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6647 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6648 * by Sacrifice (game). */
6649 const IDirect3DDevice7Vtbl IDirect3DDevice7_FPUSetup_Vtbl =
6651 /*** IUnknown Methods ***/
6652 IDirect3DDeviceImpl_7_QueryInterface,
6653 IDirect3DDeviceImpl_7_AddRef,
6654 IDirect3DDeviceImpl_7_Release,
6655 /*** IDirect3DDevice7 ***/
6656 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6657 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6658 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6659 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6660 IDirect3DDeviceImpl_7_GetDirect3D,
6661 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6662 IDirect3DDeviceImpl_7_GetRenderTarget,
6663 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6664 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6665 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6666 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6667 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6668 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6669 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6670 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6671 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6672 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6673 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6674 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6675 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6676 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6677 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6678 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6679 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6680 IDirect3DDeviceImpl_7_SetClipStatus,
6681 IDirect3DDeviceImpl_7_GetClipStatus,
6682 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6683 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6684 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6685 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6686 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6687 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6688 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6689 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6690 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6691 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6692 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6693 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6694 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6695 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6696 IDirect3DDeviceImpl_7_Load_FPUSetup,
6697 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6698 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6699 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6700 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6701 IDirect3DDeviceImpl_7_GetInfo
6704 const IDirect3DDevice7Vtbl IDirect3DDevice7_FPUPreserve_Vtbl =
6706 /*** IUnknown Methods ***/
6707 IDirect3DDeviceImpl_7_QueryInterface,
6708 IDirect3DDeviceImpl_7_AddRef,
6709 IDirect3DDeviceImpl_7_Release,
6710 /*** IDirect3DDevice7 ***/
6711 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6712 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6713 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6714 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6715 IDirect3DDeviceImpl_7_GetDirect3D,
6716 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6717 IDirect3DDeviceImpl_7_GetRenderTarget,
6718 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6719 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6720 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6721 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6722 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6723 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6724 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6725 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6726 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6727 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6728 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6729 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6730 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6731 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6732 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6733 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6734 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6735 IDirect3DDeviceImpl_7_SetClipStatus,
6736 IDirect3DDeviceImpl_7_GetClipStatus,
6737 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6738 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6739 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6740 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6741 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6742 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6743 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6744 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6745 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6746 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6747 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6748 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6749 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6750 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6751 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6752 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6753 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6754 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6755 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6756 IDirect3DDeviceImpl_7_GetInfo
6759 const IDirect3DDevice3Vtbl IDirect3DDevice3_Vtbl =
6761 /*** IUnknown Methods ***/
6762 Thunk_IDirect3DDeviceImpl_3_QueryInterface,
6763 Thunk_IDirect3DDeviceImpl_3_AddRef,
6764 Thunk_IDirect3DDeviceImpl_3_Release,
6765 /*** IDirect3DDevice3 ***/
6766 IDirect3DDeviceImpl_3_GetCaps,
6767 IDirect3DDeviceImpl_3_GetStats,
6768 IDirect3DDeviceImpl_3_AddViewport,
6769 IDirect3DDeviceImpl_3_DeleteViewport,
6770 IDirect3DDeviceImpl_3_NextViewport,
6771 Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
6772 Thunk_IDirect3DDeviceImpl_3_BeginScene,
6773 Thunk_IDirect3DDeviceImpl_3_EndScene,
6774 Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
6775 IDirect3DDeviceImpl_3_SetCurrentViewport,
6776 IDirect3DDeviceImpl_3_GetCurrentViewport,
6777 Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
6778 Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
6779 IDirect3DDeviceImpl_3_Begin,
6780 IDirect3DDeviceImpl_3_BeginIndexed,
6781 IDirect3DDeviceImpl_3_Vertex,
6782 IDirect3DDeviceImpl_3_Index,
6783 IDirect3DDeviceImpl_3_End,
6784 IDirect3DDeviceImpl_3_GetRenderState,
6785 IDirect3DDeviceImpl_3_SetRenderState,
6786 IDirect3DDeviceImpl_3_GetLightState,
6787 IDirect3DDeviceImpl_3_SetLightState,
6788 Thunk_IDirect3DDeviceImpl_3_SetTransform,
6789 Thunk_IDirect3DDeviceImpl_3_GetTransform,
6790 Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
6791 Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
6792 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6793 Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
6794 Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
6795 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6796 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6797 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6798 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6799 Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6800 Thunk_IDirect3DDeviceImpl_3_GetTexture,
6801 IDirect3DDeviceImpl_3_SetTexture,
6802 Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
6803 Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
6804 Thunk_IDirect3DDeviceImpl_3_ValidateDevice
6807 const IDirect3DDevice2Vtbl IDirect3DDevice2_Vtbl =
6809 /*** IUnknown Methods ***/
6810 Thunk_IDirect3DDeviceImpl_2_QueryInterface,
6811 Thunk_IDirect3DDeviceImpl_2_AddRef,
6812 Thunk_IDirect3DDeviceImpl_2_Release,
6813 /*** IDirect3DDevice2 ***/
6814 Thunk_IDirect3DDeviceImpl_2_GetCaps,
6815 IDirect3DDeviceImpl_2_SwapTextureHandles,
6816 Thunk_IDirect3DDeviceImpl_2_GetStats,
6817 Thunk_IDirect3DDeviceImpl_2_AddViewport,
6818 Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
6819 Thunk_IDirect3DDeviceImpl_2_NextViewport,
6820 IDirect3DDeviceImpl_2_EnumTextureFormats,
6821 Thunk_IDirect3DDeviceImpl_2_BeginScene,
6822 Thunk_IDirect3DDeviceImpl_2_EndScene,
6823 Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
6824 Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
6825 Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
6826 Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
6827 Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
6828 Thunk_IDirect3DDeviceImpl_2_Begin,
6829 Thunk_IDirect3DDeviceImpl_2_BeginIndexed,
6830 Thunk_IDirect3DDeviceImpl_2_Vertex,
6831 Thunk_IDirect3DDeviceImpl_2_Index,
6832 Thunk_IDirect3DDeviceImpl_2_End,
6833 Thunk_IDirect3DDeviceImpl_2_GetRenderState,
6834 Thunk_IDirect3DDeviceImpl_2_SetRenderState,
6835 Thunk_IDirect3DDeviceImpl_2_GetLightState,
6836 Thunk_IDirect3DDeviceImpl_2_SetLightState,
6837 Thunk_IDirect3DDeviceImpl_2_SetTransform,
6838 Thunk_IDirect3DDeviceImpl_2_GetTransform,
6839 Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
6840 Thunk_IDirect3DDeviceImpl_2_DrawPrimitive,
6841 Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6842 Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
6843 Thunk_IDirect3DDeviceImpl_2_GetClipStatus
6846 const IDirect3DDeviceVtbl IDirect3DDevice1_Vtbl =
6848 /*** IUnknown Methods ***/
6849 Thunk_IDirect3DDeviceImpl_1_QueryInterface,
6850 Thunk_IDirect3DDeviceImpl_1_AddRef,
6851 Thunk_IDirect3DDeviceImpl_1_Release,
6852 /*** IDirect3DDevice1 ***/
6853 IDirect3DDeviceImpl_1_Initialize,
6854 Thunk_IDirect3DDeviceImpl_1_GetCaps,
6855 Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
6856 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6857 Thunk_IDirect3DDeviceImpl_1_GetStats,
6858 IDirect3DDeviceImpl_1_Execute,
6859 Thunk_IDirect3DDeviceImpl_1_AddViewport,
6860 Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
6861 Thunk_IDirect3DDeviceImpl_1_NextViewport,
6862 IDirect3DDeviceImpl_1_Pick,
6863 IDirect3DDeviceImpl_1_GetPickRecords,
6864 Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
6865 IDirect3DDeviceImpl_1_CreateMatrix,
6866 IDirect3DDeviceImpl_1_SetMatrix,
6867 IDirect3DDeviceImpl_1_GetMatrix,
6868 IDirect3DDeviceImpl_1_DeleteMatrix,
6869 Thunk_IDirect3DDeviceImpl_1_BeginScene,
6870 Thunk_IDirect3DDeviceImpl_1_EndScene,
6871 Thunk_IDirect3DDeviceImpl_1_GetDirect3D
6874 /*****************************************************************************
6875 * IDirect3DDeviceImpl_CreateHandle
6877 * Not called from the VTable
6879 * Some older interface versions operate with handles, which are basically
6880 * DWORDs which identify an interface, for example
6881 * IDirect3DDevice::SetRenderState with DIRECT3DRENDERSTATE_TEXTUREHANDLE
6883 * Those handle could be just casts to the interface pointers or vice versa,
6884 * but that is not 64 bit safe and would mean blindly derefering a DWORD
6885 * passed by the app. Instead there is a dynamic array in the device which
6886 * keeps a DWORD to pointer information and a type for the handle.
6888 * Basically this array only grows, when a handle is freed its pointer is
6889 * just set to NULL. There will be much more reads from the array than
6890 * insertion operations, so a dynamic array is fine.
6892 * Params:
6893 * This: D3DDevice implementation for which this handle should be created
6895 * Returns:
6896 * A free handle on success
6897 * 0 on failure
6899 *****************************************************************************/
6900 DWORD
6901 IDirect3DDeviceImpl_CreateHandle(IDirect3DDeviceImpl *This)
6903 DWORD i;
6904 struct HandleEntry *oldHandles = This->Handles;
6906 TRACE("(%p)\n", This);
6908 for(i = 0; i < This->numHandles; i++)
6910 if(This->Handles[i].ptr == NULL &&
6911 This->Handles[i].type == DDrawHandle_Unknown)
6913 TRACE("Reusing freed handle %d\n", i + 1);
6914 return i + 1;
6918 TRACE("Growing the handle array\n");
6920 This->numHandles++;
6921 This->Handles = HeapAlloc(GetProcessHeap(), 0, sizeof(struct HandleEntry) * This->numHandles);
6922 if(!This->Handles)
6924 ERR("Out of memory\n");
6925 This->Handles = oldHandles;
6926 This->numHandles--;
6927 return 0;
6929 if(oldHandles)
6931 memcpy(This->Handles, oldHandles, (This->numHandles - 1) * sizeof(struct HandleEntry));
6932 HeapFree(GetProcessHeap(), 0, oldHandles);
6935 TRACE("Returning %d\n", This->numHandles);
6936 return This->numHandles;
6939 /*****************************************************************************
6940 * IDirect3DDeviceImpl_UpdateDepthStencil
6942 * Checks the current render target for attached depth stencils and sets the
6943 * WineD3D depth stencil accordingly.
6945 * Returns:
6946 * The depth stencil state to set if creating the device
6948 *****************************************************************************/
6949 WINED3DZBUFFERTYPE
6950 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6952 IDirectDrawSurface7 *depthStencil = NULL;
6953 IDirectDrawSurfaceImpl *dsi;
6954 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6956 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)This->target, &depthcaps, &depthStencil);
6957 if(!depthStencil)
6959 TRACE("Setting wined3d depth stencil to NULL\n");
6960 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6961 NULL);
6962 return WINED3DZB_FALSE;
6965 dsi = (IDirectDrawSurfaceImpl *)depthStencil;
6966 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->WineD3DSurface);
6967 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6968 dsi->WineD3DSurface);
6970 IDirectDrawSurface7_Release(depthStencil);
6971 return WINED3DZB_TRUE;