push 460a69df99a5ad9f5823a97170ef7a215171c033
[wine/hacks.git] / dlls / ddraw / device.c
blob819b07bda95a30ecc9f16b7714acb0c7f01fae24
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 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, 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 = ICOM_INTERFACE(This, IDirect3DDevice7);
137 /* Check DirectDraw Interfac\x01s */
138 else if( IsEqualGUID( &IID_IDirectDraw7, refiid ) )
140 *obj = ICOM_INTERFACE(This->ddraw, IDirectDraw7);
141 TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
143 else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
145 *obj = ICOM_INTERFACE(This->ddraw, IDirectDraw4);
146 TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
148 else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
150 *obj = ICOM_INTERFACE(This->ddraw, IDirectDraw2);
151 TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
153 else if( IsEqualGUID( &IID_IDirectDraw, refiid ) )
155 *obj = ICOM_INTERFACE(This->ddraw, IDirectDraw);
156 TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
159 /* Direct3D */
160 else if ( IsEqualGUID( &IID_IDirect3D , refiid ) )
162 *obj = ICOM_INTERFACE(This->ddraw, IDirect3D);
163 TRACE("(%p) Returning IDirect3D interface at %p\n", This, *obj);
165 else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) )
167 *obj = ICOM_INTERFACE(This->ddraw, IDirect3D2);
168 TRACE("(%p) Returning IDirect3D2 interface at %p\n", This, *obj);
170 else if ( IsEqualGUID( &IID_IDirect3D3 , refiid ) )
172 *obj = ICOM_INTERFACE(This->ddraw, IDirect3D3);
173 TRACE("(%p) Returning IDirect3D3 interface at %p\n", This, *obj);
175 else if ( IsEqualGUID( &IID_IDirect3D7 , refiid ) )
177 *obj = ICOM_INTERFACE(This->ddraw, IDirect3D7);
178 TRACE("(%p) Returning IDirect3D7 interface at %p\n", This, *obj);
181 /* Direct3DDevice */
182 else if ( IsEqualGUID( &IID_IDirect3DDevice , refiid ) )
184 *obj = ICOM_INTERFACE(This, IDirect3DDevice);
185 TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
187 else if ( IsEqualGUID( &IID_IDirect3DDevice2 , refiid ) ) {
188 *obj = ICOM_INTERFACE(This, IDirect3DDevice2);
189 TRACE("(%p) Returning IDirect3DDevice2 interface at %p\n", This, *obj);
191 else if ( IsEqualGUID( &IID_IDirect3DDevice3 , refiid ) ) {
192 *obj = ICOM_INTERFACE(This, IDirect3DDevice3);
193 TRACE("(%p) Returning IDirect3DDevice3 interface at %p\n", This, *obj);
195 else if ( IsEqualGUID( &IID_IDirect3DDevice7 , refiid ) ) {
196 *obj = ICOM_INTERFACE(This, IDirect3DDevice7);
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 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
218 TRACE_(ddraw_thunk)("(%p)->(%s,%p) thunking to IDirect3DDevice7 interface.\n", This, debugstr_guid(riid), obj);
219 return IDirect3DDevice7_QueryInterface(ICOM_INTERFACE(This, IDirect3DDevice7),
220 riid,
221 obj);
224 static HRESULT WINAPI
225 Thunk_IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface,
226 REFIID riid,
227 void **obj)
229 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
230 TRACE_(ddraw_thunk)("(%p)->(%s,%p) thunking to IDirect3DDevice7 interface.\n", This, debugstr_guid(riid), obj);
231 return IDirect3DDevice7_QueryInterface(ICOM_INTERFACE(This, IDirect3DDevice7),
232 riid,
233 obj);
236 static HRESULT WINAPI
237 Thunk_IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface,
238 REFIID riid,
239 void **obp)
241 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
242 TRACE_(ddraw_thunk)("(%p)->(%s,%p) thunking to IDirect3DDevice7 interface.\n", This, debugstr_guid(riid), obp);
243 return IDirect3DDevice7_QueryInterface(ICOM_INTERFACE(This, IDirect3DDevice7),
244 riid,
245 obp);
248 /*****************************************************************************
249 * IDirect3DDevice7::AddRef
251 * Increases the refcount....
252 * The most exciting Method, definitely
254 * Exists in Version 1, 2, 3 and 7
256 * Returns:
257 * The new refcount
259 *****************************************************************************/
260 static ULONG WINAPI
261 IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
263 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
264 ULONG ref = InterlockedIncrement(&This->ref);
266 TRACE("(%p) : incrementing from %u.\n", This, ref -1);
268 return ref;
271 static ULONG WINAPI
272 Thunk_IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
274 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
275 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
276 return IDirect3DDevice7_AddRef(ICOM_INTERFACE(This, IDirect3DDevice7));
279 static ULONG WINAPI
280 Thunk_IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
282 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
283 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
284 return IDirect3DDevice7_AddRef(ICOM_INTERFACE(This, IDirect3DDevice7));
287 static ULONG WINAPI
288 Thunk_IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
290 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", iface);
291 return IDirect3DDevice7_AddRef(COM_INTERFACE_CAST(IDirect3DDeviceImpl, IDirect3DDevice, IDirect3DDevice7, iface));
294 /*****************************************************************************
295 * IDirect3DDevice7::Release
297 * Decreases the refcount of the interface
298 * When the refcount is reduced to 0, the object is destroyed.
300 * Exists in Version 1, 2, 3 and 7
302 * Returns:d
303 * The new refcount
305 *****************************************************************************/
306 static ULONG WINAPI
307 IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
309 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
310 ULONG ref = InterlockedDecrement(&This->ref);
312 TRACE("(%p)->() decrementing from %u.\n", This, ref +1);
314 /* This method doesn't destroy the WineD3DDevice, because it's still in use for
315 * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
316 * when the render target is released
318 if (ref == 0)
320 IParent *IndexBufferParent;
321 DWORD i;
323 EnterCriticalSection(&ddraw_cs);
324 /* Free the index buffer. */
325 IWineD3DDevice_SetIndices(This->wineD3DDevice, NULL);
326 IWineD3DIndexBuffer_GetParent(This->indexbuffer,
327 (IUnknown **) &IndexBufferParent);
328 IParent_Release(IndexBufferParent); /* Once for the getParent */
329 if( IParent_Release(IndexBufferParent) != 0) /* And now to destroy it */
331 ERR(" (%p) Something is still holding the index buffer parent %p\n", This, IndexBufferParent);
334 /* There is no need to unset the vertex buffer here, IWineD3DDevice_Uninit3D will do that when
335 * destroying the primary stateblock. If a vertex buffer is destroyed while it is bound
336 * IDirect3DVertexBuffer::Release will unset it.
339 /* Restore the render targets */
340 if(This->OffScreenTarget)
342 WINED3DVIEWPORT vp;
344 vp.X = 0;
345 vp.Y = 0;
346 vp.Width = This->ddraw->d3d_target->surface_desc.dwWidth;
347 vp.Height = This->ddraw->d3d_target->surface_desc.dwHeight;
348 vp.MinZ = 0.0;
349 vp.MaxZ = 1.0;
350 IWineD3DDevice_SetViewport(This->wineD3DDevice,
351 &vp);
353 /* Set the device up to render to the front buffer since the back buffer will
354 * vanish soon.
356 IWineD3DDevice_SetRenderTarget(This->wineD3DDevice, 0,
357 This->ddraw->d3d_target->WineD3DSurface);
358 /* This->target is the offscreen target.
359 * This->ddraw->d3d_target is the target used by DDraw
361 TRACE("(%p) Release: Using %p as front buffer, %p as back buffer\n", This, This->ddraw->d3d_target, NULL);
362 IWineD3DDevice_SetFrontBackBuffers(This->wineD3DDevice,
363 This->ddraw->d3d_target->WineD3DSurface,
364 NULL);
367 /* Release the WineD3DDevice. This won't destroy it */
368 if(IWineD3DDevice_Release(This->wineD3DDevice) <= 0)
370 ERR(" (%p) The wineD3D device %p was destroyed unexpectedly. Prepare for trouble\n", This, This->wineD3DDevice);
373 /* The texture handles should be unset by now, but there might be some bits
374 * missing in our reference counting(needs test). Do a sanity check
376 for(i = 0; i < This->numHandles; i++)
378 if(This->Handles[i].ptr)
380 switch(This->Handles[i].type)
382 case DDrawHandle_Texture:
384 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *) This->Handles[i].ptr;
385 FIXME("Texture Handle %d not unset properly\n", i + 1);
386 surf->Handle = 0;
388 break;
390 case DDrawHandle_Material:
392 IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) This->Handles[i].ptr;
393 FIXME("Material handle %d not unset properly\n", i + 1);
394 mat->Handle = 0;
396 break;
398 case DDrawHandle_Matrix:
400 /* No fixme here because this might happen because of sloppy apps */
401 WARN("Leftover matrix handle %d, deleting\n", i + 1);
402 IDirect3DDevice_DeleteMatrix(ICOM_INTERFACE(This, IDirect3DDevice),
403 i + 1);
405 break;
407 case DDrawHandle_StateBlock:
409 /* No fixme here because this might happen because of sloppy apps */
410 WARN("Leftover stateblock handle %d, deleting\n", i + 1);
411 IDirect3DDevice7_DeleteStateBlock(ICOM_INTERFACE(This, IDirect3DDevice7),
412 i + 1);
414 break;
416 default:
417 FIXME("Unknown handle %d not unset properly\n", i + 1);
422 HeapFree(GetProcessHeap(), 0, This->Handles);
424 TRACE("Releasing target %p %p\n", This->target, This->ddraw->d3d_target);
425 /* Release the render target and the WineD3D render target
426 * (See IDirect3D7::CreateDevice for more comments on this)
428 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->target, IDirectDrawSurface7));
429 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->ddraw->d3d_target,IDirectDrawSurface7));
430 TRACE("Target release done\n");
432 This->ddraw->d3ddevice = NULL;
434 /* Now free the structure */
435 HeapFree(GetProcessHeap(), 0, This);
436 LeaveCriticalSection(&ddraw_cs);
439 TRACE("Done\n");
440 return ref;
443 static ULONG WINAPI
444 Thunk_IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
446 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
447 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
448 return IDirect3DDevice7_Release(ICOM_INTERFACE(This, IDirect3DDevice7));
451 static ULONG WINAPI
452 Thunk_IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
454 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
455 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
456 return IDirect3DDevice7_Release(ICOM_INTERFACE(This, IDirect3DDevice7));
459 static ULONG WINAPI
460 Thunk_IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
462 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
463 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
464 return IDirect3DDevice7_Release(ICOM_INTERFACE(This, IDirect3DDevice7));
467 /*****************************************************************************
468 * IDirect3DDevice Methods
469 *****************************************************************************/
471 /*****************************************************************************
472 * IDirect3DDevice::Initialize
474 * Initializes a Direct3DDevice. This implementation is a no-op, as all
475 * initialization is done at create time.
477 * Exists in Version 1
479 * Parameters:
480 * No idea what they mean, as the MSDN page is gone
482 * Returns: DD_OK
484 *****************************************************************************/
485 static HRESULT WINAPI
486 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
487 IDirect3D *Direct3D, GUID *guid,
488 D3DDEVICEDESC *Desc)
490 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
492 /* It shouldn't be crucial, but print a FIXME, I'm interested if
493 * any game calls it and when
495 FIXME("(%p)->(%p,%p,%p): No-op!\n", This, Direct3D, guid, Desc);
497 return D3D_OK;
500 /*****************************************************************************
501 * IDirect3DDevice7::GetCaps
503 * Retrieves the device's capabilities
505 * This implementation is used for Version 7 only, the older versions have
506 * their own implementation.
508 * Parameters:
509 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
511 * Returns:
512 * D3D_OK on success
513 * D3DERR_* if a problem occurs. See WineD3D
515 *****************************************************************************/
516 static HRESULT
517 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
518 D3DDEVICEDESC7 *Desc)
520 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
521 D3DDEVICEDESC OldDesc;
522 TRACE("(%p)->(%p)\n", This, Desc);
524 /* Call the same function used by IDirect3D, this saves code */
525 return IDirect3DImpl_GetCaps(This->ddraw->wineD3D, &OldDesc, Desc);
528 static HRESULT WINAPI
529 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
530 D3DDEVICEDESC7 *Desc)
532 return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
535 static HRESULT WINAPI
536 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
537 D3DDEVICEDESC7 *Desc)
539 HRESULT hr;
540 WORD old_fpucw;
542 old_fpucw = d3d_fpu_setup();
543 hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
544 set_fpu_control_word(old_fpucw);
546 return hr;
548 /*****************************************************************************
549 * IDirect3DDevice3::GetCaps
551 * Retrieves the capabilities of the hardware device and the emulation
552 * device. For Wine, hardware and emulation are the same (it's all HW).
554 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
556 * Parameters:
557 * HWDesc: Structure to fill with the HW caps
558 * HelDesc: Structure to fill with the hardware emulation caps
560 * Returns:
561 * D3D_OK on success
562 * D3DERR_* if a problem occurs. See WineD3D
564 *****************************************************************************/
565 static HRESULT WINAPI
566 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
567 D3DDEVICEDESC *HWDesc,
568 D3DDEVICEDESC *HelDesc)
570 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
571 D3DDEVICEDESC7 newDesc;
572 HRESULT hr;
573 TRACE("(%p)->(%p,%p)\n", iface, HWDesc, HelDesc);
575 hr = IDirect3DImpl_GetCaps(This->ddraw->wineD3D, HWDesc, &newDesc);
576 if(hr != D3D_OK) return hr;
578 *HelDesc = *HWDesc;
579 return D3D_OK;
582 static HRESULT WINAPI
583 Thunk_IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
584 D3DDEVICEDESC *D3DHWDevDesc,
585 D3DDEVICEDESC *D3DHELDevDesc)
587 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
588 TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice3 interface.\n", This, D3DHWDevDesc, D3DHELDevDesc);
589 return IDirect3DDevice3_GetCaps(ICOM_INTERFACE(This, IDirect3DDevice3),
590 D3DHWDevDesc,
591 D3DHELDevDesc);
594 static HRESULT WINAPI
595 Thunk_IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
596 D3DDEVICEDESC *D3DHWDevDesc,
597 D3DDEVICEDESC *D3DHELDevDesc)
599 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
600 TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice3 interface.\n", This, D3DHWDevDesc, D3DHELDevDesc);
601 return IDirect3DDevice3_GetCaps(ICOM_INTERFACE(This, IDirect3DDevice3),
602 D3DHWDevDesc,
603 D3DHELDevDesc);
606 /*****************************************************************************
607 * IDirect3DDevice2::SwapTextureHandles
609 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
611 * Parameters:
612 * Tex1, Tex2: The 2 Textures to swap
614 * Returns:
615 * D3D_OK
617 *****************************************************************************/
618 static HRESULT WINAPI
619 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
620 IDirect3DTexture2 *Tex1,
621 IDirect3DTexture2 *Tex2)
623 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
624 DWORD swap;
625 IDirectDrawSurfaceImpl *surf1 = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture2, Tex1);
626 IDirectDrawSurfaceImpl *surf2 = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture2, Tex2);
627 TRACE("(%p)->(%p,%p)\n", This, surf1, surf2);
629 EnterCriticalSection(&ddraw_cs);
630 This->Handles[surf1->Handle - 1].ptr = surf2;
631 This->Handles[surf2->Handle - 1].ptr = surf1;
633 swap = surf2->Handle;
634 surf2->Handle = surf1->Handle;
635 surf1->Handle = swap;
636 LeaveCriticalSection(&ddraw_cs);
638 return D3D_OK;
641 static HRESULT WINAPI
642 Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
643 IDirect3DTexture *D3DTex1,
644 IDirect3DTexture *D3DTex2)
646 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
647 IDirectDrawSurfaceImpl *surf1 = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture, D3DTex1);
648 IDirectDrawSurfaceImpl *surf2 = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture, D3DTex2);
649 TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice2 interface.\n", This, surf1, surf2);
650 return IDirect3DDevice2_SwapTextureHandles(ICOM_INTERFACE(This, IDirect3DDevice2),
651 ICOM_INTERFACE(surf1, IDirect3DTexture2),
652 ICOM_INTERFACE(surf2, IDirect3DTexture2));
655 /*****************************************************************************
656 * IDirect3DDevice3::GetStats
658 * This method seems to retrieve some stats from the device.
659 * The MSDN documentation doesn't exist any more, but the D3DSTATS
660 * structure suggests that the amount of drawn primitives and processed
661 * vertices is returned.
663 * Exists in Version 1, 2 and 3
665 * Parameters:
666 * Stats: Pointer to a D3DSTATS structure to be filled
668 * Returns:
669 * D3D_OK on success
670 * DDERR_INVALIDPARAMS if Stats == NULL
672 *****************************************************************************/
673 static HRESULT WINAPI
674 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
675 D3DSTATS *Stats)
677 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
678 FIXME("(%p)->(%p): Stub!\n", This, Stats);
680 if(!Stats)
681 return DDERR_INVALIDPARAMS;
683 /* Fill the Stats with 0 */
684 Stats->dwTrianglesDrawn = 0;
685 Stats->dwLinesDrawn = 0;
686 Stats->dwPointsDrawn = 0;
687 Stats->dwSpansDrawn = 0;
688 Stats->dwVerticesProcessed = 0;
690 return D3D_OK;
693 static HRESULT WINAPI
694 Thunk_IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface,
695 D3DSTATS *Stats)
697 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
698 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, Stats);
699 return IDirect3DDevice3_GetStats(ICOM_INTERFACE(This, IDirect3DDevice3),
700 Stats);
703 static HRESULT WINAPI
704 Thunk_IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface,
705 D3DSTATS *Stats)
707 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
708 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, Stats);
709 return IDirect3DDevice3_GetStats(ICOM_INTERFACE(This, IDirect3DDevice3),
710 Stats);
713 /*****************************************************************************
714 * IDirect3DDevice::CreateExecuteBuffer
716 * Creates an IDirect3DExecuteBuffer, used for rendering with a
717 * Direct3DDevice.
719 * Version 1 only.
721 * Params:
722 * Desc: Buffer description
723 * ExecuteBuffer: Address to return the Interface pointer at
724 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
725 * support
727 * Returns:
728 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
729 * DDERR_OUTOFMEMORY if we ran out of memory
730 * D3D_OK on success
732 *****************************************************************************/
733 static HRESULT WINAPI
734 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
735 D3DEXECUTEBUFFERDESC *Desc,
736 IDirect3DExecuteBuffer **ExecuteBuffer,
737 IUnknown *UnkOuter)
739 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
740 IDirect3DExecuteBufferImpl* object;
741 TRACE("(%p)->(%p,%p,%p)!\n", This, Desc, ExecuteBuffer, UnkOuter);
743 if(UnkOuter)
744 return CLASS_E_NOAGGREGATION;
746 /* Allocate the new Execute Buffer */
747 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
748 if(!object)
750 ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
751 return DDERR_OUTOFMEMORY;
754 ICOM_INIT_INTERFACE(object, IDirect3DExecuteBuffer, IDirect3DExecuteBuffer_Vtbl);
756 object->ref = 1;
757 object->d3ddev = This;
759 /* Initializes memory */
760 memcpy(&object->desc, Desc, Desc->dwSize);
762 /* No buffer given */
763 if ((object->desc.dwFlags & D3DDEB_LPDATA) == 0)
764 object->desc.lpData = NULL;
766 /* No buffer size given */
767 if ((object->desc.dwFlags & D3DDEB_BUFSIZE) == 0)
768 object->desc.dwBufferSize = 0;
770 /* Create buffer if asked */
771 if ((object->desc.lpData == NULL) && (object->desc.dwBufferSize > 0))
773 object->need_free = TRUE;
774 object->desc.lpData = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,object->desc.dwBufferSize);
775 if(!object->desc.lpData)
777 ERR("Out of memory when allocating the execute buffer data\n");
778 HeapFree(GetProcessHeap(), 0, object);
779 return DDERR_OUTOFMEMORY;
782 else
784 object->need_free = FALSE;
787 /* No vertices for the moment */
788 object->vertex_data = NULL;
790 object->desc.dwFlags |= D3DDEB_LPDATA;
792 object->indices = NULL;
793 object->nb_indices = 0;
795 *ExecuteBuffer = ICOM_INTERFACE(object, IDirect3DExecuteBuffer);
797 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
799 return D3D_OK;
802 /*****************************************************************************
803 * IDirect3DDevice::Execute
805 * Executes all the stuff in an execute buffer.
807 * Params:
808 * ExecuteBuffer: The buffer to execute
809 * Viewport: The viewport used for rendering
810 * Flags: Some flags
812 * Returns:
813 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
814 * D3D_OK on success
816 *****************************************************************************/
817 static HRESULT WINAPI
818 IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
819 IDirect3DExecuteBuffer *ExecuteBuffer,
820 IDirect3DViewport *Viewport,
821 DWORD Flags)
823 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
824 IDirect3DExecuteBufferImpl *Direct3DExecuteBufferImpl = ICOM_OBJECT(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, ExecuteBuffer);
825 IDirect3DViewportImpl *Direct3DViewportImpl = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Viewport);
827 TRACE("(%p)->(%p,%p,%08x)\n", This, Direct3DExecuteBufferImpl, Direct3DViewportImpl, Flags);
829 if(!Direct3DExecuteBufferImpl)
830 return DDERR_INVALIDPARAMS;
832 /* Execute... */
833 EnterCriticalSection(&ddraw_cs);
834 IDirect3DExecuteBufferImpl_Execute(Direct3DExecuteBufferImpl, This, Direct3DViewportImpl);
835 LeaveCriticalSection(&ddraw_cs);
837 return D3D_OK;
840 /*****************************************************************************
841 * IDirect3DDevice3::AddViewport
843 * Add a Direct3DViewport to the device's viewport list. These viewports
844 * are wrapped to IDirect3DDevice7 viewports in viewport.c
846 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
847 * are the same interfaces.
849 * Params:
850 * Viewport: The viewport to add
852 * Returns:
853 * DDERR_INVALIDPARAMS if Viewport == NULL
854 * D3D_OK on success
856 *****************************************************************************/
857 static HRESULT WINAPI
858 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
859 IDirect3DViewport3 *Viewport)
861 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
862 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Viewport);
864 TRACE("(%p)->(%p)\n", This, vp);
866 /* Sanity check */
867 if(!vp)
868 return DDERR_INVALIDPARAMS;
870 EnterCriticalSection(&ddraw_cs);
871 vp->next = This->viewport_list;
872 This->viewport_list = vp;
873 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
874 so set active_device here. */
875 LeaveCriticalSection(&ddraw_cs);
877 return D3D_OK;
880 static HRESULT WINAPI
881 Thunk_IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
882 IDirect3DViewport2 *Direct3DViewport2)
884 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
885 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Direct3DViewport2);
886 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
887 return IDirect3DDevice3_AddViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
888 ICOM_INTERFACE(vp, IDirect3DViewport3));
891 static HRESULT WINAPI
892 Thunk_IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
893 IDirect3DViewport *Direct3DViewport)
895 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
896 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Direct3DViewport);
897 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
898 return IDirect3DDevice3_AddViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
899 ICOM_INTERFACE(vp, IDirect3DViewport3));
902 /*****************************************************************************
903 * IDirect3DDevice3::DeleteViewport
905 * Deletes a Direct3DViewport from the device's viewport list.
907 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
908 * are equal.
910 * Params:
911 * Viewport: The viewport to delete
913 * Returns:
914 * D3D_OK on success
915 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
917 *****************************************************************************/
918 static HRESULT WINAPI
919 IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface,
920 IDirect3DViewport3 *Viewport)
922 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
923 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *) Viewport;
924 IDirect3DViewportImpl *cur_viewport, *prev_viewport = NULL;
926 TRACE("(%p)->(%p)\n", This, vp);
928 EnterCriticalSection(&ddraw_cs);
929 cur_viewport = This->viewport_list;
930 while (cur_viewport != NULL)
932 if (cur_viewport == vp)
934 if (prev_viewport == NULL) This->viewport_list = cur_viewport->next;
935 else prev_viewport->next = cur_viewport->next;
936 /* TODO : add desactivate of the viewport and all associated lights... */
937 LeaveCriticalSection(&ddraw_cs);
938 return D3D_OK;
940 prev_viewport = cur_viewport;
941 cur_viewport = cur_viewport->next;
944 LeaveCriticalSection(&ddraw_cs);
945 return DDERR_INVALIDPARAMS;
948 static HRESULT WINAPI
949 Thunk_IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
950 IDirect3DViewport2 *Direct3DViewport2)
952 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
953 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Direct3DViewport2);
954 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
955 return IDirect3DDevice3_DeleteViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
956 ICOM_INTERFACE(vp, IDirect3DViewport3));
959 static HRESULT WINAPI
960 Thunk_IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
961 IDirect3DViewport *Direct3DViewport)
963 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
964 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Direct3DViewport);
965 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
966 return IDirect3DDevice3_DeleteViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
967 ICOM_INTERFACE(vp, IDirect3DViewport3));
970 /*****************************************************************************
971 * IDirect3DDevice3::NextViewport
973 * Returns a viewport from the viewport list, depending on the
974 * passed viewport and the flags.
976 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
977 * are equal.
979 * Params:
980 * Viewport: Viewport to use for beginning the search
981 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
983 * Returns:
984 * D3D_OK on success
985 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
987 *****************************************************************************/
988 static HRESULT WINAPI
989 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
990 IDirect3DViewport3 *Viewport3,
991 IDirect3DViewport3 **lplpDirect3DViewport3,
992 DWORD Flags)
994 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
995 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Viewport3);
996 IDirect3DViewportImpl *res = NULL;
998 TRACE("(%p)->(%p,%p,%08x)\n", This, vp, lplpDirect3DViewport3, Flags);
1000 if(!vp)
1002 *lplpDirect3DViewport3 = NULL;
1003 return DDERR_INVALIDPARAMS;
1007 EnterCriticalSection(&ddraw_cs);
1008 switch (Flags)
1010 case D3DNEXT_NEXT:
1012 res = vp->next;
1014 break;
1015 case D3DNEXT_HEAD:
1017 res = This->viewport_list;
1019 break;
1020 case D3DNEXT_TAIL:
1022 IDirect3DViewportImpl *cur_viewport = This->viewport_list;
1023 if (cur_viewport != NULL)
1025 while (cur_viewport->next != NULL) cur_viewport = cur_viewport->next;
1027 res = cur_viewport;
1029 break;
1030 default:
1031 *lplpDirect3DViewport3 = NULL;
1032 LeaveCriticalSection(&ddraw_cs);
1033 return DDERR_INVALIDPARAMS;
1036 *lplpDirect3DViewport3 = ICOM_INTERFACE(res, IDirect3DViewport3);
1037 LeaveCriticalSection(&ddraw_cs);
1038 return D3D_OK;
1041 static HRESULT WINAPI
1042 Thunk_IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
1043 IDirect3DViewport2 *Viewport2,
1044 IDirect3DViewport2 **lplpDirect3DViewport2,
1045 DWORD Flags)
1047 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1048 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Viewport2);
1049 IDirect3DViewport3 *res;
1050 HRESULT hr;
1051 TRACE_(ddraw_thunk)("(%p)->(%p,%p,%08x) thunking to IDirect3DDevice3 interface.\n", This, vp, lplpDirect3DViewport2, Flags);
1052 hr = IDirect3DDevice3_NextViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
1053 ICOM_INTERFACE(vp, IDirect3DViewport3),
1054 &res,
1055 Flags);
1056 *lplpDirect3DViewport2 = (IDirect3DViewport2 *) COM_INTERFACE_CAST(IDirect3DViewportImpl, IDirect3DViewport3, IDirect3DViewport3, res);
1057 return hr;
1060 static HRESULT WINAPI
1061 Thunk_IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
1062 IDirect3DViewport *Viewport,
1063 IDirect3DViewport **lplpDirect3DViewport,
1064 DWORD Flags)
1066 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1067 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Viewport);
1068 IDirect3DViewport3 *res;
1069 HRESULT hr;
1070 TRACE_(ddraw_thunk)("(%p)->(%p,%p,%08x) thunking to IDirect3DDevice3 interface.\n", This, vp, lplpDirect3DViewport, Flags);
1071 hr = IDirect3DDevice3_NextViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
1072 ICOM_INTERFACE(vp, IDirect3DViewport3),
1073 &res,
1074 Flags);
1075 *lplpDirect3DViewport = (IDirect3DViewport *) COM_INTERFACE_CAST(IDirect3DViewportImpl, IDirect3DViewport3, IDirect3DViewport3, res);
1076 return hr;
1079 /*****************************************************************************
1080 * IDirect3DDevice::Pick
1082 * Executes an execute buffer without performing rendering. Instead, a
1083 * list of primitives that intersect with (x1,y1) of the passed rectangle
1084 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
1085 * this list.
1087 * Version 1 only
1089 * Params:
1090 * ExecuteBuffer: Buffer to execute
1091 * Viewport: Viewport to use for execution
1092 * Flags: None are defined, according to the SDK
1093 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
1094 * x2 and y2 are ignored.
1096 * Returns:
1097 * D3D_OK because it's a stub
1099 *****************************************************************************/
1100 static HRESULT WINAPI
1101 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
1102 IDirect3DExecuteBuffer *ExecuteBuffer,
1103 IDirect3DViewport *Viewport,
1104 DWORD Flags,
1105 D3DRECT *Rect)
1107 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1108 IDirect3DExecuteBufferImpl *execbuf = ICOM_OBJECT(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, ExecuteBuffer);
1109 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Viewport);
1110 FIXME("(%p)->(%p,%p,%08x,%p): stub!\n", This, execbuf, vp, Flags, Rect);
1112 return D3D_OK;
1115 /*****************************************************************************
1116 * IDirect3DDevice::GetPickRecords
1118 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1120 * Version 1 only
1122 * Params:
1123 * Count: Pointer to a DWORD containing the numbers of pick records to
1124 * retrieve
1125 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1127 * Returns:
1128 * D3D_OK, because it's a stub
1130 *****************************************************************************/
1131 static HRESULT WINAPI
1132 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1133 DWORD *Count,
1134 D3DPICKRECORD *D3DPickRec)
1136 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1137 FIXME("(%p)->(%p,%p): stub!\n", This, Count, D3DPickRec);
1139 return D3D_OK;
1142 /*****************************************************************************
1143 * IDirect3DDevice7::EnumTextureformats
1145 * Enumerates the supported texture formats. It has a list of all possible
1146 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1147 * WineD3D supports it. If so, then it is passed to the app.
1149 * This is for Version 7 and 3, older versions have a different
1150 * callback function and their own implementation
1152 * Params:
1153 * Callback: Callback to call for each enumerated format
1154 * Arg: Argument to pass to the callback
1156 * Returns:
1157 * D3D_OK on success
1158 * DDERR_INVALIDPARAMS if Callback == NULL
1160 *****************************************************************************/
1161 static HRESULT
1162 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1163 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1164 void *Arg)
1166 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1167 HRESULT hr;
1168 WINED3DDISPLAYMODE mode;
1169 unsigned int i;
1171 WINED3DFORMAT FormatList[] = {
1172 /* 32 bit */
1173 WINED3DFMT_A8R8G8B8,
1174 WINED3DFMT_X8R8G8B8,
1175 /* 24 bit */
1176 WINED3DFMT_R8G8B8,
1177 /* 16 Bit */
1178 WINED3DFMT_A1R5G5B5,
1179 WINED3DFMT_A4R4G4B4,
1180 WINED3DFMT_R5G6B5,
1181 WINED3DFMT_X1R5G5B5,
1182 /* 8 Bit */
1183 WINED3DFMT_R3G3B2,
1184 WINED3DFMT_P8,
1185 /* FOURCC codes */
1186 WINED3DFMT_DXT1,
1187 WINED3DFMT_DXT3,
1188 WINED3DFMT_DXT5,
1191 WINED3DFORMAT BumpFormatList[] = {
1192 WINED3DFMT_V8U8,
1193 WINED3DFMT_L6V5U5,
1194 WINED3DFMT_X8L8V8U8,
1195 WINED3DFMT_Q8W8V8U8,
1196 WINED3DFMT_V16U16,
1197 WINED3DFMT_W11V11U10,
1198 WINED3DFMT_A2W10V10U10
1201 TRACE("(%p)->(%p,%p): Relay\n", This, Callback, Arg);
1203 if(!Callback)
1204 return DDERR_INVALIDPARAMS;
1206 EnterCriticalSection(&ddraw_cs);
1208 memset(&mode, 0, sizeof(mode));
1209 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1211 &mode);
1212 if(FAILED(hr)) {
1213 LeaveCriticalSection(&ddraw_cs);
1214 WARN("Cannot get the current adapter format\n");
1215 return hr;
1218 for(i = 0; i < sizeof(FormatList) / sizeof(WINED3DFORMAT); i++)
1220 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1221 WINED3DADAPTER_DEFAULT,
1222 WINED3DDEVTYPE_HAL,
1223 mode.Format,
1224 0 /* Usage */,
1225 WINED3DRTYPE_TEXTURE,
1226 FormatList[i],
1227 SURFACE_OPENGL);
1228 if(hr == D3D_OK)
1230 DDPIXELFORMAT pformat;
1232 memset(&pformat, 0, sizeof(pformat));
1233 pformat.dwSize = sizeof(pformat);
1234 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1236 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1237 hr = Callback(&pformat, Arg);
1238 if(hr != DDENUMRET_OK)
1240 TRACE("Format enumeration cancelled by application\n");
1241 LeaveCriticalSection(&ddraw_cs);
1242 return D3D_OK;
1247 for(i = 0; i < sizeof(BumpFormatList) / sizeof(WINED3DFORMAT); i++)
1249 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1250 WINED3DADAPTER_DEFAULT,
1251 WINED3DDEVTYPE_HAL,
1252 mode.Format,
1253 WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1254 WINED3DRTYPE_TEXTURE,
1255 BumpFormatList[i],
1256 SURFACE_OPENGL);
1257 if(hr == D3D_OK)
1259 DDPIXELFORMAT pformat;
1261 memset(&pformat, 0, sizeof(pformat));
1262 pformat.dwSize = sizeof(pformat);
1263 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1265 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1266 hr = Callback(&pformat, Arg);
1267 if(hr != DDENUMRET_OK)
1269 TRACE("Format enumeration cancelled by application\n");
1270 LeaveCriticalSection(&ddraw_cs);
1271 return D3D_OK;
1275 TRACE("End of enumeration\n");
1276 LeaveCriticalSection(&ddraw_cs);
1277 return D3D_OK;
1280 static HRESULT WINAPI
1281 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1282 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1283 void *Arg)
1285 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1288 static HRESULT WINAPI
1289 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1290 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1291 void *Arg)
1293 HRESULT hr;
1294 WORD old_fpucw;
1296 old_fpucw = d3d_fpu_setup();
1297 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1298 set_fpu_control_word(old_fpucw);
1300 return hr;
1303 static HRESULT WINAPI
1304 Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1305 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1306 void *Arg)
1308 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1309 TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice7 interface.\n", This, Callback, Arg);
1310 return IDirect3DDevice7_EnumTextureFormats(ICOM_INTERFACE(This, IDirect3DDevice7),
1311 Callback,
1312 Arg);
1315 /*****************************************************************************
1316 * IDirect3DDevice2::EnumTextureformats
1318 * EnumTextureFormats for Version 1 and 2, see
1319 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1321 * This version has a different callback and does not enumerate FourCC
1322 * formats
1324 *****************************************************************************/
1325 static HRESULT WINAPI
1326 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1327 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1328 void *Arg)
1330 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1331 HRESULT hr;
1332 unsigned int i;
1333 WINED3DDISPLAYMODE mode;
1335 WINED3DFORMAT FormatList[] = {
1336 /* 32 bit */
1337 WINED3DFMT_A8R8G8B8,
1338 WINED3DFMT_X8R8G8B8,
1339 /* 24 bit */
1340 WINED3DFMT_R8G8B8,
1341 /* 16 Bit */
1342 WINED3DFMT_A1R5G5B5,
1343 WINED3DFMT_A4R4G4B4,
1344 WINED3DFMT_R5G6B5,
1345 WINED3DFMT_X1R5G5B5,
1346 /* 8 Bit */
1347 WINED3DFMT_R3G3B2,
1348 WINED3DFMT_P8,
1349 /* FOURCC codes - Not in this version*/
1352 TRACE("(%p)->(%p,%p): Relay\n", This, Callback, Arg);
1354 if(!Callback)
1355 return DDERR_INVALIDPARAMS;
1357 EnterCriticalSection(&ddraw_cs);
1359 memset(&mode, 0, sizeof(mode));
1360 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1362 &mode);
1363 if(FAILED(hr)) {
1364 LeaveCriticalSection(&ddraw_cs);
1365 WARN("Cannot get the current adapter format\n");
1366 return hr;
1369 for(i = 0; i < sizeof(FormatList) / sizeof(WINED3DFORMAT); i++)
1371 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1372 0 /* Adapter */,
1373 WINED3DDEVTYPE_HAL,
1374 mode.Format,
1375 0 /* Usage */,
1376 WINED3DRTYPE_TEXTURE,
1377 FormatList[i],
1378 SURFACE_OPENGL);
1379 if(hr == D3D_OK)
1381 DDSURFACEDESC sdesc;
1383 memset(&sdesc, 0, sizeof(sdesc));
1384 sdesc.dwSize = sizeof(sdesc);
1385 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1386 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1387 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1388 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1390 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1391 hr = Callback(&sdesc, Arg);
1392 if(hr != DDENUMRET_OK)
1394 TRACE("Format enumeration cancelled by application\n");
1395 LeaveCriticalSection(&ddraw_cs);
1396 return D3D_OK;
1400 TRACE("End of enumeration\n");
1401 LeaveCriticalSection(&ddraw_cs);
1402 return D3D_OK;
1405 static HRESULT WINAPI
1406 Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1407 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1408 void *Arg)
1410 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1411 TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice2 interface.\n", This, Callback, Arg);
1412 return IDirect3DDevice2_EnumTextureFormats(ICOM_INTERFACE(This, IDirect3DDevice2),
1413 Callback,
1414 Arg);
1417 /*****************************************************************************
1418 * IDirect3DDevice::CreateMatrix
1420 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1421 * allocated for the handle.
1423 * Version 1 only
1425 * Params
1426 * D3DMatHandle: Address to return the handle at
1428 * Returns:
1429 * D3D_OK on success
1430 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1432 *****************************************************************************/
1433 static HRESULT WINAPI
1434 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1436 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1437 D3DMATRIX *Matrix;
1438 TRACE("(%p)->(%p)\n", This, D3DMatHandle);
1440 if(!D3DMatHandle)
1441 return DDERR_INVALIDPARAMS;
1443 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1444 if(!Matrix)
1446 ERR("Out of memory when allocating a D3DMATRIX\n");
1447 return DDERR_OUTOFMEMORY;
1450 EnterCriticalSection(&ddraw_cs);
1451 *D3DMatHandle = IDirect3DDeviceImpl_CreateHandle(This);
1452 if(!(*D3DMatHandle))
1454 ERR("Failed to create a matrix handle\n");
1455 HeapFree(GetProcessHeap(), 0, Matrix);
1456 LeaveCriticalSection(&ddraw_cs);
1457 return DDERR_OUTOFMEMORY;
1459 This->Handles[*D3DMatHandle - 1].ptr = Matrix;
1460 This->Handles[*D3DMatHandle - 1].type = DDrawHandle_Matrix;
1461 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1463 LeaveCriticalSection(&ddraw_cs);
1464 return D3D_OK;
1467 /*****************************************************************************
1468 * IDirect3DDevice::SetMatrix
1470 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1471 * allocated for the handle
1473 * Version 1 only
1475 * Params:
1476 * D3DMatHandle: Handle to set the matrix to
1477 * D3DMatrix: Matrix to set
1479 * Returns:
1480 * D3D_OK on success
1481 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1482 * to set is NULL
1484 *****************************************************************************/
1485 static HRESULT WINAPI
1486 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1487 D3DMATRIXHANDLE D3DMatHandle,
1488 D3DMATRIX *D3DMatrix)
1490 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1491 TRACE("(%p)->(%08x,%p)\n", This, D3DMatHandle, D3DMatrix);
1493 if( (!D3DMatHandle) || (!D3DMatrix) )
1494 return DDERR_INVALIDPARAMS;
1496 EnterCriticalSection(&ddraw_cs);
1497 if(D3DMatHandle > This->numHandles)
1499 ERR("Handle %d out of range\n", D3DMatHandle);
1500 LeaveCriticalSection(&ddraw_cs);
1501 return DDERR_INVALIDPARAMS;
1503 else if(This->Handles[D3DMatHandle - 1].type != DDrawHandle_Matrix)
1505 ERR("Handle %d is not a matrix handle\n", D3DMatHandle);
1506 LeaveCriticalSection(&ddraw_cs);
1507 return DDERR_INVALIDPARAMS;
1510 if (TRACE_ON(d3d7))
1511 dump_D3DMATRIX(D3DMatrix);
1513 *((D3DMATRIX *) This->Handles[D3DMatHandle - 1].ptr) = *D3DMatrix;
1515 if(This->world == D3DMatHandle)
1517 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1518 WINED3DTS_WORLDMATRIX(0),
1519 (WINED3DMATRIX *) D3DMatrix);
1521 if(This->view == D3DMatHandle)
1523 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1524 WINED3DTS_VIEW,
1525 (WINED3DMATRIX *) D3DMatrix);
1527 if(This->proj == D3DMatHandle)
1529 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1530 WINED3DTS_PROJECTION,
1531 (WINED3DMATRIX *) D3DMatrix);
1534 LeaveCriticalSection(&ddraw_cs);
1535 return D3D_OK;
1538 /*****************************************************************************
1539 * IDirect3DDevice::SetMatrix
1541 * Returns the content of a D3DMATRIX handle
1543 * Version 1 only
1545 * Params:
1546 * D3DMatHandle: Matrix handle to read the content from
1547 * D3DMatrix: Address to store the content at
1549 * Returns:
1550 * D3D_OK on success
1551 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1553 *****************************************************************************/
1554 static HRESULT WINAPI
1555 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1556 D3DMATRIXHANDLE D3DMatHandle,
1557 D3DMATRIX *D3DMatrix)
1559 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1560 TRACE("(%p)->(%08x,%p)\n", This, D3DMatHandle, D3DMatrix);
1562 if(!D3DMatrix)
1563 return DDERR_INVALIDPARAMS;
1564 if(!D3DMatHandle)
1565 return DDERR_INVALIDPARAMS;
1567 EnterCriticalSection(&ddraw_cs);
1568 if(D3DMatHandle > This->numHandles)
1570 ERR("Handle %d out of range\n", D3DMatHandle);
1571 LeaveCriticalSection(&ddraw_cs);
1572 return DDERR_INVALIDPARAMS;
1574 else if(This->Handles[D3DMatHandle - 1].type != DDrawHandle_Matrix)
1576 ERR("Handle %d is not a matrix handle\n", D3DMatHandle);
1577 LeaveCriticalSection(&ddraw_cs);
1578 return DDERR_INVALIDPARAMS;
1581 /* The handle is simply a pointer to a D3DMATRIX structure */
1582 *D3DMatrix = *((D3DMATRIX *) This->Handles[D3DMatHandle - 1].ptr);
1584 LeaveCriticalSection(&ddraw_cs);
1585 return D3D_OK;
1588 /*****************************************************************************
1589 * IDirect3DDevice::DeleteMatrix
1591 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1593 * Version 1 only
1595 * Params:
1596 * D3DMatHandle: Handle to destroy
1598 * Returns:
1599 * D3D_OK on success
1600 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1602 *****************************************************************************/
1603 static HRESULT WINAPI
1604 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1605 D3DMATRIXHANDLE D3DMatHandle)
1607 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1608 TRACE("(%p)->(%08x)\n", This, D3DMatHandle);
1610 if(!D3DMatHandle)
1611 return DDERR_INVALIDPARAMS;
1613 EnterCriticalSection(&ddraw_cs);
1614 if(D3DMatHandle > This->numHandles)
1616 ERR("Handle %d out of range\n", D3DMatHandle);
1617 LeaveCriticalSection(&ddraw_cs);
1618 return DDERR_INVALIDPARAMS;
1620 else if(This->Handles[D3DMatHandle - 1].type != DDrawHandle_Matrix)
1622 ERR("Handle %d is not a matrix handle\n", D3DMatHandle);
1623 LeaveCriticalSection(&ddraw_cs);
1624 return DDERR_INVALIDPARAMS;
1627 HeapFree(GetProcessHeap(), 0, This->Handles[D3DMatHandle - 1].ptr);
1628 This->Handles[D3DMatHandle - 1].ptr = NULL;
1629 This->Handles[D3DMatHandle - 1].type = DDrawHandle_Unknown;
1631 LeaveCriticalSection(&ddraw_cs);
1632 return D3D_OK;
1635 /*****************************************************************************
1636 * IDirect3DDevice7::BeginScene
1638 * This method must be called before any rendering is performed.
1639 * IDirect3DDevice::EndScene has to be called after the scene is complete
1641 * Version 1, 2, 3 and 7
1643 * Returns:
1644 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1645 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1646 * started scene).
1648 *****************************************************************************/
1649 static HRESULT
1650 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1652 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1653 HRESULT hr;
1654 TRACE("(%p): Relay\n", This);
1656 EnterCriticalSection(&ddraw_cs);
1657 hr = IWineD3DDevice_BeginScene(This->wineD3DDevice);
1658 LeaveCriticalSection(&ddraw_cs);
1659 if(hr == WINED3D_OK) return D3D_OK;
1660 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1663 static HRESULT WINAPI
1664 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1666 return IDirect3DDeviceImpl_7_BeginScene(iface);
1669 static HRESULT WINAPI
1670 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1672 HRESULT hr;
1673 WORD old_fpucw;
1675 old_fpucw = d3d_fpu_setup();
1676 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1677 set_fpu_control_word(old_fpucw);
1679 return hr;
1682 static HRESULT WINAPI
1683 Thunk_IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1685 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1686 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1687 return IDirect3DDevice7_BeginScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1690 static HRESULT WINAPI
1691 Thunk_IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1693 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1694 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1695 return IDirect3DDevice7_BeginScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1698 static HRESULT WINAPI
1699 Thunk_IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1701 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1702 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1703 return IDirect3DDevice7_BeginScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1706 /*****************************************************************************
1707 * IDirect3DDevice7::EndScene
1709 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1710 * This method must be called after rendering is finished.
1712 * Version 1, 2, 3 and 7
1714 * Returns:
1715 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1716 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1717 * that only if the scene was already ended.
1719 *****************************************************************************/
1720 static HRESULT
1721 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1723 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1724 HRESULT hr;
1725 TRACE("(%p): Relay\n", This);
1727 EnterCriticalSection(&ddraw_cs);
1728 hr = IWineD3DDevice_EndScene(This->wineD3DDevice);
1729 LeaveCriticalSection(&ddraw_cs);
1730 if(hr == WINED3D_OK) return D3D_OK;
1731 else return D3DERR_SCENE_NOT_IN_SCENE;
1734 static HRESULT WINAPI
1735 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1737 return IDirect3DDeviceImpl_7_EndScene(iface);
1740 static HRESULT WINAPI
1741 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1743 HRESULT hr;
1744 WORD old_fpucw;
1746 old_fpucw = d3d_fpu_setup();
1747 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1748 set_fpu_control_word(old_fpucw);
1750 return hr;
1753 static HRESULT WINAPI
1754 Thunk_IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1756 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1757 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1758 return IDirect3DDevice7_EndScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1761 static HRESULT WINAPI
1762 Thunk_IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1764 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1765 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1766 return IDirect3DDevice7_EndScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1769 static HRESULT WINAPI
1770 Thunk_IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1772 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1773 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1774 return IDirect3DDevice7_EndScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1777 /*****************************************************************************
1778 * IDirect3DDevice7::GetDirect3D
1780 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1781 * this device.
1783 * Params:
1784 * Direct3D7: Address to store the interface pointer at
1786 * Returns:
1787 * D3D_OK on success
1788 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1790 *****************************************************************************/
1791 static HRESULT WINAPI
1792 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1793 IDirect3D7 **Direct3D7)
1795 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1796 TRACE("(%p)->(%p)\n", This, Direct3D7);
1798 if(!Direct3D7)
1799 return DDERR_INVALIDPARAMS;
1801 *Direct3D7 = ICOM_INTERFACE(This->ddraw, IDirect3D7);
1802 IDirect3D7_AddRef(*Direct3D7);
1804 TRACE(" returning interface %p\n", *Direct3D7);
1805 return D3D_OK;
1808 static HRESULT WINAPI
1809 Thunk_IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1810 IDirect3D3 **Direct3D3)
1812 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1813 HRESULT ret;
1814 IDirect3D7 *ret_ptr;
1816 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Direct3D3);
1817 ret = IDirect3DDevice7_GetDirect3D(ICOM_INTERFACE(This, IDirect3DDevice7),
1818 &ret_ptr);
1819 if(ret != D3D_OK)
1820 return ret;
1821 *Direct3D3 = COM_INTERFACE_CAST(IDirectDrawImpl, IDirect3D7, IDirect3D3, ret_ptr);
1822 TRACE(" returning interface %p\n", *Direct3D3);
1823 return D3D_OK;
1826 static HRESULT WINAPI
1827 Thunk_IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1828 IDirect3D2 **Direct3D2)
1830 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1831 HRESULT ret;
1832 IDirect3D7 *ret_ptr;
1834 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Direct3D2);
1835 ret = IDirect3DDevice7_GetDirect3D(ICOM_INTERFACE(This, IDirect3DDevice7),
1836 &ret_ptr);
1837 if(ret != D3D_OK)
1838 return ret;
1839 *Direct3D2 = COM_INTERFACE_CAST(IDirectDrawImpl, IDirect3D7, IDirect3D2, ret_ptr);
1840 TRACE(" returning interface %p\n", *Direct3D2);
1841 return D3D_OK;
1844 static HRESULT WINAPI
1845 Thunk_IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1846 IDirect3D **Direct3D)
1848 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1849 HRESULT ret;
1850 IDirect3D7 *ret_ptr;
1852 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Direct3D);
1853 ret = IDirect3DDevice7_GetDirect3D(ICOM_INTERFACE(This, IDirect3DDevice7),
1854 &ret_ptr);
1855 if(ret != D3D_OK)
1856 return ret;
1857 *Direct3D = COM_INTERFACE_CAST(IDirectDrawImpl, IDirect3D7, IDirect3D, ret_ptr);
1858 TRACE(" returning interface %p\n", *Direct3D);
1859 return D3D_OK;
1862 /*****************************************************************************
1863 * IDirect3DDevice3::SetCurrentViewport
1865 * Sets a Direct3DViewport as the current viewport.
1866 * For the thunks note that all viewport interface versions are equal
1868 * Params:
1869 * Direct3DViewport3: The viewport to set
1871 * Version 2 and 3
1873 * Returns:
1874 * D3D_OK on success
1875 * (Is a NULL viewport valid?)
1877 *****************************************************************************/
1878 static HRESULT WINAPI
1879 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1880 IDirect3DViewport3 *Direct3DViewport3)
1882 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1883 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Direct3DViewport3);
1884 TRACE("(%p)->(%p)\n", This, Direct3DViewport3);
1886 EnterCriticalSection(&ddraw_cs);
1887 /* Do nothing if the specified viewport is the same as the current one */
1888 if (This->current_viewport == vp )
1890 LeaveCriticalSection(&ddraw_cs);
1891 return D3D_OK;
1894 /* Should check if the viewport was added or not */
1896 /* Release previous viewport and AddRef the new one */
1897 if (This->current_viewport)
1899 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport, ICOM_INTERFACE(This->current_viewport, IDirect3DViewport3));
1900 IDirect3DViewport3_Release( ICOM_INTERFACE(This->current_viewport, IDirect3DViewport3) );
1902 IDirect3DViewport3_AddRef(Direct3DViewport3);
1904 /* Set this viewport as the current viewport */
1905 This->current_viewport = vp;
1907 /* Activate this viewport */
1908 This->current_viewport->active_device = This;
1909 This->current_viewport->activate(This->current_viewport, FALSE);
1911 LeaveCriticalSection(&ddraw_cs);
1912 return D3D_OK;
1915 static HRESULT WINAPI
1916 Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1917 IDirect3DViewport2 *Direct3DViewport2)
1919 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1920 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Direct3DViewport2);
1921 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
1922 return IDirect3DDevice3_SetCurrentViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
1923 ICOM_INTERFACE(vp, IDirect3DViewport3));
1926 /*****************************************************************************
1927 * IDirect3DDevice3::GetCurrentViewport
1929 * Returns the currently active viewport.
1931 * Version 2 and 3
1933 * Params:
1934 * Direct3DViewport3: Address to return the interface pointer at
1936 * Returns:
1937 * D3D_OK on success
1938 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1940 *****************************************************************************/
1941 static HRESULT WINAPI
1942 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1943 IDirect3DViewport3 **Direct3DViewport3)
1945 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1946 TRACE("(%p)->(%p)\n", This, Direct3DViewport3);
1948 if(!Direct3DViewport3)
1949 return DDERR_INVALIDPARAMS;
1951 EnterCriticalSection(&ddraw_cs);
1952 *Direct3DViewport3 = ICOM_INTERFACE(This->current_viewport, IDirect3DViewport3);
1954 /* AddRef the returned viewport */
1955 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1957 TRACE(" returning interface %p\n", *Direct3DViewport3);
1959 LeaveCriticalSection(&ddraw_cs);
1960 return D3D_OK;
1963 static HRESULT WINAPI
1964 Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1965 IDirect3DViewport2 **Direct3DViewport2)
1967 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1968 HRESULT hr;
1969 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, Direct3DViewport2);
1970 hr = IDirect3DDevice3_GetCurrentViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
1971 (IDirect3DViewport3 **) Direct3DViewport2);
1972 if(hr != D3D_OK) return hr;
1973 *Direct3DViewport2 = (IDirect3DViewport2 *) COM_INTERFACE_CAST(IDirect3DViewportImpl, IDirect3DViewport3, IDirect3DViewport3, *Direct3DViewport2);
1974 return D3D_OK;
1977 /*****************************************************************************
1978 * IDirect3DDevice7::SetRenderTarget
1980 * Sets the render target for the Direct3DDevice.
1981 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1982 * IDirectDrawSurface3 == IDirectDrawSurface
1984 * Version 2, 3 and 7
1986 * Params:
1987 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1988 * render target
1989 * Flags: Some flags
1991 * Returns:
1992 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1994 *****************************************************************************/
1995 static HRESULT
1996 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1997 IDirectDrawSurface7 *NewTarget,
1998 DWORD Flags)
2000 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2001 IDirectDrawSurfaceImpl *Target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, NewTarget);
2002 HRESULT hr;
2003 TRACE("(%p)->(%p,%08x): Relay\n", This, NewTarget, Flags);
2005 EnterCriticalSection(&ddraw_cs);
2006 /* Flags: Not used */
2008 if(This->target == Target)
2010 TRACE("No-op SetRenderTarget operation, not doing anything\n");
2011 LeaveCriticalSection(&ddraw_cs);
2012 return D3D_OK;
2015 hr = IWineD3DDevice_SetRenderTarget(This->wineD3DDevice,
2017 Target ? Target->WineD3DSurface : NULL);
2018 if(hr != D3D_OK)
2020 LeaveCriticalSection(&ddraw_cs);
2021 return hr;
2023 IDirectDrawSurface7_AddRef(NewTarget);
2024 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->target, IDirectDrawSurface7));
2025 This->target = Target;
2026 IDirect3DDeviceImpl_UpdateDepthStencil(This);
2027 LeaveCriticalSection(&ddraw_cs);
2028 return D3D_OK;
2031 static HRESULT WINAPI
2032 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
2033 IDirectDrawSurface7 *NewTarget,
2034 DWORD Flags)
2036 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
2039 static HRESULT WINAPI
2040 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
2041 IDirectDrawSurface7 *NewTarget,
2042 DWORD Flags)
2044 HRESULT hr;
2045 WORD old_fpucw;
2047 old_fpucw = d3d_fpu_setup();
2048 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
2049 set_fpu_control_word(old_fpucw);
2051 return hr;
2054 static HRESULT WINAPI
2055 Thunk_IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
2056 IDirectDrawSurface4 *NewRenderTarget,
2057 DWORD Flags)
2059 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2060 IDirectDrawSurfaceImpl *Target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, NewRenderTarget);
2061 TRACE_(ddraw_thunk)("(%p)->(%p,%08x) thunking to IDirect3DDevice7 interface.\n", This, Target, Flags);
2062 return IDirect3DDevice7_SetRenderTarget(ICOM_INTERFACE(This, IDirect3DDevice7),
2063 ICOM_INTERFACE(Target, IDirectDrawSurface7),
2064 Flags);
2067 static HRESULT WINAPI
2068 Thunk_IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
2069 IDirectDrawSurface *NewRenderTarget,
2070 DWORD Flags)
2072 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2073 IDirectDrawSurfaceImpl *Target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface3, NewRenderTarget);
2074 TRACE_(ddraw_thunk)("(%p)->(%p,%08x) thunking to IDirect3DDevice7 interface.\n", This, Target, Flags);
2075 return IDirect3DDevice7_SetRenderTarget(ICOM_INTERFACE(This, IDirect3DDevice7),
2076 ICOM_INTERFACE(Target, IDirectDrawSurface7),
2077 Flags);
2080 /*****************************************************************************
2081 * IDirect3DDevice7::GetRenderTarget
2083 * Returns the current render target.
2084 * This is handled locally, because the WineD3D render target's parent
2085 * is an IParent
2087 * Version 2, 3 and 7
2089 * Params:
2090 * RenderTarget: Address to store the surface interface pointer
2092 * Returns:
2093 * D3D_OK on success
2094 * DDERR_INVALIDPARAMS if RenderTarget == NULL
2096 *****************************************************************************/
2097 static HRESULT WINAPI
2098 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
2099 IDirectDrawSurface7 **RenderTarget)
2101 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2102 TRACE("(%p)->(%p): Relay\n", This, RenderTarget);
2104 if(!RenderTarget)
2105 return DDERR_INVALIDPARAMS;
2107 EnterCriticalSection(&ddraw_cs);
2108 *RenderTarget = ICOM_INTERFACE(This->target, IDirectDrawSurface7);
2109 IDirectDrawSurface7_AddRef(*RenderTarget);
2111 LeaveCriticalSection(&ddraw_cs);
2112 return D3D_OK;
2115 static HRESULT WINAPI
2116 Thunk_IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
2117 IDirectDrawSurface4 **RenderTarget)
2119 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2120 HRESULT hr;
2121 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, RenderTarget);
2122 hr = IDirect3DDevice7_GetRenderTarget(ICOM_INTERFACE(This, IDirect3DDevice7),
2123 (IDirectDrawSurface7 **) RenderTarget);
2124 if(hr != D3D_OK) return hr;
2125 *RenderTarget = (IDirectDrawSurface4 *) COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirectDrawSurface7, IDirectDrawSurface7, *RenderTarget);
2126 return D3D_OK;
2129 static HRESULT WINAPI
2130 Thunk_IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
2131 IDirectDrawSurface **RenderTarget)
2133 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2134 HRESULT hr;
2135 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, RenderTarget);
2136 hr = IDirect3DDevice7_GetRenderTarget(ICOM_INTERFACE(This, IDirect3DDevice7),
2137 (IDirectDrawSurface7 **) RenderTarget);
2138 if(hr != D3D_OK) return hr;
2139 *RenderTarget = (IDirectDrawSurface *) COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirectDrawSurface7, IDirectDrawSurface3, *RenderTarget);
2140 return D3D_OK;
2143 /*****************************************************************************
2144 * IDirect3DDevice3::Begin
2146 * Begins a description block of vertices. This is similar to glBegin()
2147 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2148 * described with IDirect3DDevice::Vertex are drawn.
2150 * Version 2 and 3
2152 * Params:
2153 * PrimitiveType: The type of primitives to draw
2154 * VertexTypeDesc: A flexible vertex format description of the vertices
2155 * Flags: Some flags..
2157 * Returns:
2158 * D3D_OK on success
2160 *****************************************************************************/
2161 static HRESULT WINAPI
2162 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2163 D3DPRIMITIVETYPE PrimitiveType,
2164 DWORD VertexTypeDesc,
2165 DWORD Flags)
2167 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2168 TRACE("(%p)->(%d,%d,%08x)\n", This, PrimitiveType, VertexTypeDesc, Flags);
2170 EnterCriticalSection(&ddraw_cs);
2171 This->primitive_type = PrimitiveType;
2172 This->vertex_type = VertexTypeDesc;
2173 This->render_flags = Flags;
2174 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2175 This->nb_vertices = 0;
2176 LeaveCriticalSection(&ddraw_cs);
2178 return D3D_OK;
2181 static HRESULT WINAPI
2182 Thunk_IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface,
2183 D3DPRIMITIVETYPE d3dpt,
2184 D3DVERTEXTYPE dwVertexTypeDesc,
2185 DWORD dwFlags)
2187 DWORD FVF;
2188 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2189 TRACE_(ddraw_thunk)("(%p/%p)->(%08x,%08x,%08x): Thunking to IDirect3DDevice3\n", This, iface, d3dpt, dwVertexTypeDesc, dwFlags);
2191 switch(dwVertexTypeDesc)
2193 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2194 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2195 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2196 default:
2197 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2198 return DDERR_INVALIDPARAMS; /* Should never happen */
2201 return IDirect3DDevice3_Begin(ICOM_INTERFACE(This, IDirect3DDevice3),
2202 d3dpt,
2203 FVF,
2204 dwFlags);
2207 /*****************************************************************************
2208 * IDirect3DDevice3::BeginIndexed
2210 * Draws primitives based on vertices in a vertex array which are specified
2211 * by indices.
2213 * Version 2 and 3
2215 * Params:
2216 * PrimitiveType: Primitive type to draw
2217 * VertexType: A FVF description of the vertex format
2218 * Vertices: pointer to an array containing the vertices
2219 * NumVertices: The number of vertices in the vertex array
2220 * Flags: Some flags ...
2222 * Returns:
2223 * D3D_OK, because it's a stub
2225 *****************************************************************************/
2226 static HRESULT WINAPI
2227 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2228 D3DPRIMITIVETYPE PrimitiveType,
2229 DWORD VertexType,
2230 void *Vertices,
2231 DWORD NumVertices,
2232 DWORD Flags)
2234 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2235 FIXME("(%p)->(%08x,%08x,%p,%08x,%08x): stub!\n", This, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2236 return D3D_OK;
2240 static HRESULT WINAPI
2241 Thunk_IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2242 D3DPRIMITIVETYPE d3dptPrimitiveType,
2243 D3DVERTEXTYPE d3dvtVertexType,
2244 void *lpvVertices,
2245 DWORD dwNumVertices,
2246 DWORD dwFlags)
2248 DWORD FVF;
2249 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2250 TRACE_(ddraw_thunk)("(%p/%p)->(%08x,%08x,%p,%08x,%08x): Thunking to IDirect3DDevice3\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2252 switch(d3dvtVertexType)
2254 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2255 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2256 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2257 default:
2258 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2259 return DDERR_INVALIDPARAMS; /* Should never happen */
2262 return IDirect3DDevice3_BeginIndexed(ICOM_INTERFACE(This,IDirect3DDevice3),
2263 d3dptPrimitiveType,
2264 FVF,
2265 lpvVertices,
2266 dwNumVertices,
2267 dwFlags);
2270 /*****************************************************************************
2271 * IDirect3DDevice3::Vertex
2273 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2274 * drawn vertices in a vertex buffer. If the buffer is too small, its
2275 * size is increased.
2277 * Version 2 and 3
2279 * Params:
2280 * Vertex: Pointer to the vertex
2282 * Returns:
2283 * D3D_OK, on success
2284 * DDERR_INVALIDPARAMS if Vertex is NULL
2286 *****************************************************************************/
2287 static HRESULT WINAPI
2288 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2289 void *Vertex)
2291 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2292 TRACE("(%p)->(%p)\n", This, Vertex);
2294 if(!Vertex)
2295 return DDERR_INVALIDPARAMS;
2297 EnterCriticalSection(&ddraw_cs);
2298 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2300 BYTE *old_buffer;
2301 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2302 old_buffer = This->vertex_buffer;
2303 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2304 if (old_buffer)
2306 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2307 HeapFree(GetProcessHeap(), 0, old_buffer);
2311 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2313 LeaveCriticalSection(&ddraw_cs);
2314 return D3D_OK;
2317 static HRESULT WINAPI
2318 Thunk_IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface,
2319 void *lpVertexType)
2321 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2322 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, lpVertexType);
2323 return IDirect3DDevice3_Vertex(ICOM_INTERFACE(This, IDirect3DDevice3),
2324 lpVertexType);
2327 /*****************************************************************************
2328 * IDirect3DDevice3::Index
2330 * Specifies an index to a vertex to be drawn. The vertex array has to
2331 * be specified with BeginIndexed first.
2333 * Parameters:
2334 * VertexIndex: The index of the vertex to draw
2336 * Returns:
2337 * D3D_OK because it's a stub
2339 *****************************************************************************/
2340 static HRESULT WINAPI
2341 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2342 WORD VertexIndex)
2344 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2345 FIXME("(%p)->(%04x): stub!\n", This, VertexIndex);
2346 return D3D_OK;
2349 static HRESULT WINAPI
2350 Thunk_IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface,
2351 WORD wVertexIndex)
2353 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2354 TRACE_(ddraw_thunk)("(%p)->(%04x) thunking to IDirect3DDevice3 interface.\n", This, wVertexIndex);
2355 return IDirect3DDevice3_Index(ICOM_INTERFACE(This, IDirect3DDevice3),
2356 wVertexIndex);
2359 /*****************************************************************************
2360 * IDirect3DDevice3::End
2362 * Ends a draw begun with IDirect3DDevice3::Begin or
2363 * IDirect3DDevice::BeginIndexed. The vertices specified with
2364 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2365 * the IDirect3DDevice7::DrawPrimitive method. So far only
2366 * non-indexed mode is supported
2368 * Version 2 and 3
2370 * Params:
2371 * Flags: Some flags, as usual. Don't know which are defined
2373 * Returns:
2374 * The return value of IDirect3DDevice7::DrawPrimitive
2376 *****************************************************************************/
2377 static HRESULT WINAPI
2378 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2379 DWORD Flags)
2381 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2382 TRACE("(%p)->(%08x)\n", This, Flags);
2384 return IDirect3DDevice7_DrawPrimitive(ICOM_INTERFACE(This, IDirect3DDevice7),
2385 This->primitive_type, This->vertex_type,
2386 This->vertex_buffer, This->nb_vertices,
2387 This->render_flags);
2390 static HRESULT WINAPI
2391 Thunk_IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface,
2392 DWORD dwFlags)
2394 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2395 TRACE_(ddraw_thunk)("(%p)->(%08x) thunking to IDirect3DDevice3 interface.\n", This, dwFlags);
2396 return IDirect3DDevice3_End(ICOM_INTERFACE(This, IDirect3DDevice3),
2397 dwFlags);
2400 /*****************************************************************************
2401 * IDirect3DDevice7::GetRenderState
2403 * Returns the value of a render state. The possible render states are
2404 * defined in include/d3dtypes.h
2406 * Version 2, 3 and 7
2408 * Params:
2409 * RenderStateType: Render state to return the current setting of
2410 * Value: Address to store the value at
2412 * Returns:
2413 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2414 * DDERR_INVALIDPARAMS if Value == NULL
2416 *****************************************************************************/
2417 static HRESULT
2418 IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2419 D3DRENDERSTATETYPE RenderStateType,
2420 DWORD *Value)
2422 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2423 HRESULT hr;
2424 TRACE("(%p)->(%08x,%p): Relay\n", This, RenderStateType, Value);
2426 if(!Value)
2427 return DDERR_INVALIDPARAMS;
2429 EnterCriticalSection(&ddraw_cs);
2430 switch(RenderStateType)
2432 case D3DRENDERSTATE_TEXTUREMAG:
2434 WINED3DTEXTUREFILTERTYPE tex_mag;
2436 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2437 0, WINED3DSAMP_MAGFILTER,
2438 &tex_mag);
2440 switch (tex_mag)
2442 case WINED3DTEXF_POINT:
2443 *Value = D3DFILTER_NEAREST;
2444 break;
2445 case WINED3DTEXF_LINEAR:
2446 *Value = D3DFILTER_LINEAR;
2447 break;
2448 default:
2449 ERR("Unhandled texture mag %d !\n",tex_mag);
2450 *Value = 0;
2452 break;
2455 case D3DRENDERSTATE_TEXTUREMIN:
2457 WINED3DTEXTUREFILTERTYPE tex_min;
2459 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2460 0, WINED3DSAMP_MINFILTER,
2461 &tex_min);
2463 switch (tex_min)
2465 case WINED3DTEXF_POINT:
2466 *Value = D3DFILTER_NEAREST;
2467 break;
2468 case WINED3DTEXF_LINEAR:
2469 *Value = D3DFILTER_LINEAR;
2470 break;
2471 default:
2472 ERR("Unhandled texture mag %d !\n",tex_min);
2473 *Value = 0;
2475 break;
2478 case D3DRENDERSTATE_TEXTUREADDRESS:
2479 case D3DRENDERSTATE_TEXTUREADDRESSU:
2480 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2481 0, WINED3DSAMP_ADDRESSU,
2482 Value);
2483 break;
2484 case D3DRENDERSTATE_TEXTUREADDRESSV:
2485 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2486 0, WINED3DSAMP_ADDRESSV,
2487 Value);
2488 break;
2490 default:
2491 /* FIXME: Unhandled: D3DRENDERSTATE_STIPPLEPATTERN00 - 31 */
2492 hr = IWineD3DDevice_GetRenderState(This->wineD3DDevice,
2493 RenderStateType,
2494 Value);
2496 LeaveCriticalSection(&ddraw_cs);
2497 return hr;
2500 static HRESULT WINAPI
2501 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2502 D3DRENDERSTATETYPE RenderStateType,
2503 DWORD *Value)
2505 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2508 static HRESULT WINAPI
2509 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2510 D3DRENDERSTATETYPE RenderStateType,
2511 DWORD *Value)
2513 HRESULT hr;
2514 WORD old_fpucw;
2516 old_fpucw = d3d_fpu_setup();
2517 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2518 set_fpu_control_word(old_fpucw);
2520 return hr;
2523 static HRESULT WINAPI
2524 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2525 D3DRENDERSTATETYPE dwRenderStateType,
2526 DWORD *lpdwRenderState)
2528 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2529 HRESULT hr;
2530 TRACE("(%p)->(%08x,%p)\n", This, dwRenderStateType, lpdwRenderState);
2532 switch(dwRenderStateType)
2534 case D3DRENDERSTATE_TEXTUREHANDLE:
2536 /* This state is wrapped to SetTexture in SetRenderState, so
2537 * it has to be wrapped to GetTexture here
2539 IWineD3DBaseTexture *tex = NULL;
2540 *lpdwRenderState = 0;
2542 EnterCriticalSection(&ddraw_cs);
2544 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2546 &tex);
2548 if(hr == WINED3D_OK && tex)
2550 IDirectDrawSurface7 *parent = NULL;
2551 hr = IWineD3DBaseTexture_GetParent(tex,
2552 (IUnknown **) &parent);
2553 if(parent)
2555 /* The parent of the texture is the IDirectDrawSurface7 interface
2556 * of the ddraw surface
2558 IDirectDrawSurfaceImpl *texImpl = ICOM_OBJECT(IDirectDrawSurfaceImpl,
2559 IDirectDrawSurface7,
2560 parent);
2561 *lpdwRenderState = texImpl->Handle;
2562 IDirectDrawSurface7_Release(parent);
2564 IWineD3DBaseTexture_Release(tex);
2567 LeaveCriticalSection(&ddraw_cs);
2569 return hr;
2572 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2574 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2575 the mapping to get the value. */
2576 DWORD colorop, colorarg1, colorarg2;
2577 DWORD alphaop, alphaarg1, alphaarg2;
2579 EnterCriticalSection(&ddraw_cs);
2581 This->legacyTextureBlending = TRUE;
2583 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, &colorop);
2584 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, &colorarg1);
2585 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, &colorarg2);
2586 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, &alphaop);
2587 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2588 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2590 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2591 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2593 *lpdwRenderState = D3DTBLEND_DECAL;
2595 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2596 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2598 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2600 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2601 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2603 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2605 else
2607 HRESULT hr;
2608 BOOL tex_alpha = FALSE;
2609 IWineD3DBaseTexture *tex = NULL;
2610 WINED3DSURFACE_DESC desc;
2611 WINED3DFORMAT fmt;
2612 DDPIXELFORMAT ddfmt;
2614 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2616 &tex);
2618 if(hr == WINED3D_OK && tex)
2620 memset(&desc, 0, sizeof(desc));
2621 desc.Format = &fmt;
2622 hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2623 if (SUCCEEDED(hr))
2625 ddfmt.dwSize = sizeof(ddfmt);
2626 PixelFormat_WineD3DtoDD(&ddfmt, fmt);
2627 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2630 IWineD3DBaseTexture_Release(tex);
2633 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2634 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == (tex_alpha ? WINED3DTA_TEXTURE : 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(ICOM_INTERFACE(This, IDirect3DDevice7),
2649 dwRenderStateType,
2650 lpdwRenderState);
2654 static HRESULT WINAPI
2655 Thunk_IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2656 D3DRENDERSTATETYPE dwRenderStateType,
2657 DWORD *lpdwRenderState)
2659 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2660 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice3 interface.\n", This, dwRenderStateType, lpdwRenderState);
2661 return IDirect3DDevice3_GetRenderState(ICOM_INTERFACE(This, IDirect3DDevice3),
2662 dwRenderStateType,
2663 lpdwRenderState);
2666 /*****************************************************************************
2667 * IDirect3DDevice7::SetRenderState
2669 * Sets a render state. The possible render states are defined in
2670 * include/d3dtypes.h
2672 * Version 2, 3 and 7
2674 * Params:
2675 * RenderStateType: State to set
2676 * Value: Value to assign to that state
2678 * Returns:
2679 * D3D_OK on success,
2680 * for details see IWineD3DDevice::SetRenderState
2682 *****************************************************************************/
2683 static HRESULT
2684 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2685 D3DRENDERSTATETYPE RenderStateType,
2686 DWORD Value)
2688 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2689 HRESULT hr;
2690 TRACE("(%p)->(%08x,%d): Relay\n", This, RenderStateType, Value);
2692 EnterCriticalSection(&ddraw_cs);
2693 /* Some render states need special care */
2694 switch(RenderStateType)
2696 case D3DRENDERSTATE_TEXTUREMAG:
2698 WINED3DTEXTUREFILTERTYPE tex_mag = WINED3DTEXF_NONE;
2700 switch ((D3DTEXTUREFILTER) Value)
2702 case D3DFILTER_NEAREST:
2703 case D3DFILTER_LINEARMIPNEAREST:
2704 tex_mag = WINED3DTEXF_POINT;
2705 break;
2706 case D3DFILTER_LINEAR:
2707 case D3DFILTER_LINEARMIPLINEAR:
2708 tex_mag = WINED3DTEXF_LINEAR;
2709 break;
2710 default:
2711 ERR("Unhandled texture mag %d !\n",Value);
2714 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2715 0, WINED3DSAMP_MAGFILTER,
2716 tex_mag);
2717 break;
2720 case D3DRENDERSTATE_TEXTUREMIN:
2722 WINED3DTEXTUREFILTERTYPE tex_min = WINED3DTEXF_NONE;
2723 WINED3DTEXTUREFILTERTYPE tex_mip = WINED3DTEXF_NONE;
2725 switch ((D3DTEXTUREFILTER) Value)
2727 case D3DFILTER_NEAREST:
2728 tex_min = WINED3DTEXF_POINT;
2729 break;
2730 case D3DFILTER_LINEAR:
2731 tex_min = WINED3DTEXF_LINEAR;
2732 break;
2733 case D3DFILTER_MIPNEAREST:
2734 tex_min = WINED3DTEXF_NONE;
2735 tex_mip = WINED3DTEXF_POINT;
2736 break;
2737 case D3DFILTER_MIPLINEAR:
2738 tex_min = WINED3DTEXF_NONE;
2739 tex_mip = WINED3DTEXF_LINEAR;
2740 break;
2741 case D3DFILTER_LINEARMIPNEAREST:
2742 tex_min = WINED3DTEXF_POINT;
2743 tex_mip = WINED3DTEXF_LINEAR;
2744 break;
2745 case D3DFILTER_LINEARMIPLINEAR:
2746 tex_min = WINED3DTEXF_LINEAR;
2747 tex_mip = WINED3DTEXF_LINEAR;
2748 break;
2750 default:
2751 ERR("Unhandled texture min %d !\n",Value);
2754 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2755 0, WINED3DSAMP_MIPFILTER,
2756 tex_mip);
2757 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2758 0, WINED3DSAMP_MINFILTER,
2759 tex_min);
2760 break;
2763 case D3DRENDERSTATE_TEXTUREADDRESS:
2764 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2765 0, WINED3DSAMP_ADDRESSV,
2766 Value);
2767 /* Drop through */
2768 case D3DRENDERSTATE_TEXTUREADDRESSU:
2769 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2770 0, WINED3DSAMP_ADDRESSU,
2771 Value);
2772 break;
2773 case D3DRENDERSTATE_TEXTUREADDRESSV:
2774 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2775 0, WINED3DSAMP_ADDRESSV,
2776 Value);
2777 break;
2779 default:
2781 /* FIXME: Unhandled: D3DRENDERSTATE_STIPPLEPATTERN00 - 31 */
2783 hr = IWineD3DDevice_SetRenderState(This->wineD3DDevice,
2784 RenderStateType,
2785 Value);
2786 break;
2788 LeaveCriticalSection(&ddraw_cs);
2789 return hr;
2792 static HRESULT WINAPI
2793 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2794 D3DRENDERSTATETYPE RenderStateType,
2795 DWORD Value)
2797 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2800 static HRESULT WINAPI
2801 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2802 D3DRENDERSTATETYPE RenderStateType,
2803 DWORD Value)
2805 HRESULT hr;
2806 WORD old_fpucw;
2808 old_fpucw = d3d_fpu_setup();
2809 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2810 set_fpu_control_word(old_fpucw);
2812 return hr;
2815 static HRESULT WINAPI
2816 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2817 D3DRENDERSTATETYPE RenderStateType,
2818 DWORD Value)
2820 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2821 for this state can be directly mapped to texture stage colorop and alphaop, but
2822 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2823 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2824 alphaarg when needed.
2826 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2828 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2829 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2830 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2831 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2832 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2833 in device - TRUE if the app is using TEXTUREMAPBLEND.
2835 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2836 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2837 unless some broken game will be found that cares. */
2839 HRESULT hr;
2840 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2841 TRACE("(%p)->(%08x,%d)\n", This, RenderStateType, Value);
2843 EnterCriticalSection(&ddraw_cs);
2845 switch(RenderStateType)
2847 case D3DRENDERSTATE_TEXTUREHANDLE:
2849 if(Value == 0)
2851 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
2853 NULL);
2854 break;
2857 if(Value > This->numHandles)
2859 FIXME("Specified handle %d out of range\n", Value);
2860 hr = DDERR_INVALIDPARAMS;
2861 break;
2863 if(This->Handles[Value - 1].type != DDrawHandle_Texture)
2865 FIXME("Handle %d isn't a texture handle\n", Value);
2866 hr = DDERR_INVALIDPARAMS;
2867 break;
2869 else
2871 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *) This->Handles[Value - 1].ptr;
2872 hr = IDirect3DDevice3_SetTexture(iface, 0, ICOM_INTERFACE(surf, IDirect3DTexture2));
2873 break;
2877 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2879 This->legacyTextureBlending = TRUE;
2881 switch ( (D3DTEXTUREBLEND) Value)
2883 case D3DTBLEND_MODULATE:
2885 BOOL tex_alpha = FALSE;
2886 IWineD3DBaseTexture *tex = NULL;
2887 WINED3DSURFACE_DESC desc;
2888 WINED3DFORMAT fmt;
2889 DDPIXELFORMAT ddfmt;
2891 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2893 &tex);
2895 if(hr == WINED3D_OK && tex)
2897 memset(&desc, 0, sizeof(desc));
2898 desc.Format = &fmt;
2899 hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2900 if (SUCCEEDED(hr))
2902 ddfmt.dwSize = sizeof(ddfmt);
2903 PixelFormat_WineD3DtoDD(&ddfmt, fmt);
2904 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2907 IWineD3DBaseTexture_Release(tex);
2910 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2911 if (tex_alpha)
2913 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2915 else
2917 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_CURRENT);
2920 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2921 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2922 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2924 break;
2927 case D3DTBLEND_ADD:
2928 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2929 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2930 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2931 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2932 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2933 break;
2935 case D3DTBLEND_MODULATEALPHA:
2936 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2937 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2938 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2939 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2940 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2941 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2942 break;
2944 case D3DTBLEND_COPY:
2945 case D3DTBLEND_DECAL:
2946 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2947 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2948 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2949 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2950 break;
2952 case D3DTBLEND_DECALALPHA:
2953 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2954 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2955 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2956 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2957 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2958 break;
2960 default:
2961 ERR("Unhandled texture environment %d !\n",Value);
2964 hr = D3D_OK;
2965 break;
2968 default:
2969 hr = IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
2970 RenderStateType,
2971 Value);
2972 break;
2975 LeaveCriticalSection(&ddraw_cs);
2977 return hr;
2980 static HRESULT WINAPI
2981 Thunk_IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2982 D3DRENDERSTATETYPE RenderStateType,
2983 DWORD Value)
2985 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2986 TRACE_(ddraw_thunk)("(%p)->(%08x,%d) thunking to IDirect3DDevice3 interface.\n", This, RenderStateType, Value);
2987 return IDirect3DDevice3_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice3), RenderStateType, Value);
2990 /*****************************************************************************
2991 * Direct3DDevice3::SetLightState
2993 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2994 * light states are forwarded to Direct3DDevice7 render states
2996 * Version 2 and 3
2998 * Params:
2999 * LightStateType: The light state to change
3000 * Value: The value to assign to that light state
3002 * Returns:
3003 * D3D_OK on success
3004 * DDERR_INVALIDPARAMS if the parameters were incorrect
3005 * Also check IDirect3DDevice7::SetRenderState
3007 *****************************************************************************/
3008 static HRESULT WINAPI
3009 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
3010 D3DLIGHTSTATETYPE LightStateType,
3011 DWORD Value)
3013 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3014 HRESULT hr;
3016 TRACE("(%p)->(%08x,%08x)\n", This, LightStateType, Value);
3018 if (!LightStateType && (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3020 TRACE("Unexpected Light State Type\n");
3021 return DDERR_INVALIDPARAMS;
3024 EnterCriticalSection(&ddraw_cs);
3025 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3027 IDirect3DMaterialImpl *mat;
3029 if(Value == 0) mat = NULL;
3030 else if(Value > This->numHandles)
3032 ERR("Material handle out of range(%d)\n", Value);
3033 LeaveCriticalSection(&ddraw_cs);
3034 return DDERR_INVALIDPARAMS;
3036 else if(This->Handles[Value - 1].type != DDrawHandle_Material)
3038 ERR("Invalid handle %d\n", Value);
3039 LeaveCriticalSection(&ddraw_cs);
3040 return DDERR_INVALIDPARAMS;
3042 else
3044 mat = (IDirect3DMaterialImpl *) This->Handles[Value - 1].ptr;
3047 if (mat != NULL)
3049 TRACE(" activating material %p.\n", mat);
3050 mat->activate(mat);
3052 else
3054 FIXME(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
3056 This->material = Value;
3058 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3060 switch (Value)
3062 case D3DCOLOR_MONO:
3063 ERR("DDCOLOR_MONO should not happen!\n");
3064 break;
3065 case D3DCOLOR_RGB:
3066 /* We are already in this mode */
3067 TRACE("Setting color model to RGB (no-op).\n");
3068 break;
3069 default:
3070 ERR("Unknown color model!\n");
3071 LeaveCriticalSection(&ddraw_cs);
3072 return DDERR_INVALIDPARAMS;
3075 else
3077 D3DRENDERSTATETYPE rs;
3078 switch (LightStateType)
3080 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3081 rs = D3DRENDERSTATE_AMBIENT;
3082 break;
3083 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3084 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3085 break;
3086 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3087 rs = D3DRENDERSTATE_FOGSTART;
3088 break;
3089 case D3DLIGHTSTATE_FOGEND: /* 6 */
3090 rs = D3DRENDERSTATE_FOGEND;
3091 break;
3092 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3093 rs = D3DRENDERSTATE_FOGDENSITY;
3094 break;
3095 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3096 rs = D3DRENDERSTATE_COLORVERTEX;
3097 break;
3098 default:
3099 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3100 LeaveCriticalSection(&ddraw_cs);
3101 return DDERR_INVALIDPARAMS;
3104 hr = IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
3106 Value);
3107 LeaveCriticalSection(&ddraw_cs);
3108 return hr;
3111 LeaveCriticalSection(&ddraw_cs);
3112 return D3D_OK;
3115 static HRESULT WINAPI
3116 Thunk_IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3117 D3DLIGHTSTATETYPE LightStateType,
3118 DWORD Value)
3120 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3121 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x) thunking to IDirect3DDevice3 interface.\n", This, LightStateType, Value);
3122 return IDirect3DDevice3_SetLightState(ICOM_INTERFACE(This, IDirect3DDevice3),
3123 LightStateType,
3124 Value);
3127 /*****************************************************************************
3128 * IDirect3DDevice3::GetLightState
3130 * Returns the current setting of a light state. The state is read from
3131 * the Direct3DDevice7 render state.
3133 * Version 2 and 3
3135 * Params:
3136 * LightStateType: The light state to return
3137 * Value: The address to store the light state setting at
3139 * Returns:
3140 * D3D_OK on success
3141 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3142 * Also see IDirect3DDevice7::GetRenderState
3144 *****************************************************************************/
3145 static HRESULT WINAPI
3146 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3147 D3DLIGHTSTATETYPE LightStateType,
3148 DWORD *Value)
3150 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3151 HRESULT hr;
3153 TRACE("(%p)->(%08x,%p)\n", This, LightStateType, Value);
3155 if (!LightStateType && (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3157 TRACE("Unexpected Light State Type\n");
3158 return DDERR_INVALIDPARAMS;
3161 if(!Value)
3162 return DDERR_INVALIDPARAMS;
3164 EnterCriticalSection(&ddraw_cs);
3165 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3167 *Value = This->material;
3169 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3171 *Value = D3DCOLOR_RGB;
3173 else
3175 D3DRENDERSTATETYPE rs;
3176 switch (LightStateType)
3178 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3179 rs = D3DRENDERSTATE_AMBIENT;
3180 break;
3181 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3182 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3183 break;
3184 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3185 rs = D3DRENDERSTATE_FOGSTART;
3186 break;
3187 case D3DLIGHTSTATE_FOGEND: /* 6 */
3188 rs = D3DRENDERSTATE_FOGEND;
3189 break;
3190 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3191 rs = D3DRENDERSTATE_FOGDENSITY;
3192 break;
3193 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3194 rs = D3DRENDERSTATE_COLORVERTEX;
3195 break;
3196 default:
3197 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3198 LeaveCriticalSection(&ddraw_cs);
3199 return DDERR_INVALIDPARAMS;
3202 hr = IDirect3DDevice7_GetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
3204 Value);
3205 LeaveCriticalSection(&ddraw_cs);
3206 return hr;
3209 LeaveCriticalSection(&ddraw_cs);
3210 return D3D_OK;
3213 static HRESULT WINAPI
3214 Thunk_IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3215 D3DLIGHTSTATETYPE LightStateType,
3216 DWORD *Value)
3218 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3219 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice3 interface.\n", This, LightStateType, Value);
3220 return IDirect3DDevice3_GetLightState(ICOM_INTERFACE(This, IDirect3DDevice3),
3221 LightStateType,
3222 Value);
3225 /*****************************************************************************
3226 * IDirect3DDevice7::SetTransform
3228 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3229 * in include/d3dtypes.h.
3230 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3231 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3232 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3234 * Version 2, 3 and 7
3236 * Params:
3237 * TransformStateType: transform state to set
3238 * Matrix: Matrix to assign to the state
3240 * Returns:
3241 * D3D_OK on success
3242 * DDERR_INVALIDPARAMS if Matrix == NULL
3243 * For details see IWineD3DDevice::SetTransform
3245 *****************************************************************************/
3246 static HRESULT
3247 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3248 D3DTRANSFORMSTATETYPE TransformStateType,
3249 D3DMATRIX *Matrix)
3251 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3252 D3DTRANSFORMSTATETYPE type;
3253 HRESULT hr;
3254 TRACE("(%p)->(%08x,%p): Relay\n", This, TransformStateType, Matrix);
3256 switch(TransformStateType)
3258 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3259 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3260 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3261 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3262 default: type = TransformStateType;
3265 if(!Matrix)
3266 return DDERR_INVALIDPARAMS;
3268 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3269 EnterCriticalSection(&ddraw_cs);
3270 hr = IWineD3DDevice_SetTransform(This->wineD3DDevice,
3271 type,
3272 (WINED3DMATRIX*) Matrix);
3273 LeaveCriticalSection(&ddraw_cs);
3274 return hr;
3277 static HRESULT WINAPI
3278 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3279 D3DTRANSFORMSTATETYPE TransformStateType,
3280 D3DMATRIX *Matrix)
3282 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3285 static HRESULT WINAPI
3286 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3287 D3DTRANSFORMSTATETYPE TransformStateType,
3288 D3DMATRIX *Matrix)
3290 HRESULT hr;
3291 WORD old_fpucw;
3293 old_fpucw = d3d_fpu_setup();
3294 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3295 set_fpu_control_word(old_fpucw);
3297 return hr;
3300 static HRESULT WINAPI
3301 Thunk_IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3302 D3DTRANSFORMSTATETYPE TransformStateType,
3303 D3DMATRIX *D3DMatrix)
3305 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3306 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3307 return IDirect3DDevice7_SetTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
3308 TransformStateType,
3309 D3DMatrix);
3312 static HRESULT WINAPI
3313 Thunk_IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3314 D3DTRANSFORMSTATETYPE TransformStateType,
3315 D3DMATRIX *D3DMatrix)
3317 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3318 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3319 return IDirect3DDevice7_SetTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
3320 TransformStateType,
3321 D3DMatrix);
3324 /*****************************************************************************
3325 * IDirect3DDevice7::GetTransform
3327 * Returns the matrix assigned to a transform state
3328 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3329 * SetTransform
3331 * Params:
3332 * TransformStateType: State to read the matrix from
3333 * Matrix: Address to store the matrix at
3335 * Returns:
3336 * D3D_OK on success
3337 * DDERR_INVALIDPARAMS if Matrix == NULL
3338 * For details, see IWineD3DDevice::GetTransform
3340 *****************************************************************************/
3341 static HRESULT
3342 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3343 D3DTRANSFORMSTATETYPE TransformStateType,
3344 D3DMATRIX *Matrix)
3346 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3347 D3DTRANSFORMSTATETYPE type;
3348 HRESULT hr;
3349 TRACE("(%p)->(%08x,%p): Relay\n", This, TransformStateType, Matrix);
3351 switch(TransformStateType)
3353 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3354 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3355 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3356 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3357 default: type = TransformStateType;
3360 if(!Matrix)
3361 return DDERR_INVALIDPARAMS;
3363 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3364 EnterCriticalSection(&ddraw_cs);
3365 hr = IWineD3DDevice_GetTransform(This->wineD3DDevice, type, (WINED3DMATRIX*) Matrix);
3366 LeaveCriticalSection(&ddraw_cs);
3367 return hr;
3370 static HRESULT WINAPI
3371 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3372 D3DTRANSFORMSTATETYPE TransformStateType,
3373 D3DMATRIX *Matrix)
3375 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3378 static HRESULT WINAPI
3379 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3380 D3DTRANSFORMSTATETYPE TransformStateType,
3381 D3DMATRIX *Matrix)
3383 HRESULT hr;
3384 WORD old_fpucw;
3386 old_fpucw = d3d_fpu_setup();
3387 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3388 set_fpu_control_word(old_fpucw);
3390 return hr;
3393 static HRESULT WINAPI
3394 Thunk_IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3395 D3DTRANSFORMSTATETYPE TransformStateType,
3396 D3DMATRIX *D3DMatrix)
3398 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3399 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3400 return IDirect3DDevice7_GetTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
3401 TransformStateType,
3402 D3DMatrix);
3405 static HRESULT WINAPI
3406 Thunk_IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3407 D3DTRANSFORMSTATETYPE TransformStateType,
3408 D3DMATRIX *D3DMatrix)
3410 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3411 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3412 return IDirect3DDevice7_GetTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
3413 TransformStateType,
3414 D3DMatrix);
3417 /*****************************************************************************
3418 * IDirect3DDevice7::MultiplyTransform
3420 * Multiplies the already-set transform matrix of a transform state
3421 * with another matrix. For the world matrix, see SetTransform
3423 * Version 2, 3 and 7
3425 * Params:
3426 * TransformStateType: Transform state to multiply
3427 * D3DMatrix Matrix to multiply with.
3429 * Returns
3430 * D3D_OK on success
3431 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3432 * For details, see IWineD3DDevice::MultiplyTransform
3434 *****************************************************************************/
3435 static HRESULT
3436 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3437 D3DTRANSFORMSTATETYPE TransformStateType,
3438 D3DMATRIX *D3DMatrix)
3440 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3441 HRESULT hr;
3442 D3DTRANSFORMSTATETYPE type;
3443 TRACE("(%p)->(%08x,%p): Relay\n", This, TransformStateType, D3DMatrix);
3445 switch(TransformStateType)
3447 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3448 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3449 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3450 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3451 default: type = TransformStateType;
3454 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3455 EnterCriticalSection(&ddraw_cs);
3456 hr = IWineD3DDevice_MultiplyTransform(This->wineD3DDevice,
3457 type,
3458 (WINED3DMATRIX*) D3DMatrix);
3459 LeaveCriticalSection(&ddraw_cs);
3460 return hr;
3463 static HRESULT WINAPI
3464 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3465 D3DTRANSFORMSTATETYPE TransformStateType,
3466 D3DMATRIX *D3DMatrix)
3468 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3471 static HRESULT WINAPI
3472 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3473 D3DTRANSFORMSTATETYPE TransformStateType,
3474 D3DMATRIX *D3DMatrix)
3476 HRESULT hr;
3477 WORD old_fpucw;
3479 old_fpucw = d3d_fpu_setup();
3480 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3481 set_fpu_control_word(old_fpucw);
3483 return hr;
3486 static HRESULT WINAPI
3487 Thunk_IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3488 D3DTRANSFORMSTATETYPE TransformStateType,
3489 D3DMATRIX *D3DMatrix)
3491 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3492 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3493 return IDirect3DDevice7_MultiplyTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
3494 TransformStateType,
3495 D3DMatrix);
3498 static HRESULT WINAPI
3499 Thunk_IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3500 D3DTRANSFORMSTATETYPE TransformStateType,
3501 D3DMATRIX *D3DMatrix)
3503 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3504 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3505 return IDirect3DDevice7_MultiplyTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
3506 TransformStateType,
3507 D3DMatrix);
3510 /*****************************************************************************
3511 * IDirect3DDevice7::DrawPrimitive
3513 * Draws primitives based on vertices in an application-provided pointer
3515 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3516 * an FVF format for D3D7
3518 * Params:
3519 * PrimitiveType: The type of the primitives to draw
3520 * Vertex type: Flexible vertex format vertex description
3521 * Vertices: Pointer to the vertex array
3522 * VertexCount: The number of vertices to draw
3523 * Flags: As usual a few flags
3525 * Returns:
3526 * D3D_OK on success
3527 * DDERR_INVALIDPARAMS if Vertices is NULL
3528 * For details, see IWineD3DDevice::DrawPrimitiveUP
3530 *****************************************************************************/
3531 static HRESULT
3532 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3533 D3DPRIMITIVETYPE PrimitiveType,
3534 DWORD VertexType,
3535 void *Vertices,
3536 DWORD VertexCount,
3537 DWORD Flags)
3539 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3540 UINT PrimitiveCount, stride;
3541 HRESULT hr;
3542 TRACE("(%p)->(%08x,%08x,%p,%08x,%08x): Relay!\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3544 if(!Vertices)
3545 return DDERR_INVALIDPARAMS;
3547 /* Get the vertex count */
3548 switch(PrimitiveType)
3550 case D3DPT_POINTLIST:
3551 PrimitiveCount = VertexCount;
3552 break;
3554 case D3DPT_LINELIST:
3555 PrimitiveCount = VertexCount / 2;
3556 break;
3558 case D3DPT_LINESTRIP:
3559 PrimitiveCount = VertexCount - 1;
3560 break;
3562 case D3DPT_TRIANGLELIST:
3563 PrimitiveCount = VertexCount / 3;
3564 break;
3566 case D3DPT_TRIANGLESTRIP:
3567 PrimitiveCount = VertexCount - 2;
3568 break;
3570 case D3DPT_TRIANGLEFAN:
3571 PrimitiveCount = VertexCount - 2;
3572 break;
3574 default:
3575 return DDERR_INVALIDPARAMS;
3578 /* Get the stride */
3579 stride = get_flexible_vertex_size(VertexType);
3581 /* Set the FVF */
3582 EnterCriticalSection(&ddraw_cs);
3583 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
3584 IDirectDrawImpl_FindDecl(This->ddraw, VertexType));
3585 if(hr != D3D_OK)
3587 LeaveCriticalSection(&ddraw_cs);
3588 return hr;
3591 /* This method translates to the user pointer draw of WineD3D */
3592 hr = IWineD3DDevice_DrawPrimitiveUP(This->wineD3DDevice,
3593 PrimitiveType,
3594 PrimitiveCount,
3595 Vertices,
3596 stride);
3597 LeaveCriticalSection(&ddraw_cs);
3598 return hr;
3601 static HRESULT WINAPI
3602 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3603 D3DPRIMITIVETYPE PrimitiveType,
3604 DWORD VertexType,
3605 void *Vertices,
3606 DWORD VertexCount,
3607 DWORD Flags)
3609 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3612 static HRESULT WINAPI
3613 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3614 D3DPRIMITIVETYPE PrimitiveType,
3615 DWORD VertexType,
3616 void *Vertices,
3617 DWORD VertexCount,
3618 DWORD Flags)
3620 HRESULT hr;
3621 WORD old_fpucw;
3623 old_fpucw = d3d_fpu_setup();
3624 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3625 set_fpu_control_word(old_fpucw);
3627 return hr;
3630 static HRESULT WINAPI
3631 Thunk_IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3632 D3DPRIMITIVETYPE PrimitiveType,
3633 DWORD VertexType,
3634 void *Vertices,
3635 DWORD VertexCount,
3636 DWORD Flags)
3638 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3639 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3640 return IDirect3DDevice7_DrawPrimitive(ICOM_INTERFACE(This, IDirect3DDevice7),
3641 PrimitiveType,
3642 VertexType,
3643 Vertices,
3644 VertexCount,
3645 Flags);
3648 static HRESULT WINAPI
3649 Thunk_IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3650 D3DPRIMITIVETYPE PrimitiveType,
3651 D3DVERTEXTYPE VertexType,
3652 void *Vertices,
3653 DWORD VertexCount,
3654 DWORD Flags)
3656 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3657 DWORD FVF;
3658 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3660 switch(VertexType)
3662 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3663 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3664 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3665 default:
3666 ERR("Unexpected vertex type %d\n", VertexType);
3667 return DDERR_INVALIDPARAMS; /* Should never happen */
3670 return IDirect3DDevice7_DrawPrimitive(ICOM_INTERFACE(This, IDirect3DDevice7),
3671 PrimitiveType,
3672 FVF,
3673 Vertices,
3674 VertexCount,
3675 Flags);
3678 /*****************************************************************************
3679 * IDirect3DDevice7::DrawIndexedPrimitive
3681 * Draws vertices from an application-provided pointer, based on the index
3682 * numbers in a WORD array.
3684 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3685 * an FVF format for D3D7
3687 * Params:
3688 * PrimitiveType: The primitive type to draw
3689 * VertexType: The FVF vertex description
3690 * Vertices: Pointer to the vertex array
3691 * VertexCount: ?
3692 * Indices: Pointer to the index array
3693 * IndexCount: Number of indices = Number of vertices to draw
3694 * Flags: As usual, some flags
3696 * Returns:
3697 * D3D_OK on success
3698 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3699 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3701 *****************************************************************************/
3702 static HRESULT
3703 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3704 D3DPRIMITIVETYPE PrimitiveType,
3705 DWORD VertexType,
3706 void *Vertices,
3707 DWORD VertexCount,
3708 WORD *Indices,
3709 DWORD IndexCount,
3710 DWORD Flags)
3712 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3713 UINT PrimitiveCount = 0;
3714 HRESULT hr;
3715 TRACE("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x): Relay!\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3717 /* Get the primitive number */
3718 switch(PrimitiveType)
3720 case D3DPT_POINTLIST:
3721 PrimitiveCount = IndexCount;
3722 break;
3724 case D3DPT_LINELIST:
3725 PrimitiveCount = IndexCount / 2;
3726 break;
3728 case D3DPT_LINESTRIP:
3729 PrimitiveCount = IndexCount - 1;
3730 break;
3732 case D3DPT_TRIANGLELIST:
3733 PrimitiveCount = IndexCount / 3;
3734 break;
3736 case D3DPT_TRIANGLESTRIP:
3737 PrimitiveCount = IndexCount - 2;
3738 break;
3740 case D3DPT_TRIANGLEFAN:
3741 PrimitiveCount = IndexCount - 2;
3742 break;
3744 default:
3745 return DDERR_INVALIDPARAMS;
3748 /* Set the D3DDevice's FVF */
3749 EnterCriticalSection(&ddraw_cs);
3750 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
3751 IDirectDrawImpl_FindDecl(This->ddraw, VertexType));
3752 if(FAILED(hr))
3754 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3755 LeaveCriticalSection(&ddraw_cs);
3756 return hr;
3759 hr = IWineD3DDevice_DrawIndexedPrimitiveUP(This->wineD3DDevice,
3760 PrimitiveType,
3761 0 /* MinVertexIndex */,
3762 VertexCount /* UINT NumVertexIndex */,
3763 PrimitiveCount,
3764 Indices,
3765 WINED3DFMT_INDEX16,
3766 Vertices,
3767 get_flexible_vertex_size(VertexType));
3768 LeaveCriticalSection(&ddraw_cs);
3769 return hr;
3772 static HRESULT WINAPI
3773 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3774 D3DPRIMITIVETYPE PrimitiveType,
3775 DWORD VertexType,
3776 void *Vertices,
3777 DWORD VertexCount,
3778 WORD *Indices,
3779 DWORD IndexCount,
3780 DWORD Flags)
3782 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3785 static HRESULT WINAPI
3786 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3787 D3DPRIMITIVETYPE PrimitiveType,
3788 DWORD VertexType,
3789 void *Vertices,
3790 DWORD VertexCount,
3791 WORD *Indices,
3792 DWORD IndexCount,
3793 DWORD Flags)
3795 HRESULT hr;
3796 WORD old_fpucw;
3798 old_fpucw = d3d_fpu_setup();
3799 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3800 set_fpu_control_word(old_fpucw);
3802 return hr;
3805 static HRESULT WINAPI
3806 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3807 D3DPRIMITIVETYPE PrimitiveType,
3808 DWORD VertexType,
3809 void *Vertices,
3810 DWORD VertexCount,
3811 WORD *Indices,
3812 DWORD IndexCount,
3813 DWORD Flags)
3815 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3816 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3817 return IDirect3DDevice7_DrawIndexedPrimitive(ICOM_INTERFACE(This, IDirect3DDevice7),
3818 PrimitiveType,
3819 VertexType,
3820 Vertices,
3821 VertexCount,
3822 Indices,
3823 IndexCount,
3824 Flags);
3827 static HRESULT WINAPI
3828 Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3829 D3DPRIMITIVETYPE PrimitiveType,
3830 D3DVERTEXTYPE VertexType,
3831 void *Vertices,
3832 DWORD VertexCount,
3833 WORD *Indices,
3834 DWORD IndexCount,
3835 DWORD Flags)
3837 DWORD FVF;
3838 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3839 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3841 switch(VertexType)
3843 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3844 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3845 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3846 default:
3847 ERR("Unexpected vertex type %d\n", VertexType);
3848 return DDERR_INVALIDPARAMS; /* Should never happen */
3851 return IDirect3DDevice7_DrawIndexedPrimitive(ICOM_INTERFACE(This, IDirect3DDevice7),
3852 PrimitiveType,
3853 FVF,
3854 Vertices,
3855 VertexCount,
3856 Indices,
3857 IndexCount,
3858 Flags);
3861 /*****************************************************************************
3862 * IDirect3DDevice7::SetClipStatus
3864 * Sets the clip status. This defines things as clipping conditions and
3865 * the extents of the clipping region.
3867 * Version 2, 3 and 7
3869 * Params:
3870 * ClipStatus:
3872 * Returns:
3873 * D3D_OK because it's a stub
3874 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3876 *****************************************************************************/
3877 static HRESULT WINAPI
3878 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3879 D3DCLIPSTATUS *ClipStatus)
3881 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3882 FIXME("(%p)->(%p): Stub!\n", This, ClipStatus);
3884 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3885 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3887 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3888 return D3D_OK;
3891 static HRESULT WINAPI
3892 Thunk_IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3893 D3DCLIPSTATUS *ClipStatus)
3895 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3896 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3897 return IDirect3DDevice7_SetClipStatus(ICOM_INTERFACE(This, IDirect3DDevice7),
3898 ClipStatus);
3901 static HRESULT WINAPI
3902 Thunk_IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3903 D3DCLIPSTATUS *ClipStatus)
3905 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3906 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3907 return IDirect3DDevice7_SetClipStatus(ICOM_INTERFACE(This, IDirect3DDevice7),
3908 ClipStatus);
3911 /*****************************************************************************
3912 * IDirect3DDevice7::GetClipStatus
3914 * Returns the clip status
3916 * Params:
3917 * ClipStatus: Address to write the clip status to
3919 * Returns:
3920 * D3D_OK because it's a stub
3922 *****************************************************************************/
3923 static HRESULT WINAPI
3924 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3925 D3DCLIPSTATUS *ClipStatus)
3927 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3928 FIXME("(%p)->(%p): Stub!\n", This, ClipStatus);
3930 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3931 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3932 return D3D_OK;
3935 static HRESULT WINAPI
3936 Thunk_IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3937 D3DCLIPSTATUS *ClipStatus)
3939 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3940 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3941 return IDirect3DDevice7_GetClipStatus(ICOM_INTERFACE(This, IDirect3DDevice7),
3942 ClipStatus);
3945 static HRESULT WINAPI
3946 Thunk_IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3947 D3DCLIPSTATUS *ClipStatus)
3949 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3950 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3951 return IDirect3DDevice7_GetClipStatus(ICOM_INTERFACE(This, IDirect3DDevice7),
3952 ClipStatus);
3955 /*****************************************************************************
3956 * IDirect3DDevice::DrawPrimitiveStrided
3958 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3960 * Version 3 and 7
3962 * Params:
3963 * PrimitiveType: The primitive type to draw
3964 * VertexType: The FVF description of the vertices to draw (for the stride??)
3965 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3966 * the vertex data locations
3967 * VertexCount: The number of vertices to draw
3968 * Flags: Some flags
3970 * Returns:
3971 * D3D_OK, because it's a stub
3972 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3973 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3975 *****************************************************************************/
3976 static HRESULT
3977 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3978 D3DPRIMITIVETYPE PrimitiveType,
3979 DWORD VertexType,
3980 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3981 DWORD VertexCount,
3982 DWORD Flags)
3984 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3985 WineDirect3DVertexStridedData WineD3DStrided;
3986 DWORD i;
3987 UINT PrimitiveCount;
3988 HRESULT hr;
3990 TRACE("(%p)->(%08x,%08x,%p,%08x,%08x): stub!\n", This, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3992 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3993 /* Get the strided data right. the wined3d structure is a bit bigger
3994 * Watch out: The contents of the strided data are determined by the fvf,
3995 * not by the members set in D3DDrawPrimStrideData. So it's valid
3996 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3997 * not set in the fvf.
3999 if(VertexType & D3DFVF_POSITION_MASK)
4001 WineD3DStrided.u.s.position.lpData = D3DDrawPrimStrideData->position.lpvData;
4002 WineD3DStrided.u.s.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
4003 WineD3DStrided.u.s.position.dwType = WINED3DDECLTYPE_FLOAT3;
4004 if (VertexType & D3DFVF_XYZRHW)
4006 WineD3DStrided.u.s.position.dwType = WINED3DDECLTYPE_FLOAT4;
4007 WineD3DStrided.position_transformed = TRUE;
4008 } else
4009 WineD3DStrided.position_transformed = FALSE;
4012 if(VertexType & D3DFVF_NORMAL)
4014 WineD3DStrided.u.s.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
4015 WineD3DStrided.u.s.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
4016 WineD3DStrided.u.s.normal.dwType = WINED3DDECLTYPE_FLOAT3;
4019 if(VertexType & D3DFVF_DIFFUSE)
4021 WineD3DStrided.u.s.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
4022 WineD3DStrided.u.s.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
4023 WineD3DStrided.u.s.diffuse.dwType = WINED3DDECLTYPE_D3DCOLOR;
4026 if(VertexType & D3DFVF_SPECULAR)
4028 WineD3DStrided.u.s.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
4029 WineD3DStrided.u.s.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
4030 WineD3DStrided.u.s.specular.dwType = WINED3DDECLTYPE_D3DCOLOR;
4033 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
4035 WineD3DStrided.u.s.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4036 WineD3DStrided.u.s.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4037 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
4039 case 1: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT1; break;
4040 case 2: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT2; break;
4041 case 3: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT3; break;
4042 case 4: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT4; break;
4043 default: ERR("Unexpected texture coordinate size %d\n",
4044 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4048 /* Get the primitive count */
4049 switch(PrimitiveType)
4051 case D3DPT_POINTLIST:
4052 PrimitiveCount = VertexCount;
4053 break;
4055 case D3DPT_LINELIST:
4056 PrimitiveCount = VertexCount / 2;
4057 break;
4059 case D3DPT_LINESTRIP:
4060 PrimitiveCount = VertexCount - 1;
4061 break;
4063 case D3DPT_TRIANGLELIST:
4064 PrimitiveCount = VertexCount / 3;
4065 break;
4067 case D3DPT_TRIANGLESTRIP:
4068 PrimitiveCount = VertexCount - 2;
4069 break;
4071 case D3DPT_TRIANGLEFAN:
4072 PrimitiveCount = VertexCount - 2;
4073 break;
4075 default: return DDERR_INVALIDPARAMS;
4078 /* WineD3D doesn't need the FVF here */
4079 EnterCriticalSection(&ddraw_cs);
4080 hr = IWineD3DDevice_DrawPrimitiveStrided(This->wineD3DDevice,
4081 PrimitiveType,
4082 PrimitiveCount,
4083 &WineD3DStrided);
4084 LeaveCriticalSection(&ddraw_cs);
4085 return hr;
4088 static HRESULT WINAPI
4089 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4090 D3DPRIMITIVETYPE PrimitiveType,
4091 DWORD VertexType,
4092 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4093 DWORD VertexCount,
4094 DWORD Flags)
4096 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4099 static HRESULT WINAPI
4100 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4101 D3DPRIMITIVETYPE PrimitiveType,
4102 DWORD VertexType,
4103 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4104 DWORD VertexCount,
4105 DWORD Flags)
4107 HRESULT hr;
4108 WORD old_fpucw;
4110 old_fpucw = d3d_fpu_setup();
4111 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4112 set_fpu_control_word(old_fpucw);
4114 return hr;
4117 static HRESULT WINAPI
4118 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
4119 D3DPRIMITIVETYPE PrimitiveType,
4120 DWORD VertexType,
4121 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4122 DWORD VertexCount,
4123 DWORD Flags)
4125 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4126 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4127 return IDirect3DDevice7_DrawPrimitiveStrided(ICOM_INTERFACE(This, IDirect3DDevice7),
4128 PrimitiveType,
4129 VertexType,
4130 D3DDrawPrimStrideData,
4131 VertexCount,
4132 Flags);
4135 /*****************************************************************************
4136 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
4138 * Draws primitives specified by strided data locations based on indices
4140 * Version 3 and 7
4142 * Params:
4143 * PrimitiveType:
4145 * Returns:
4146 * D3D_OK, because it's a stub
4147 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
4148 * (DDERR_INVALIDPARAMS if Indices is NULL)
4149 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
4151 *****************************************************************************/
4152 static HRESULT
4153 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
4154 D3DPRIMITIVETYPE PrimitiveType,
4155 DWORD VertexType,
4156 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4157 DWORD VertexCount,
4158 WORD *Indices,
4159 DWORD IndexCount,
4160 DWORD Flags)
4162 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4163 WineDirect3DVertexStridedData WineD3DStrided;
4164 DWORD i;
4165 UINT PrimitiveCount;
4166 HRESULT hr;
4168 TRACE("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x)\n", This, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4170 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
4171 /* Get the strided data right. the wined3d structure is a bit bigger
4172 * Watch out: The contents of the strided data are determined by the fvf,
4173 * not by the members set in D3DDrawPrimStrideData. So it's valid
4174 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
4175 * not set in the fvf.
4177 if(VertexType & D3DFVF_POSITION_MASK)
4179 WineD3DStrided.u.s.position.lpData = D3DDrawPrimStrideData->position.lpvData;
4180 WineD3DStrided.u.s.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
4181 WineD3DStrided.u.s.position.dwType = WINED3DDECLTYPE_FLOAT3;
4182 if (VertexType & D3DFVF_XYZRHW)
4184 WineD3DStrided.u.s.position.dwType = WINED3DDECLTYPE_FLOAT4;
4185 WineD3DStrided.position_transformed = TRUE;
4186 } else
4187 WineD3DStrided.position_transformed = FALSE;
4190 if(VertexType & D3DFVF_NORMAL)
4192 WineD3DStrided.u.s.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
4193 WineD3DStrided.u.s.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
4194 WineD3DStrided.u.s.normal.dwType = WINED3DDECLTYPE_FLOAT3;
4197 if(VertexType & D3DFVF_DIFFUSE)
4199 WineD3DStrided.u.s.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
4200 WineD3DStrided.u.s.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
4201 WineD3DStrided.u.s.diffuse.dwType = WINED3DDECLTYPE_D3DCOLOR;
4204 if(VertexType & D3DFVF_SPECULAR)
4206 WineD3DStrided.u.s.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
4207 WineD3DStrided.u.s.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
4208 WineD3DStrided.u.s.specular.dwType = WINED3DDECLTYPE_D3DCOLOR;
4211 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
4213 WineD3DStrided.u.s.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4214 WineD3DStrided.u.s.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4215 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
4217 case 1: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT1; break;
4218 case 2: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT2; break;
4219 case 3: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT3; break;
4220 case 4: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT4; break;
4221 default: ERR("Unexpected texture coordinate size %d\n",
4222 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4226 /* Get the primitive count */
4227 switch(PrimitiveType)
4229 case D3DPT_POINTLIST:
4230 PrimitiveCount = IndexCount;
4231 break;
4233 case D3DPT_LINELIST:
4234 PrimitiveCount = IndexCount / 2;
4235 break;
4237 case D3DPT_LINESTRIP:
4238 PrimitiveCount = IndexCount - 1;
4239 break;
4241 case D3DPT_TRIANGLELIST:
4242 PrimitiveCount = IndexCount / 3;
4243 break;
4245 case D3DPT_TRIANGLESTRIP:
4246 PrimitiveCount = IndexCount - 2;
4247 break;
4249 case D3DPT_TRIANGLEFAN:
4250 PrimitiveCount = IndexCount - 2;
4251 break;
4253 default: return DDERR_INVALIDPARAMS;
4256 /* WineD3D doesn't need the FVF here */
4257 EnterCriticalSection(&ddraw_cs);
4258 hr = IWineD3DDevice_DrawIndexedPrimitiveStrided(This->wineD3DDevice,
4259 PrimitiveType,
4260 PrimitiveCount,
4261 &WineD3DStrided,
4262 VertexCount,
4263 Indices,
4264 WINED3DFMT_INDEX16);
4265 LeaveCriticalSection(&ddraw_cs);
4266 return hr;
4269 static HRESULT WINAPI
4270 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4271 D3DPRIMITIVETYPE PrimitiveType,
4272 DWORD VertexType,
4273 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4274 DWORD VertexCount,
4275 WORD *Indices,
4276 DWORD IndexCount,
4277 DWORD Flags)
4279 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4282 static HRESULT WINAPI
4283 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4284 D3DPRIMITIVETYPE PrimitiveType,
4285 DWORD VertexType,
4286 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4287 DWORD VertexCount,
4288 WORD *Indices,
4289 DWORD IndexCount,
4290 DWORD Flags)
4292 HRESULT hr;
4293 WORD old_fpucw;
4295 old_fpucw = d3d_fpu_setup();
4296 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4297 set_fpu_control_word(old_fpucw);
4299 return hr;
4302 static HRESULT WINAPI
4303 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4304 D3DPRIMITIVETYPE PrimitiveType,
4305 DWORD VertexType,
4306 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4307 DWORD VertexCount,
4308 WORD *Indices,
4309 DWORD IndexCount,
4310 DWORD Flags)
4312 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4313 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4314 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(ICOM_INTERFACE(This, IDirect3DDevice7),
4315 PrimitiveType,
4316 VertexType,
4317 D3DDrawPrimStrideData,
4318 VertexCount,
4319 Indices,
4320 IndexCount,
4321 Flags);
4324 /*****************************************************************************
4325 * IDirect3DDevice7::DrawPrimitiveVB
4327 * Draws primitives from a vertex buffer to the screen.
4329 * Version 3 and 7
4331 * Params:
4332 * PrimitiveType: Type of primitive to be rendered.
4333 * D3DVertexBuf: Source Vertex Buffer
4334 * StartVertex: Index of the first vertex from the buffer to be rendered
4335 * NumVertices: Number of vertices to be rendered
4336 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4338 * Return values
4339 * D3D_OK on success
4340 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4342 *****************************************************************************/
4343 static HRESULT
4344 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4345 D3DPRIMITIVETYPE PrimitiveType,
4346 IDirect3DVertexBuffer7 *D3DVertexBuf,
4347 DWORD StartVertex,
4348 DWORD NumVertices,
4349 DWORD Flags)
4351 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4352 IDirect3DVertexBufferImpl *vb = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, D3DVertexBuf);
4353 UINT PrimitiveCount;
4354 HRESULT hr;
4355 DWORD stride;
4356 WINED3DVERTEXBUFFER_DESC Desc;
4358 TRACE("(%p)->(%08x,%p,%08x,%08x,%08x)\n", This, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4360 /* Sanity checks */
4361 if(!vb)
4363 ERR("(%p) No Vertex buffer specified\n", This);
4364 return DDERR_INVALIDPARAMS;
4367 /* Get the primitive count */
4368 switch(PrimitiveType)
4370 case D3DPT_POINTLIST:
4371 PrimitiveCount = NumVertices;
4372 break;
4374 case D3DPT_LINELIST:
4375 PrimitiveCount = NumVertices / 2;
4376 break;
4378 case D3DPT_LINESTRIP:
4379 PrimitiveCount = NumVertices - 1;
4380 break;
4382 case D3DPT_TRIANGLELIST:
4383 PrimitiveCount = NumVertices / 3;
4384 break;
4386 case D3DPT_TRIANGLESTRIP:
4387 PrimitiveCount = NumVertices - 2;
4388 break;
4390 case D3DPT_TRIANGLEFAN:
4391 PrimitiveCount = NumVertices - 2;
4392 break;
4394 default:
4395 return DDERR_INVALIDPARAMS;
4398 /* Get the FVF of the vertex buffer, and its stride */
4399 EnterCriticalSection(&ddraw_cs);
4400 hr = IWineD3DVertexBuffer_GetDesc(vb->wineD3DVertexBuffer,
4401 &Desc);
4402 if(hr != D3D_OK)
4404 ERR("(%p) IWineD3DVertexBuffer::GetDesc failed with hr = %08x\n", This, hr);
4405 LeaveCriticalSection(&ddraw_cs);
4406 return hr;
4408 stride = get_flexible_vertex_size(Desc.FVF);
4410 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4411 vb->wineD3DVertexDeclaration);
4412 if(FAILED(hr))
4414 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4415 LeaveCriticalSection(&ddraw_cs);
4416 return hr;
4419 /* Set the vertex stream source */
4420 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4421 0 /* StreamNumber */,
4422 vb->wineD3DVertexBuffer,
4423 0 /* StartVertex - we pass this to DrawPrimitive */,
4424 stride);
4425 if(hr != D3D_OK)
4427 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4428 LeaveCriticalSection(&ddraw_cs);
4429 return hr;
4432 /* Now draw the primitives */
4433 hr = IWineD3DDevice_DrawPrimitive(This->wineD3DDevice,
4434 PrimitiveType,
4435 StartVertex,
4436 PrimitiveCount);
4437 LeaveCriticalSection(&ddraw_cs);
4438 return hr;
4441 static HRESULT WINAPI
4442 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4443 D3DPRIMITIVETYPE PrimitiveType,
4444 IDirect3DVertexBuffer7 *D3DVertexBuf,
4445 DWORD StartVertex,
4446 DWORD NumVertices,
4447 DWORD Flags)
4449 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4452 static HRESULT WINAPI
4453 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4454 D3DPRIMITIVETYPE PrimitiveType,
4455 IDirect3DVertexBuffer7 *D3DVertexBuf,
4456 DWORD StartVertex,
4457 DWORD NumVertices,
4458 DWORD Flags)
4460 HRESULT hr;
4461 WORD old_fpucw;
4463 old_fpucw = d3d_fpu_setup();
4464 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4465 set_fpu_control_word(old_fpucw);
4467 return hr;
4470 static HRESULT WINAPI
4471 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4472 D3DPRIMITIVETYPE PrimitiveType,
4473 IDirect3DVertexBuffer *D3DVertexBuf,
4474 DWORD StartVertex,
4475 DWORD NumVertices,
4476 DWORD Flags)
4478 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4479 IDirect3DVertexBufferImpl *vb = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, D3DVertexBuf);
4480 TRACE_(ddraw_thunk)("(%p)->(%08x,%p,%08x,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, vb, StartVertex, NumVertices, Flags);
4481 return IDirect3DDevice7_DrawPrimitiveVB(ICOM_INTERFACE(This, IDirect3DDevice7),
4482 PrimitiveType,
4483 ICOM_INTERFACE(vb, IDirect3DVertexBuffer7),
4484 StartVertex,
4485 NumVertices,
4486 Flags);
4490 /*****************************************************************************
4491 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4493 * Draws primitives from a vertex buffer to the screen
4495 * Params:
4496 * PrimitiveType: Type of primitive to be rendered.
4497 * D3DVertexBuf: Source Vertex Buffer
4498 * StartVertex: Index of the first vertex from the buffer to be rendered
4499 * NumVertices: Number of vertices to be rendered
4500 * Indices: Array of DWORDs used to index into the Vertices
4501 * IndexCount: Number of indices in Indices
4502 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4504 * Return values
4506 *****************************************************************************/
4507 static HRESULT
4508 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4509 D3DPRIMITIVETYPE PrimitiveType,
4510 IDirect3DVertexBuffer7 *D3DVertexBuf,
4511 DWORD StartVertex,
4512 DWORD NumVertices,
4513 WORD *Indices,
4514 DWORD IndexCount,
4515 DWORD Flags)
4517 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4518 IDirect3DVertexBufferImpl *vb = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, D3DVertexBuf);
4519 DWORD stride;
4520 UINT PrimitiveCount;
4521 WORD *LockedIndices;
4522 HRESULT hr;
4523 WINED3DVERTEXBUFFER_DESC Desc;
4525 TRACE("(%p)->(%08x,%p,%d,%d,%p,%d,%08x)\n", This, PrimitiveType, vb, StartVertex, NumVertices, Indices, IndexCount, Flags);
4527 /* Steps:
4528 * 1) Calculate some things: Vertex count -> Primitive count, stride, ...
4529 * 2) Upload the Indices to the index buffer
4530 * 3) Set the index source
4531 * 4) Set the Vertex Buffer as the Stream source
4532 * 5) Call IWineD3DDevice::DrawIndexedPrimitive
4535 /* Get the primitive count */
4536 switch(PrimitiveType)
4538 case D3DPT_POINTLIST:
4539 PrimitiveCount = IndexCount;
4540 break;
4542 case D3DPT_LINELIST:
4543 PrimitiveCount = IndexCount / 2;
4544 break;
4546 case D3DPT_LINESTRIP:
4547 PrimitiveCount = IndexCount - 1;
4548 break;
4550 case D3DPT_TRIANGLELIST:
4551 PrimitiveCount = IndexCount / 3;
4552 break;
4554 case D3DPT_TRIANGLESTRIP:
4555 PrimitiveCount = IndexCount - 2;
4556 break;
4558 case D3DPT_TRIANGLEFAN:
4559 PrimitiveCount = IndexCount - 2;
4560 break;
4562 default: return DDERR_INVALIDPARAMS;
4565 EnterCriticalSection(&ddraw_cs);
4566 /* Get the FVF of the vertex buffer, and its stride */
4567 hr = IWineD3DVertexBuffer_GetDesc(vb->wineD3DVertexBuffer,
4568 &Desc);
4569 if(hr != D3D_OK)
4571 ERR("(%p) IWineD3DVertexBuffer::GetDesc failed with hr = %08x\n", This, hr);
4572 LeaveCriticalSection(&ddraw_cs);
4573 return hr;
4575 stride = get_flexible_vertex_size(Desc.FVF);
4576 TRACE("Vertex buffer FVF = %08x, stride=%d\n", Desc.FVF, stride);
4578 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4579 vb->wineD3DVertexDeclaration);
4580 if(FAILED(hr))
4582 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4583 LeaveCriticalSection(&ddraw_cs);
4584 return hr;
4587 /* copy the index stream into the index buffer.
4588 * A new IWineD3DDevice method could be created
4589 * which takes an user pointer containing the indices
4590 * or a SetData-Method for the index buffer, which
4591 * overrides the index buffer data with our pointer.
4593 hr = IWineD3DIndexBuffer_Lock(This->indexbuffer,
4594 0 /* OffSetToLock */,
4595 IndexCount * sizeof(WORD),
4596 (BYTE **) &LockedIndices,
4597 0 /* Flags */);
4598 assert(IndexCount < 0x100000);
4599 if(hr != D3D_OK)
4601 ERR("(%p) IWineD3DIndexBuffer::Lock failed with hr = %08x\n", This, hr);
4602 LeaveCriticalSection(&ddraw_cs);
4603 return hr;
4605 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4606 hr = IWineD3DIndexBuffer_Unlock(This->indexbuffer);
4607 if(hr != D3D_OK)
4609 ERR("(%p) IWineD3DIndexBuffer::Unlock failed with hr = %08x\n", This, hr);
4610 LeaveCriticalSection(&ddraw_cs);
4611 return hr;
4614 /* Set the index stream */
4615 IWineD3DDevice_SetBaseVertexIndex(This->wineD3DDevice, StartVertex);
4616 hr = IWineD3DDevice_SetIndices(This->wineD3DDevice, This->indexbuffer);
4618 /* Set the vertex stream source */
4619 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4620 0 /* StreamNumber */,
4621 vb->wineD3DVertexBuffer,
4622 0 /* offset, we pass this to DrawIndexedPrimitive */,
4623 stride);
4624 if(hr != D3D_OK)
4626 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4627 LeaveCriticalSection(&ddraw_cs);
4628 return hr;
4632 hr = IWineD3DDevice_DrawIndexedPrimitive(This->wineD3DDevice,
4633 PrimitiveType,
4634 0 /* minIndex */,
4635 NumVertices,
4636 0 /* StartIndex */,
4637 PrimitiveCount);
4639 LeaveCriticalSection(&ddraw_cs);
4640 return hr;
4643 static HRESULT WINAPI
4644 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4645 D3DPRIMITIVETYPE PrimitiveType,
4646 IDirect3DVertexBuffer7 *D3DVertexBuf,
4647 DWORD StartVertex,
4648 DWORD NumVertices,
4649 WORD *Indices,
4650 DWORD IndexCount,
4651 DWORD Flags)
4653 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4656 static HRESULT WINAPI
4657 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4658 D3DPRIMITIVETYPE PrimitiveType,
4659 IDirect3DVertexBuffer7 *D3DVertexBuf,
4660 DWORD StartVertex,
4661 DWORD NumVertices,
4662 WORD *Indices,
4663 DWORD IndexCount,
4664 DWORD Flags)
4666 HRESULT hr;
4667 WORD old_fpucw;
4669 old_fpucw = d3d_fpu_setup();
4670 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4671 set_fpu_control_word(old_fpucw);
4673 return hr;
4676 static HRESULT WINAPI
4677 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4678 D3DPRIMITIVETYPE PrimitiveType,
4679 IDirect3DVertexBuffer *D3DVertexBuf,
4680 WORD *Indices,
4681 DWORD IndexCount,
4682 DWORD Flags)
4684 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4685 IDirect3DVertexBufferImpl *VB = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, D3DVertexBuf);
4686 TRACE_(ddraw_thunk)("(%p)->(%08x,%p,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VB, Indices, IndexCount, Flags);
4688 return IDirect3DDevice7_DrawIndexedPrimitiveVB(ICOM_INTERFACE(This, IDirect3DDevice7),
4689 PrimitiveType,
4690 ICOM_INTERFACE(VB, IDirect3DVertexBuffer7),
4692 IndexCount,
4693 Indices,
4694 IndexCount,
4695 Flags);
4698 /*****************************************************************************
4699 * IDirect3DDevice7::ComputeSphereVisibility
4701 * Calculates the visibility of spheres in the current viewport. The spheres
4702 * are passed in the Centers and Radii arrays, the results are passed back
4703 * in the ReturnValues array. Return values are either completely visible,
4704 * partially visible or completely invisible.
4705 * The return value consist of a combination of D3DCLIP_* flags, or it's
4706 * 0 if the sphere is completely visible(according to the SDK, not checked)
4708 * Sounds like an overdose of math ;)
4710 * Version 3 and 7
4712 * Params:
4713 * Centers: Array containing the sphere centers
4714 * Radii: Array containing the sphere radii
4715 * NumSpheres: The number of centers and radii in the arrays
4716 * Flags: Some flags
4717 * ReturnValues: Array to write the results to
4719 * Returns:
4720 * D3D_OK because it's a stub
4721 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4722 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4723 * is singular)
4725 *****************************************************************************/
4726 static HRESULT WINAPI
4727 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4728 D3DVECTOR *Centers,
4729 D3DVALUE *Radii,
4730 DWORD NumSpheres,
4731 DWORD Flags,
4732 DWORD *ReturnValues)
4734 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4735 FIXME("(%p)->(%p,%p,%08x,%08x,%p): stub!\n", This, Centers, Radii, NumSpheres, Flags, ReturnValues);
4737 /* the DirectX 7 sdk says that the visibility is computed by
4738 * back-transforming the viewing frustum to model space
4739 * using the inverse of the combined world, view and projection
4740 * matrix. If the matrix can't be reversed, D3DERR_INVALIDMATRIX
4741 * is returned.
4743 * Basic implementation idea:
4744 * 1) Check if the center is in the viewing frustum
4745 * 2) Cut the sphere with the planes of the viewing
4746 * frustum
4748 * ->Center inside the frustum, no intersections:
4749 * Fully visible
4750 * ->Center outside the frustum, no intersections:
4751 * Not visible
4752 * ->Some intersections: Partially visible
4754 * Implement this call in WineD3D. Either implement the
4755 * matrix and vector stuff in WineD3D, or use some external
4756 * math library.
4759 return D3D_OK;
4762 static HRESULT WINAPI
4763 Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4764 D3DVECTOR *Centers,
4765 D3DVALUE *Radii,
4766 DWORD NumSpheres,
4767 DWORD Flags,
4768 DWORD *ReturnValues)
4770 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4771 TRACE_(ddraw_thunk)("(%p)->(%p,%p,%08x,%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, Centers, Radii, NumSpheres, Flags, ReturnValues);
4772 return IDirect3DDevice7_ComputeSphereVisibility(ICOM_INTERFACE(This, IDirect3DDevice7),
4773 Centers,
4774 Radii,
4775 NumSpheres,
4776 Flags,
4777 ReturnValues);
4780 /*****************************************************************************
4781 * IDirect3DDevice7::GetTexture
4783 * Returns the texture interface handle assigned to a texture stage.
4784 * The returned texture is AddRefed. This is taken from old ddraw,
4785 * not checked in Windows.
4787 * Version 3 and 7
4789 * Params:
4790 * Stage: Texture stage to read the texture from
4791 * Texture: Address to store the interface pointer at
4793 * Returns:
4794 * D3D_OK on success
4795 * DDERR_INVALIDPARAMS if Texture is NULL
4796 * For details, see IWineD3DDevice::GetTexture
4798 *****************************************************************************/
4799 static HRESULT
4800 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4801 DWORD Stage,
4802 IDirectDrawSurface7 **Texture)
4804 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4805 IWineD3DBaseTexture *Surf;
4806 HRESULT hr;
4807 TRACE("(%p)->(%d,%p): Relay\n", This, Stage, Texture);
4809 if(!Texture)
4811 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4812 return DDERR_INVALIDPARAMS;
4815 EnterCriticalSection(&ddraw_cs);
4816 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, Stage, &Surf);
4817 if( (hr != D3D_OK) || (!Surf) )
4819 *Texture = NULL;
4820 LeaveCriticalSection(&ddraw_cs);
4821 return hr;
4824 /* GetParent AddRef()s, which is perfectly OK.
4825 * We have passed the IDirectDrawSurface7 interface to WineD3D, so that's OK too.
4827 hr = IWineD3DBaseTexture_GetParent(Surf,
4828 (IUnknown **) Texture);
4829 LeaveCriticalSection(&ddraw_cs);
4830 return hr;
4833 static HRESULT WINAPI
4834 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4835 DWORD Stage,
4836 IDirectDrawSurface7 **Texture)
4838 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4841 static HRESULT WINAPI
4842 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4843 DWORD Stage,
4844 IDirectDrawSurface7 **Texture)
4846 HRESULT hr;
4847 WORD old_fpucw;
4849 old_fpucw = d3d_fpu_setup();
4850 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4851 set_fpu_control_word(old_fpucw);
4853 return hr;
4856 static HRESULT WINAPI
4857 Thunk_IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface,
4858 DWORD Stage,
4859 IDirect3DTexture2 **Texture2)
4861 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4862 HRESULT ret;
4863 IDirectDrawSurface7 *ret_val;
4865 TRACE_(ddraw_thunk)("(%p)->(%d,%p) thunking to IDirect3DDevice7 interface.\n", This, Stage, Texture2);
4866 ret = IDirect3DDevice7_GetTexture(ICOM_INTERFACE(This, IDirect3DDevice7),
4867 Stage,
4868 &ret_val);
4870 *Texture2 = COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirectDrawSurface7, IDirect3DTexture2, ret_val);
4872 TRACE_(ddraw_thunk)(" returning interface %p.\n", *Texture2);
4874 return ret;
4877 /*****************************************************************************
4878 * IDirect3DDevice7::SetTexture
4880 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4882 * Version 3 and 7
4884 * Params:
4885 * Stage: The stage to assign the texture to
4886 * Texture: Interface pointer to the texture surface
4888 * Returns
4889 * D3D_OK on success
4890 * For details, see IWineD3DDevice::SetTexture
4892 *****************************************************************************/
4893 static HRESULT
4894 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4895 DWORD Stage,
4896 IDirectDrawSurface7 *Texture)
4898 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4899 IDirectDrawSurfaceImpl *surf = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, Texture);
4900 HRESULT hr;
4901 TRACE("(%p)->(%08x,%p): Relay!\n", This, Stage, surf);
4903 /* Texture may be NULL here */
4904 EnterCriticalSection(&ddraw_cs);
4905 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
4906 Stage,
4907 surf ? surf->wineD3DTexture : NULL);
4908 LeaveCriticalSection(&ddraw_cs);
4909 return hr;
4912 static HRESULT WINAPI
4913 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4914 DWORD Stage,
4915 IDirectDrawSurface7 *Texture)
4917 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4920 static HRESULT WINAPI
4921 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4922 DWORD Stage,
4923 IDirectDrawSurface7 *Texture)
4925 HRESULT hr;
4926 WORD old_fpucw;
4928 old_fpucw = d3d_fpu_setup();
4929 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4930 set_fpu_control_word(old_fpucw);
4932 return hr;
4935 static HRESULT WINAPI
4936 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4937 DWORD Stage,
4938 IDirect3DTexture2 *Texture2)
4940 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4941 IDirectDrawSurfaceImpl *tex = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture2, Texture2);
4942 DWORD texmapblend;
4943 HRESULT hr;
4944 TRACE("(%p)->(%d,%p)\n", This, Stage, tex);
4946 EnterCriticalSection(&ddraw_cs);
4948 if (This->legacyTextureBlending)
4949 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4951 hr = IDirect3DDevice7_SetTexture(ICOM_INTERFACE(This, IDirect3DDevice7),
4952 Stage,
4953 ICOM_INTERFACE(tex, IDirectDrawSurface7));
4955 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4957 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4958 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4959 BOOL tex_alpha = FALSE;
4960 IWineD3DBaseTexture *tex = NULL;
4961 WINED3DSURFACE_DESC desc;
4962 WINED3DFORMAT fmt;
4963 DDPIXELFORMAT ddfmt;
4964 HRESULT result;
4966 result = IWineD3DDevice_GetTexture(This->wineD3DDevice,
4968 &tex);
4970 if(result == WINED3D_OK && tex)
4972 memset(&desc, 0, sizeof(desc));
4973 desc.Format = &fmt;
4974 result = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
4975 if (SUCCEEDED(result))
4977 ddfmt.dwSize = sizeof(ddfmt);
4978 PixelFormat_WineD3DtoDD(&ddfmt, fmt);
4979 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4982 IWineD3DBaseTexture_Release(tex);
4985 /* alphaop is WINED3DTOP_SELECTARG1 if it's D3DTBLEND_MODULATE, so only modify alphaarg1 */
4986 if (tex_alpha)
4988 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
4990 else
4992 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_CURRENT);
4996 LeaveCriticalSection(&ddraw_cs);
4998 return hr;
5001 static const struct tss_lookup
5003 BOOL sampler_state;
5004 DWORD state;
5006 tss_lookup[] =
5008 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
5009 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
5010 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
5011 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
5012 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
5013 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
5014 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
5015 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
5016 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
5017 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
5018 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
5019 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
5020 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
5021 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
5022 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
5023 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
5024 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
5025 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
5026 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
5027 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
5028 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
5029 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
5030 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
5031 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
5032 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
5035 /*****************************************************************************
5036 * IDirect3DDevice7::GetTextureStageState
5038 * Retrieves a state from a texture stage.
5040 * Version 3 and 7
5042 * Params:
5043 * Stage: The stage to retrieve the state from
5044 * TexStageStateType: The state type to retrieve
5045 * State: Address to store the state's value at
5047 * Returns:
5048 * D3D_OK on success
5049 * DDERR_INVALIDPARAMS if State is NULL
5050 * For details, see IWineD3DDevice::GetTextureStageState
5052 *****************************************************************************/
5053 static HRESULT
5054 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
5055 DWORD Stage,
5056 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5057 DWORD *State)
5059 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5060 HRESULT hr;
5061 const struct tss_lookup *l = &tss_lookup[TexStageStateType];
5062 TRACE("(%p)->(%08x,%08x,%p): Relay!\n", This, Stage, TexStageStateType, State);
5064 if(!State)
5065 return DDERR_INVALIDPARAMS;
5067 EnterCriticalSection(&ddraw_cs);
5069 if (l->sampler_state)
5071 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice, Stage, l->state, State);
5073 switch(TexStageStateType)
5075 /* Mipfilter is a sampler state with different values */
5076 case D3DTSS_MIPFILTER:
5078 switch(*State)
5080 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
5081 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
5082 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
5083 default:
5084 ERR("Unexpected mipfilter value %#x\n", *State);
5085 *State = D3DTFP_NONE;
5086 break;
5088 break;
5091 /* Magfilter has slightly different values */
5092 case D3DTSS_MAGFILTER:
5094 switch(*State)
5096 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
5097 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
5098 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
5099 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
5100 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
5101 default:
5102 ERR("Unexpected wined3d mag filter value %#x\n", *State);
5103 *State = D3DTFG_POINT;
5104 break;
5106 break;
5109 default:
5110 break;
5113 else
5115 hr = IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
5118 LeaveCriticalSection(&ddraw_cs);
5119 return hr;
5122 static HRESULT WINAPI
5123 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5124 DWORD Stage,
5125 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5126 DWORD *State)
5128 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
5131 static HRESULT WINAPI
5132 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5133 DWORD Stage,
5134 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5135 DWORD *State)
5137 HRESULT hr;
5138 WORD old_fpucw;
5140 old_fpucw = d3d_fpu_setup();
5141 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
5142 set_fpu_control_word(old_fpucw);
5144 return hr;
5147 static HRESULT WINAPI
5148 Thunk_IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
5149 DWORD Stage,
5150 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5151 DWORD *State)
5153 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
5154 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, Stage, TexStageStateType, State);
5155 return IDirect3DDevice7_GetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
5156 Stage,
5157 TexStageStateType,
5158 State);
5161 /*****************************************************************************
5162 * IDirect3DDevice7::SetTextureStageState
5164 * Sets a texture stage state. Some stage types need to be handled specially,
5165 * because they do not exist in WineD3D and were moved to another place
5167 * Version 3 and 7
5169 * Params:
5170 * Stage: The stage to modify
5171 * TexStageStateType: The state to change
5172 * State: The new value for the state
5174 * Returns:
5175 * D3D_OK on success
5176 * For details, see IWineD3DDevice::SetTextureStageState
5178 *****************************************************************************/
5179 static HRESULT
5180 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
5181 DWORD Stage,
5182 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5183 DWORD State)
5185 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5186 const struct tss_lookup *l = &tss_lookup[TexStageStateType];
5187 HRESULT hr;
5188 TRACE("(%p)->(%08x,%08x,%08x): Relay!\n", This, Stage, TexStageStateType, State);
5190 EnterCriticalSection(&ddraw_cs);
5192 if (l->sampler_state)
5194 switch(TexStageStateType)
5196 /* Mipfilter is a sampler state with different values */
5197 case D3DTSS_MIPFILTER:
5199 switch(State)
5201 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
5202 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
5203 case 0: /* Unchecked */
5204 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
5205 default:
5206 ERR("Unexpected mipfilter value %d\n", State);
5207 State = WINED3DTEXF_NONE;
5208 break;
5210 break;
5213 /* Magfilter has slightly different values */
5214 case D3DTSS_MAGFILTER:
5216 switch(State)
5218 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
5219 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
5220 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
5221 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
5222 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
5223 default:
5224 ERR("Unexpected d3d7 mag filter type %d\n", State);
5225 State = WINED3DTEXF_POINT;
5226 break;
5228 break;
5231 case D3DTSS_ADDRESS:
5232 IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, WINED3DSAMP_ADDRESSV, State);
5233 break;
5235 default:
5236 break;
5239 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, l->state, State);
5241 else
5243 hr = IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
5246 LeaveCriticalSection(&ddraw_cs);
5247 return hr;
5250 static HRESULT WINAPI
5251 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5252 DWORD Stage,
5253 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5254 DWORD State)
5256 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5259 static HRESULT WINAPI
5260 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5261 DWORD Stage,
5262 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5263 DWORD State)
5265 HRESULT hr;
5266 WORD old_fpucw;
5268 old_fpucw = d3d_fpu_setup();
5269 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5270 set_fpu_control_word(old_fpucw);
5272 return hr;
5275 static HRESULT WINAPI
5276 Thunk_IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
5277 DWORD Stage,
5278 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5279 DWORD State)
5281 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
5282 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, Stage, TexStageStateType, State);
5283 return IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
5284 Stage,
5285 TexStageStateType,
5286 State);
5289 /*****************************************************************************
5290 * IDirect3DDevice7::ValidateDevice
5292 * SDK: "Reports the device's ability to render the currently set
5293 * texture-blending operations in a single pass". Whatever that means
5294 * exactly...
5296 * Version 3 and 7
5298 * Params:
5299 * NumPasses: Address to write the number of necessary passes for the
5300 * desired effect to.
5302 * Returns:
5303 * D3D_OK on success
5304 * See IWineD3DDevice::ValidateDevice for more details
5306 *****************************************************************************/
5307 static HRESULT
5308 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
5309 DWORD *NumPasses)
5311 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5312 HRESULT hr;
5313 TRACE("(%p)->(%p): Relay\n", This, NumPasses);
5315 EnterCriticalSection(&ddraw_cs);
5316 hr = IWineD3DDevice_ValidateDevice(This->wineD3DDevice, NumPasses);
5317 LeaveCriticalSection(&ddraw_cs);
5318 return hr;
5321 static HRESULT WINAPI
5322 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
5323 DWORD *NumPasses)
5325 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5328 static HRESULT WINAPI
5329 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
5330 DWORD *NumPasses)
5332 HRESULT hr;
5333 WORD old_fpucw;
5335 old_fpucw = d3d_fpu_setup();
5336 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5337 set_fpu_control_word(old_fpucw);
5339 return hr;
5342 static HRESULT WINAPI
5343 Thunk_IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface,
5344 DWORD *Passes)
5346 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
5347 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Passes);
5348 return IDirect3DDevice7_ValidateDevice(ICOM_INTERFACE(This, IDirect3DDevice7),
5349 Passes);
5352 /*****************************************************************************
5353 * IDirect3DDevice7::Clear
5355 * Fills the render target, the z buffer and the stencil buffer with a
5356 * clear color / value
5358 * Version 7 only
5360 * Params:
5361 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5362 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5363 * Flags: Some flags, as usual
5364 * Color: Clear color for the render target
5365 * Z: Clear value for the Z buffer
5366 * Stencil: Clear value to store in each stencil buffer entry
5368 * Returns:
5369 * D3D_OK on success
5370 * For details, see IWineD3DDevice::Clear
5372 *****************************************************************************/
5373 static HRESULT
5374 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
5375 DWORD Count,
5376 D3DRECT *Rects,
5377 DWORD Flags,
5378 D3DCOLOR Color,
5379 D3DVALUE Z,
5380 DWORD Stencil)
5382 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5383 HRESULT hr;
5384 TRACE("(%p)->(%08x,%p,%08x,%08x,%f,%08x): Relay\n", This, Count, Rects, Flags, Color, Z, Stencil);
5386 /* Note; D3DRECT is compatible with WINED3DRECT */
5387 EnterCriticalSection(&ddraw_cs);
5388 hr = IWineD3DDevice_Clear(This->wineD3DDevice, Count, (WINED3DRECT*) Rects, Flags, Color, Z, Stencil);
5389 LeaveCriticalSection(&ddraw_cs);
5390 return hr;
5393 static HRESULT WINAPI
5394 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5395 DWORD Count,
5396 D3DRECT *Rects,
5397 DWORD Flags,
5398 D3DCOLOR Color,
5399 D3DVALUE Z,
5400 DWORD Stencil)
5402 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5405 static HRESULT WINAPI
5406 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5407 DWORD Count,
5408 D3DRECT *Rects,
5409 DWORD Flags,
5410 D3DCOLOR Color,
5411 D3DVALUE Z,
5412 DWORD Stencil)
5414 HRESULT hr;
5415 WORD old_fpucw;
5417 old_fpucw = d3d_fpu_setup();
5418 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5419 set_fpu_control_word(old_fpucw);
5421 return hr;
5424 /*****************************************************************************
5425 * IDirect3DDevice7::SetViewport
5427 * Sets the current viewport.
5429 * Version 7 only, but IDirect3DViewport uses this call for older
5430 * versions
5432 * Params:
5433 * Data: The new viewport to set
5435 * Returns:
5436 * D3D_OK on success
5437 * DDERR_INVALIDPARAMS if Data is NULL
5438 * For more details, see IWineDDDevice::SetViewport
5440 *****************************************************************************/
5441 static HRESULT
5442 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5443 D3DVIEWPORT7 *Data)
5445 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5446 HRESULT hr;
5447 TRACE("(%p)->(%p) Relay!\n", This, Data);
5449 if(!Data)
5450 return DDERR_INVALIDPARAMS;
5452 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5453 EnterCriticalSection(&ddraw_cs);
5454 hr = IWineD3DDevice_SetViewport(This->wineD3DDevice,
5455 (WINED3DVIEWPORT*) Data);
5456 LeaveCriticalSection(&ddraw_cs);
5457 return hr;
5460 static HRESULT WINAPI
5461 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5462 D3DVIEWPORT7 *Data)
5464 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5467 static HRESULT WINAPI
5468 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5469 D3DVIEWPORT7 *Data)
5471 HRESULT hr;
5472 WORD old_fpucw;
5474 old_fpucw = d3d_fpu_setup();
5475 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5476 set_fpu_control_word(old_fpucw);
5478 return hr;
5481 /*****************************************************************************
5482 * IDirect3DDevice::GetViewport
5484 * Returns the current viewport
5486 * Version 7
5488 * Params:
5489 * Data: D3D7Viewport structure to write the viewport information to
5491 * Returns:
5492 * D3D_OK on success
5493 * DDERR_INVALIDPARAMS if Data is NULL
5494 * For more details, see IWineD3DDevice::GetViewport
5496 *****************************************************************************/
5497 static HRESULT
5498 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5499 D3DVIEWPORT7 *Data)
5501 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5502 HRESULT hr;
5503 TRACE("(%p)->(%p) Relay!\n", This, Data);
5505 if(!Data)
5506 return DDERR_INVALIDPARAMS;
5508 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5509 EnterCriticalSection(&ddraw_cs);
5510 hr = IWineD3DDevice_GetViewport(This->wineD3DDevice,
5511 (WINED3DVIEWPORT*) Data);
5513 LeaveCriticalSection(&ddraw_cs);
5514 return hr_ddraw_from_wined3d(hr);
5517 static HRESULT WINAPI
5518 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5519 D3DVIEWPORT7 *Data)
5521 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5524 static HRESULT WINAPI
5525 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5526 D3DVIEWPORT7 *Data)
5528 HRESULT hr;
5529 WORD old_fpucw;
5531 old_fpucw = d3d_fpu_setup();
5532 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5533 set_fpu_control_word(old_fpucw);
5535 return hr;
5538 /*****************************************************************************
5539 * IDirect3DDevice7::SetMaterial
5541 * Sets the Material
5543 * Version 7
5545 * Params:
5546 * Mat: The material to set
5548 * Returns:
5549 * D3D_OK on success
5550 * DDERR_INVALIDPARAMS if Mat is NULL.
5551 * For more details, see IWineD3DDevice::SetMaterial
5553 *****************************************************************************/
5554 static HRESULT
5555 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5556 D3DMATERIAL7 *Mat)
5558 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5559 HRESULT hr;
5560 TRACE("(%p)->(%p): Relay!\n", This, Mat);
5562 if (!Mat) return DDERR_INVALIDPARAMS;
5563 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5564 EnterCriticalSection(&ddraw_cs);
5565 hr = IWineD3DDevice_SetMaterial(This->wineD3DDevice,
5566 (WINED3DMATERIAL*) Mat);
5567 LeaveCriticalSection(&ddraw_cs);
5568 return hr_ddraw_from_wined3d(hr);
5571 static HRESULT WINAPI
5572 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5573 D3DMATERIAL7 *Mat)
5575 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5578 static HRESULT WINAPI
5579 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5580 D3DMATERIAL7 *Mat)
5582 HRESULT hr;
5583 WORD old_fpucw;
5585 old_fpucw = d3d_fpu_setup();
5586 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5587 set_fpu_control_word(old_fpucw);
5589 return hr;
5592 /*****************************************************************************
5593 * IDirect3DDevice7::GetMaterial
5595 * Returns the current material
5597 * Version 7
5599 * Params:
5600 * Mat: D3DMATERIAL7 structure to write the material parameters to
5602 * Returns:
5603 * D3D_OK on success
5604 * DDERR_INVALIDPARAMS if Mat is NULL
5605 * For more details, see IWineD3DDevice::GetMaterial
5607 *****************************************************************************/
5608 static HRESULT
5609 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5610 D3DMATERIAL7 *Mat)
5612 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5613 HRESULT hr;
5614 TRACE("(%p)->(%p): Relay!\n", This, Mat);
5616 EnterCriticalSection(&ddraw_cs);
5617 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5618 hr = IWineD3DDevice_GetMaterial(This->wineD3DDevice,
5619 (WINED3DMATERIAL*) Mat);
5620 LeaveCriticalSection(&ddraw_cs);
5621 return hr_ddraw_from_wined3d(hr);
5624 static HRESULT WINAPI
5625 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5626 D3DMATERIAL7 *Mat)
5628 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5631 static HRESULT WINAPI
5632 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5633 D3DMATERIAL7 *Mat)
5635 HRESULT hr;
5636 WORD old_fpucw;
5638 old_fpucw = d3d_fpu_setup();
5639 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5640 set_fpu_control_word(old_fpucw);
5642 return hr;
5645 /*****************************************************************************
5646 * IDirect3DDevice7::SetLight
5648 * Assigns a light to a light index, but doesn't activate it yet.
5650 * Version 7, IDirect3DLight uses this method for older versions
5652 * Params:
5653 * LightIndex: The index of the new light
5654 * Light: A D3DLIGHT7 structure describing the light
5656 * Returns:
5657 * D3D_OK on success
5658 * For more details, see IWineD3DDevice::SetLight
5660 *****************************************************************************/
5661 static HRESULT
5662 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5663 DWORD LightIndex,
5664 D3DLIGHT7 *Light)
5666 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5667 HRESULT hr;
5668 TRACE("(%p)->(%08x,%p): Relay!\n", This, LightIndex, Light);
5670 EnterCriticalSection(&ddraw_cs);
5671 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5672 hr = IWineD3DDevice_SetLight(This->wineD3DDevice,
5673 LightIndex,
5674 (WINED3DLIGHT*) Light);
5675 LeaveCriticalSection(&ddraw_cs);
5676 return hr_ddraw_from_wined3d(hr);
5679 static HRESULT WINAPI
5680 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5681 DWORD LightIndex,
5682 D3DLIGHT7 *Light)
5684 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5687 static HRESULT WINAPI
5688 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5689 DWORD LightIndex,
5690 D3DLIGHT7 *Light)
5692 HRESULT hr;
5693 WORD old_fpucw;
5695 old_fpucw = d3d_fpu_setup();
5696 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5697 set_fpu_control_word(old_fpucw);
5699 return hr;
5702 /*****************************************************************************
5703 * IDirect3DDevice7::GetLight
5705 * Returns the light assigned to a light index
5707 * Params:
5708 * Light: Structure to write the light information to
5710 * Returns:
5711 * D3D_OK on success
5712 * DDERR_INVALIDPARAMS if Light is NULL
5713 * For details, see IWineD3DDevice::GetLight
5715 *****************************************************************************/
5716 static HRESULT
5717 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5718 DWORD LightIndex,
5719 D3DLIGHT7 *Light)
5721 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5722 HRESULT rc;
5723 TRACE("(%p)->(%08x,%p): Relay!\n", This, LightIndex, Light);
5725 EnterCriticalSection(&ddraw_cs);
5726 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5727 rc = IWineD3DDevice_GetLight(This->wineD3DDevice,
5728 LightIndex,
5729 (WINED3DLIGHT*) Light);
5731 /* Translate the result. WineD3D returns other values than D3D7 */
5732 LeaveCriticalSection(&ddraw_cs);
5733 return hr_ddraw_from_wined3d(rc);
5736 static HRESULT WINAPI
5737 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5738 DWORD LightIndex,
5739 D3DLIGHT7 *Light)
5741 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5744 static HRESULT WINAPI
5745 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5746 DWORD LightIndex,
5747 D3DLIGHT7 *Light)
5749 HRESULT hr;
5750 WORD old_fpucw;
5752 old_fpucw = d3d_fpu_setup();
5753 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5754 set_fpu_control_word(old_fpucw);
5756 return hr;
5759 /*****************************************************************************
5760 * IDirect3DDevice7::BeginStateBlock
5762 * Begins recording to a stateblock
5764 * Version 7
5766 * Returns:
5767 * D3D_OK on success
5768 * For details see IWineD3DDevice::BeginStateBlock
5770 *****************************************************************************/
5771 static HRESULT
5772 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5774 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5775 HRESULT hr;
5776 TRACE("(%p)->(): Relay!\n", This);
5778 EnterCriticalSection(&ddraw_cs);
5779 hr = IWineD3DDevice_BeginStateBlock(This->wineD3DDevice);
5780 LeaveCriticalSection(&ddraw_cs);
5781 return hr_ddraw_from_wined3d(hr);
5784 static HRESULT WINAPI
5785 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5787 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5790 static HRESULT WINAPI
5791 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5793 HRESULT hr;
5794 WORD old_fpucw;
5796 old_fpucw = d3d_fpu_setup();
5797 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5798 set_fpu_control_word(old_fpucw);
5800 return hr;
5803 /*****************************************************************************
5804 * IDirect3DDevice7::EndStateBlock
5806 * Stops recording to a state block and returns the created stateblock
5807 * handle.
5809 * Version 7
5811 * Params:
5812 * BlockHandle: Address to store the stateblock's handle to
5814 * Returns:
5815 * D3D_OK on success
5816 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5817 * See IWineD3DDevice::EndStateBlock for more details
5819 *****************************************************************************/
5820 static HRESULT
5821 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5822 DWORD *BlockHandle)
5824 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5825 HRESULT hr;
5826 TRACE("(%p)->(%p): Relay!\n", This, BlockHandle);
5828 if(!BlockHandle)
5830 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5831 return DDERR_INVALIDPARAMS;
5834 EnterCriticalSection(&ddraw_cs);
5835 *BlockHandle = IDirect3DDeviceImpl_CreateHandle(This);
5836 if(!*BlockHandle)
5838 ERR("Cannot get a handle number for the stateblock\n");
5839 LeaveCriticalSection(&ddraw_cs);
5840 return DDERR_OUTOFMEMORY;
5842 This->Handles[*BlockHandle - 1].type = DDrawHandle_StateBlock;
5843 hr = IWineD3DDevice_EndStateBlock(This->wineD3DDevice,
5844 (IWineD3DStateBlock **) &This->Handles[*BlockHandle - 1].ptr);
5845 LeaveCriticalSection(&ddraw_cs);
5846 return hr_ddraw_from_wined3d(hr);
5849 static HRESULT WINAPI
5850 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5851 DWORD *BlockHandle)
5853 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5856 static HRESULT WINAPI
5857 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5858 DWORD *BlockHandle)
5860 HRESULT hr;
5861 WORD old_fpucw;
5863 old_fpucw = d3d_fpu_setup();
5864 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5865 set_fpu_control_word(old_fpucw);
5867 return hr;
5870 /*****************************************************************************
5871 * IDirect3DDevice7::PreLoad
5873 * Allows the app to signal that a texture will be used soon, to allow
5874 * the Direct3DDevice to load it to the video card in the meantime.
5876 * Version 7
5878 * Params:
5879 * Texture: The texture to preload
5881 * Returns:
5882 * D3D_OK on success
5883 * DDERR_INVALIDPARAMS if Texture is NULL
5884 * See IWineD3DSurface::PreLoad for details
5886 *****************************************************************************/
5887 static HRESULT
5888 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5889 IDirectDrawSurface7 *Texture)
5891 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5892 IDirectDrawSurfaceImpl *surf = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, Texture);
5894 TRACE("(%p)->(%p): Relay!\n", This, surf);
5896 if(!Texture)
5897 return DDERR_INVALIDPARAMS;
5899 EnterCriticalSection(&ddraw_cs);
5900 IWineD3DSurface_PreLoad(surf->WineD3DSurface);
5901 LeaveCriticalSection(&ddraw_cs);
5902 return D3D_OK;
5905 static HRESULT WINAPI
5906 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5907 IDirectDrawSurface7 *Texture)
5909 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5912 static HRESULT WINAPI
5913 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5914 IDirectDrawSurface7 *Texture)
5916 HRESULT hr;
5917 WORD old_fpucw;
5919 old_fpucw = d3d_fpu_setup();
5920 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5921 set_fpu_control_word(old_fpucw);
5923 return hr;
5926 /*****************************************************************************
5927 * IDirect3DDevice7::ApplyStateBlock
5929 * Activates the state stored in a state block handle.
5931 * Params:
5932 * BlockHandle: The stateblock handle to activate
5934 * Returns:
5935 * D3D_OK on success
5936 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5938 *****************************************************************************/
5939 static HRESULT
5940 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5941 DWORD BlockHandle)
5943 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5944 HRESULT hr;
5945 TRACE("(%p)->(%08x): Relay!\n", This, BlockHandle);
5947 EnterCriticalSection(&ddraw_cs);
5948 if(!BlockHandle || BlockHandle > This->numHandles)
5950 WARN("Out of range handle %d, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5951 LeaveCriticalSection(&ddraw_cs);
5952 return D3DERR_INVALIDSTATEBLOCK;
5954 if(This->Handles[BlockHandle - 1].type != DDrawHandle_StateBlock)
5956 WARN("Handle %d is not a stateblock, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5957 LeaveCriticalSection(&ddraw_cs);
5958 return D3DERR_INVALIDSTATEBLOCK;
5961 hr = IWineD3DStateBlock_Apply((IWineD3DStateBlock *) This->Handles[BlockHandle - 1].ptr);
5962 LeaveCriticalSection(&ddraw_cs);
5963 return hr_ddraw_from_wined3d(hr);
5966 static HRESULT WINAPI
5967 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5968 DWORD BlockHandle)
5970 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5973 static HRESULT WINAPI
5974 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5975 DWORD BlockHandle)
5977 HRESULT hr;
5978 WORD old_fpucw;
5980 old_fpucw = d3d_fpu_setup();
5981 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5982 set_fpu_control_word(old_fpucw);
5984 return hr;
5987 /*****************************************************************************
5988 * IDirect3DDevice7::CaptureStateBlock
5990 * Updates a stateblock's values to the values currently set for the device
5992 * Version 7
5994 * Params:
5995 * BlockHandle: Stateblock to update
5997 * Returns:
5998 * D3D_OK on success
5999 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
6000 * See IWineD3DDevice::CaptureStateBlock for more details
6002 *****************************************************************************/
6003 static HRESULT
6004 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
6005 DWORD BlockHandle)
6007 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6008 HRESULT hr;
6009 TRACE("(%p)->(%08x): Relay!\n", This, BlockHandle);
6011 EnterCriticalSection(&ddraw_cs);
6012 if(BlockHandle == 0 || BlockHandle > This->numHandles)
6014 WARN("Out of range handle %d, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
6015 LeaveCriticalSection(&ddraw_cs);
6016 return D3DERR_INVALIDSTATEBLOCK;
6018 if(This->Handles[BlockHandle - 1].type != DDrawHandle_StateBlock)
6020 WARN("Handle %d is not a stateblock, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
6021 LeaveCriticalSection(&ddraw_cs);
6022 return D3DERR_INVALIDSTATEBLOCK;
6025 hr = IWineD3DStateBlock_Capture((IWineD3DStateBlock *) This->Handles[BlockHandle - 1].ptr);
6026 LeaveCriticalSection(&ddraw_cs);
6027 return hr_ddraw_from_wined3d(hr);
6030 static HRESULT WINAPI
6031 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
6032 DWORD BlockHandle)
6034 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
6037 static HRESULT WINAPI
6038 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
6039 DWORD BlockHandle)
6041 HRESULT hr;
6042 WORD old_fpucw;
6044 old_fpucw = d3d_fpu_setup();
6045 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
6046 set_fpu_control_word(old_fpucw);
6048 return hr;
6051 /*****************************************************************************
6052 * IDirect3DDevice7::DeleteStateBlock
6054 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
6056 * Version 7
6058 * Params:
6059 * BlockHandle: Stateblock handle to delete
6061 * Returns:
6062 * D3D_OK on success
6063 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
6065 *****************************************************************************/
6066 static HRESULT
6067 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
6068 DWORD BlockHandle)
6070 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6071 ULONG ref;
6072 TRACE("(%p)->(%08x): Relay!\n", This, BlockHandle);
6074 EnterCriticalSection(&ddraw_cs);
6075 if(BlockHandle == 0 || BlockHandle > This->numHandles)
6077 WARN("Out of range handle %d, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
6078 LeaveCriticalSection(&ddraw_cs);
6079 return D3DERR_INVALIDSTATEBLOCK;
6081 if(This->Handles[BlockHandle - 1].type != DDrawHandle_StateBlock)
6083 WARN("Handle %d is not a stateblock, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
6084 LeaveCriticalSection(&ddraw_cs);
6085 return D3DERR_INVALIDSTATEBLOCK;
6088 ref = IWineD3DStateBlock_Release((IWineD3DStateBlock *) This->Handles[BlockHandle - 1].ptr);
6089 if(ref)
6091 ERR("Something is still holding the stateblock %p(Handle %d). Ref = %d\n", This->Handles[BlockHandle - 1].ptr, BlockHandle, ref);
6093 This->Handles[BlockHandle - 1].ptr = NULL;
6094 This->Handles[BlockHandle - 1].type = DDrawHandle_Unknown;
6096 LeaveCriticalSection(&ddraw_cs);
6097 return D3D_OK;
6100 static HRESULT WINAPI
6101 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
6102 DWORD BlockHandle)
6104 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
6107 static HRESULT WINAPI
6108 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
6109 DWORD BlockHandle)
6111 HRESULT hr;
6112 WORD old_fpucw;
6114 old_fpucw = d3d_fpu_setup();
6115 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
6116 set_fpu_control_word(old_fpucw);
6118 return hr;
6121 /*****************************************************************************
6122 * IDirect3DDevice7::CreateStateBlock
6124 * Creates a new state block handle.
6126 * Version 7
6128 * Params:
6129 * Type: The state block type
6130 * BlockHandle: Address to write the created handle to
6132 * Returns:
6133 * D3D_OK on success
6134 * DDERR_INVALIDPARAMS if BlockHandle is NULL
6136 *****************************************************************************/
6137 static HRESULT
6138 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
6139 D3DSTATEBLOCKTYPE Type,
6140 DWORD *BlockHandle)
6142 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6143 HRESULT hr;
6144 TRACE("(%p)->(%08x,%p)!\n", This, Type, BlockHandle);
6146 if(!BlockHandle)
6148 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
6149 return DDERR_INVALIDPARAMS;
6151 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
6152 Type != D3DSBT_VERTEXSTATE ) {
6153 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
6154 return DDERR_INVALIDPARAMS;
6157 EnterCriticalSection(&ddraw_cs);
6158 *BlockHandle = IDirect3DDeviceImpl_CreateHandle(This);
6159 if(!*BlockHandle)
6161 ERR("Cannot get a handle number for the stateblock\n");
6162 LeaveCriticalSection(&ddraw_cs);
6163 return DDERR_OUTOFMEMORY;
6165 This->Handles[*BlockHandle - 1].type = DDrawHandle_StateBlock;
6167 /* The D3DSTATEBLOCKTYPE enum is fine here */
6168 hr = IWineD3DDevice_CreateStateBlock(This->wineD3DDevice,
6169 Type,
6170 (IWineD3DStateBlock **) &This->Handles[*BlockHandle - 1].ptr,
6171 NULL /* Parent, hope that works */);
6172 LeaveCriticalSection(&ddraw_cs);
6173 return hr_ddraw_from_wined3d(hr);
6176 static HRESULT WINAPI
6177 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
6178 D3DSTATEBLOCKTYPE Type,
6179 DWORD *BlockHandle)
6181 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6184 static HRESULT WINAPI
6185 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
6186 D3DSTATEBLOCKTYPE Type,
6187 DWORD *BlockHandle)
6189 HRESULT hr;
6190 WORD old_fpucw;
6192 old_fpucw = d3d_fpu_setup();
6193 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6194 set_fpu_control_word(old_fpucw);
6196 return hr;
6199 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6200 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
6201 IDirectDrawSurfaceImpl *src)
6203 IDirectDrawSurfaceImpl *src_level, *dest_level;
6204 IDirectDrawSurface7 *temp;
6205 DDSURFACEDESC2 ddsd;
6206 BOOL levelFound; /* at least one suitable sublevel in dest found */
6208 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
6209 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
6210 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
6212 levelFound = FALSE;
6214 src_level = src;
6215 dest_level = dest;
6217 for (;src_level && dest_level;)
6219 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6220 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6222 levelFound = TRUE;
6224 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6225 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6226 IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(dest_level, IDirectDrawSurface7), &ddsd.ddsCaps, &temp);
6228 if (dest_level != dest) IDirectDrawSurface7_Release(ICOM_INTERFACE(dest_level, IDirectDrawSurface7));
6230 dest_level = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, temp);
6233 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6234 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6235 IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(src_level, IDirectDrawSurface7), &ddsd.ddsCaps, &temp);
6237 if (src_level != src) IDirectDrawSurface7_Release(ICOM_INTERFACE(src_level, IDirectDrawSurface7));
6239 src_level = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, temp);
6242 if (src_level && src_level != src) IDirectDrawSurface7_Release(ICOM_INTERFACE(src_level, IDirectDrawSurface7));
6243 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(ICOM_INTERFACE(dest_level, IDirectDrawSurface7));
6245 return !dest_level && levelFound;
6248 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6249 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
6250 IDirectDrawSurfaceImpl *dest,
6251 IDirectDrawSurfaceImpl *src,
6252 POINT *DestPoint,
6253 RECT *SrcRect)
6255 IDirectDrawSurfaceImpl *src_level, *dest_level;
6256 IDirectDrawSurface7 *temp;
6257 DDSURFACEDESC2 ddsd;
6258 POINT point;
6259 RECT rect;
6260 HRESULT hr;
6261 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
6262 DWORD ckeyflag;
6263 DDCOLORKEY ddckey;
6264 BOOL palette_missing = FALSE;
6266 /* Copy palette, if possible. */
6267 IDirectDrawSurface7_GetPalette(ICOM_INTERFACE(src, IDirectDrawSurface7), &pal_src);
6268 IDirectDrawSurface7_GetPalette(ICOM_INTERFACE(dest, IDirectDrawSurface7), &pal);
6270 if (pal_src != NULL && pal != NULL)
6272 PALETTEENTRY palent[256];
6274 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
6275 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
6278 if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
6279 DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
6281 palette_missing = TRUE;
6284 if (pal) IDirectDrawPalette_Release(pal);
6285 if (pal_src) IDirectDrawPalette_Release(pal_src);
6287 /* Copy colorkeys, if present. */
6288 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6290 hr = IDirectDrawSurface7_GetColorKey(ICOM_INTERFACE(src, IDirectDrawSurface7), ckeyflag, &ddckey);
6292 if (SUCCEEDED(hr))
6294 IDirectDrawSurface7_SetColorKey(ICOM_INTERFACE(dest, IDirectDrawSurface7), ckeyflag, &ddckey);
6298 src_level = src;
6299 dest_level = dest;
6301 point = *DestPoint;
6302 rect = *SrcRect;
6304 for (;src_level && dest_level;)
6306 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6307 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6309 /* Try UpdateSurface that may perform a more direct opengl loading. But skip this if destination is paletted texture and has no palette.
6310 * Some games like Sacrifice set palette after Load, and it is a waste of effort to try to load texture without palette and generates
6311 * warnings in wined3d. */
6312 if (!palette_missing)
6313 hr = IWineD3DDevice_UpdateSurface(device->wineD3DDevice, src_level->WineD3DSurface, &rect, dest_level->WineD3DSurface,
6314 &point);
6316 if (palette_missing || FAILED(hr))
6318 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
6319 IWineD3DSurface_BltFast(dest_level->WineD3DSurface,
6320 point.x, point.y,
6321 src_level->WineD3DSurface, &rect, 0);
6324 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6325 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6326 IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(dest_level, IDirectDrawSurface7), &ddsd.ddsCaps, &temp);
6328 if (dest_level != dest) IDirectDrawSurface7_Release(ICOM_INTERFACE(dest_level, IDirectDrawSurface7));
6330 dest_level = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, temp);
6333 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6334 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6335 IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(src_level, IDirectDrawSurface7), &ddsd.ddsCaps, &temp);
6337 if (src_level != src) IDirectDrawSurface7_Release(ICOM_INTERFACE(src_level, IDirectDrawSurface7));
6339 src_level = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, temp);
6341 point.x /= 2;
6342 point.y /= 2;
6344 rect.top /= 2;
6345 rect.left /= 2;
6346 rect.right = (rect.right + 1) / 2;
6347 rect.bottom = (rect.bottom + 1) / 2;
6350 if (src_level && src_level != src) IDirectDrawSurface7_Release(ICOM_INTERFACE(src_level, IDirectDrawSurface7));
6351 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(ICOM_INTERFACE(dest_level, IDirectDrawSurface7));
6354 /*****************************************************************************
6355 * IDirect3DDevice7::Load
6357 * Loads a rectangular area from the source into the destination texture.
6358 * It can also copy the source to the faces of a cubic environment map
6360 * Version 7
6362 * Params:
6363 * DestTex: Destination texture
6364 * DestPoint: Point in the destination where the source image should be
6365 * written to
6366 * SrcTex: Source texture
6367 * SrcRect: Source rectangle
6368 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6369 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6370 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6372 * Returns:
6373 * D3D_OK on success
6374 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6377 *****************************************************************************/
6379 static HRESULT
6380 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6381 IDirectDrawSurface7 *DestTex,
6382 POINT *DestPoint,
6383 IDirectDrawSurface7 *SrcTex,
6384 RECT *SrcRect,
6385 DWORD Flags)
6387 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6388 IDirectDrawSurfaceImpl *dest = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, DestTex);
6389 IDirectDrawSurfaceImpl *src = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, SrcTex);
6390 POINT destpoint;
6391 RECT srcrect;
6392 TRACE("(%p)->(%p,%p,%p,%p,%08x)\n", This, dest, DestPoint, src, SrcRect, Flags);
6394 if( (!src) || (!dest) )
6395 return DDERR_INVALIDPARAMS;
6397 EnterCriticalSection(&ddraw_cs);
6399 if (SrcRect) srcrect = *SrcRect;
6400 else
6402 srcrect.left = srcrect.top = 0;
6403 srcrect.right = src->surface_desc.dwWidth;
6404 srcrect.bottom = src->surface_desc.dwHeight;
6407 if (DestPoint) destpoint = *DestPoint;
6408 else
6410 destpoint.x = destpoint.y = 0;
6412 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6413 * destination can be a subset of mip levels, in which case actual coordinates used
6414 * for it may be divided. If any dimension of dest is larger than source, it can't be
6415 * mip level subset, so an error can be returned early.
6417 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6418 srcrect.right > src->surface_desc.dwWidth ||
6419 srcrect.bottom > src->surface_desc.dwHeight ||
6420 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6421 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6422 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6423 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6425 LeaveCriticalSection(&ddraw_cs);
6426 return DDERR_INVALIDPARAMS;
6429 /* Must be top level surfaces. */
6430 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6431 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6433 LeaveCriticalSection(&ddraw_cs);
6434 return DDERR_INVALIDPARAMS;
6437 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6439 DWORD src_face_flag, dest_face_flag;
6440 IDirectDrawSurfaceImpl *src_face, *dest_face;
6441 IDirectDrawSurface7 *temp;
6442 DDSURFACEDESC2 ddsd;
6443 int i;
6445 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6447 LeaveCriticalSection(&ddraw_cs);
6448 return DDERR_INVALIDPARAMS;
6451 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6452 * time it's actual surface loading. */
6453 for (i = 0; i < 2; i++)
6455 dest_face = dest;
6456 src_face = src;
6458 for (;dest_face && src_face;)
6460 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6461 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6463 if (src_face_flag == dest_face_flag)
6465 if (i == 0)
6467 /* Destination mip levels must be subset of source mip levels. */
6468 if (!is_mip_level_subset(dest_face, src_face))
6470 LeaveCriticalSection(&ddraw_cs);
6471 return DDERR_INVALIDPARAMS;
6474 else if (Flags & dest_face_flag)
6476 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6479 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6481 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6482 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6483 IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(src, IDirectDrawSurface7), &ddsd.ddsCaps, &temp);
6485 if (src_face != src) IDirectDrawSurface7_Release(ICOM_INTERFACE(src_face, IDirectDrawSurface7));
6487 src_face = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, temp);
6489 else
6491 if (src_face != src) IDirectDrawSurface7_Release(ICOM_INTERFACE(src_face, IDirectDrawSurface7));
6493 src_face = NULL;
6497 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6499 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6500 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6501 IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(dest, IDirectDrawSurface7), &ddsd.ddsCaps, &temp);
6503 if (dest_face != dest) IDirectDrawSurface7_Release(ICOM_INTERFACE(dest_face, IDirectDrawSurface7));
6505 dest_face = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, temp);
6507 else
6509 if (dest_face != dest) IDirectDrawSurface7_Release(ICOM_INTERFACE(dest_face, IDirectDrawSurface7));
6511 dest_face = NULL;
6515 if (i == 0)
6517 /* Native returns error if src faces are not subset of dest faces. */
6518 if (src_face)
6520 LeaveCriticalSection(&ddraw_cs);
6521 return DDERR_INVALIDPARAMS;
6526 LeaveCriticalSection(&ddraw_cs);
6527 return D3D_OK;
6529 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6531 LeaveCriticalSection(&ddraw_cs);
6532 return DDERR_INVALIDPARAMS;
6535 /* Handle non cube map textures. */
6537 /* Destination mip levels must be subset of source mip levels. */
6538 if (!is_mip_level_subset(dest, src))
6540 LeaveCriticalSection(&ddraw_cs);
6541 return DDERR_INVALIDPARAMS;
6544 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6546 LeaveCriticalSection(&ddraw_cs);
6547 return D3D_OK;
6550 static HRESULT WINAPI
6551 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6552 IDirectDrawSurface7 *DestTex,
6553 POINT *DestPoint,
6554 IDirectDrawSurface7 *SrcTex,
6555 RECT *SrcRect,
6556 DWORD Flags)
6558 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6561 static HRESULT WINAPI
6562 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6563 IDirectDrawSurface7 *DestTex,
6564 POINT *DestPoint,
6565 IDirectDrawSurface7 *SrcTex,
6566 RECT *SrcRect,
6567 DWORD Flags)
6569 HRESULT hr;
6570 WORD old_fpucw;
6572 old_fpucw = d3d_fpu_setup();
6573 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6574 set_fpu_control_word(old_fpucw);
6576 return hr;
6579 /*****************************************************************************
6580 * IDirect3DDevice7::LightEnable
6582 * Enables or disables a light
6584 * Version 7, IDirect3DLight uses this method too.
6586 * Params:
6587 * LightIndex: The index of the light to enable / disable
6588 * Enable: Enable or disable the light
6590 * Returns:
6591 * D3D_OK on success
6592 * For more details, see IWineD3DDevice::SetLightEnable
6594 *****************************************************************************/
6595 static HRESULT
6596 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6597 DWORD LightIndex,
6598 BOOL Enable)
6600 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6601 HRESULT hr;
6602 TRACE("(%p)->(%08x,%d): Relay!\n", This, LightIndex, Enable);
6604 EnterCriticalSection(&ddraw_cs);
6605 hr = IWineD3DDevice_SetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6606 LeaveCriticalSection(&ddraw_cs);
6607 return hr_ddraw_from_wined3d(hr);
6610 static HRESULT WINAPI
6611 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6612 DWORD LightIndex,
6613 BOOL Enable)
6615 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6618 static HRESULT WINAPI
6619 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6620 DWORD LightIndex,
6621 BOOL Enable)
6623 HRESULT hr;
6624 WORD old_fpucw;
6626 old_fpucw = d3d_fpu_setup();
6627 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6628 set_fpu_control_word(old_fpucw);
6630 return hr;
6633 /*****************************************************************************
6634 * IDirect3DDevice7::GetLightEnable
6636 * Retrieves if the light with the given index is enabled or not
6638 * Version 7
6640 * Params:
6641 * LightIndex: Index of desired light
6642 * Enable: Pointer to a BOOL which contains the result
6644 * Returns:
6645 * D3D_OK on success
6646 * DDERR_INVALIDPARAMS if Enable is NULL
6647 * See IWineD3DDevice::GetLightEnable for more details
6649 *****************************************************************************/
6650 static HRESULT
6651 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6652 DWORD LightIndex,
6653 BOOL* Enable)
6655 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6656 HRESULT hr;
6657 TRACE("(%p)->(%08x,%p): Relay\n", This, LightIndex, Enable);
6659 if(!Enable)
6660 return DDERR_INVALIDPARAMS;
6662 EnterCriticalSection(&ddraw_cs);
6663 hr = IWineD3DDevice_GetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6664 LeaveCriticalSection(&ddraw_cs);
6665 return hr_ddraw_from_wined3d(hr);
6668 static HRESULT WINAPI
6669 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6670 DWORD LightIndex,
6671 BOOL* Enable)
6673 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6676 static HRESULT WINAPI
6677 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6678 DWORD LightIndex,
6679 BOOL* Enable)
6681 HRESULT hr;
6682 WORD old_fpucw;
6684 old_fpucw = d3d_fpu_setup();
6685 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6686 set_fpu_control_word(old_fpucw);
6688 return hr;
6691 /*****************************************************************************
6692 * IDirect3DDevice7::SetClipPlane
6694 * Sets custom clipping plane
6696 * Version 7
6698 * Params:
6699 * Index: The index of the clipping plane
6700 * PlaneEquation: An equation defining the clipping plane
6702 * Returns:
6703 * D3D_OK on success
6704 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6705 * See IWineD3DDevice::SetClipPlane for more details
6707 *****************************************************************************/
6708 static HRESULT
6709 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6710 DWORD Index,
6711 D3DVALUE* PlaneEquation)
6713 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6714 HRESULT hr;
6715 TRACE("(%p)->(%08x,%p): Relay!\n", This, Index, PlaneEquation);
6717 if(!PlaneEquation)
6718 return DDERR_INVALIDPARAMS;
6720 EnterCriticalSection(&ddraw_cs);
6721 hr = IWineD3DDevice_SetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6722 LeaveCriticalSection(&ddraw_cs);
6723 return hr;
6726 static HRESULT WINAPI
6727 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6728 DWORD Index,
6729 D3DVALUE* PlaneEquation)
6731 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6734 static HRESULT WINAPI
6735 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6736 DWORD Index,
6737 D3DVALUE* PlaneEquation)
6739 HRESULT hr;
6740 WORD old_fpucw;
6742 old_fpucw = d3d_fpu_setup();
6743 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6744 set_fpu_control_word(old_fpucw);
6746 return hr;
6749 /*****************************************************************************
6750 * IDirect3DDevice7::GetClipPlane
6752 * Returns the clipping plane with a specific index
6754 * Params:
6755 * Index: The index of the desired plane
6756 * PlaneEquation: Address to store the plane equation to
6758 * Returns:
6759 * D3D_OK on success
6760 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6761 * See IWineD3DDevice::GetClipPlane for more details
6763 *****************************************************************************/
6764 static HRESULT
6765 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6766 DWORD Index,
6767 D3DVALUE* PlaneEquation)
6769 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6770 HRESULT hr;
6771 TRACE("(%p)->(%d,%p): Relay!\n", This, Index, PlaneEquation);
6773 if(!PlaneEquation)
6774 return DDERR_INVALIDPARAMS;
6776 EnterCriticalSection(&ddraw_cs);
6777 hr = IWineD3DDevice_GetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6778 LeaveCriticalSection(&ddraw_cs);
6779 return hr;
6782 static HRESULT WINAPI
6783 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6784 DWORD Index,
6785 D3DVALUE* PlaneEquation)
6787 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6790 static HRESULT WINAPI
6791 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6792 DWORD Index,
6793 D3DVALUE* PlaneEquation)
6795 HRESULT hr;
6796 WORD old_fpucw;
6798 old_fpucw = d3d_fpu_setup();
6799 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6800 set_fpu_control_word(old_fpucw);
6802 return hr;
6805 /*****************************************************************************
6806 * IDirect3DDevice7::GetInfo
6808 * Retrieves some information about the device. The DirectX sdk says that
6809 * this version returns S_FALSE for all retail builds of DirectX, that's what
6810 * this implementation does.
6812 * Params:
6813 * DevInfoID: Information type requested
6814 * DevInfoStruct: Pointer to a structure to store the info to
6815 * Size: Size of the structure
6817 * Returns:
6818 * S_FALSE, because it's a non-debug driver
6820 *****************************************************************************/
6821 static HRESULT WINAPI
6822 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6823 DWORD DevInfoID,
6824 void *DevInfoStruct,
6825 DWORD Size)
6827 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6828 TRACE("(%p)->(%08x,%p,%08x)\n", This, DevInfoID, DevInfoStruct, Size);
6830 if (TRACE_ON(d3d7))
6832 TRACE(" info requested : ");
6833 switch (DevInfoID)
6835 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6836 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6837 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6838 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6842 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6845 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6846 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6847 * are not duplicated.
6849 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6850 * has already been setup for optimal d3d operation.
6852 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6853 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6854 * by Sacrifice (game). */
6855 const IDirect3DDevice7Vtbl IDirect3DDevice7_FPUSetup_Vtbl =
6857 /*** IUnknown Methods ***/
6858 IDirect3DDeviceImpl_7_QueryInterface,
6859 IDirect3DDeviceImpl_7_AddRef,
6860 IDirect3DDeviceImpl_7_Release,
6861 /*** IDirect3DDevice7 ***/
6862 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6863 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6864 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6865 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6866 IDirect3DDeviceImpl_7_GetDirect3D,
6867 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6868 IDirect3DDeviceImpl_7_GetRenderTarget,
6869 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6870 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6871 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6872 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6873 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6874 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6875 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6876 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6877 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6878 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6879 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6880 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6881 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6882 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6883 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6884 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6885 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6886 IDirect3DDeviceImpl_7_SetClipStatus,
6887 IDirect3DDeviceImpl_7_GetClipStatus,
6888 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6889 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6890 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6891 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6892 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6893 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6894 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6895 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6896 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6897 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6898 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6899 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6900 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6901 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6902 IDirect3DDeviceImpl_7_Load_FPUSetup,
6903 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6904 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6905 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6906 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6907 IDirect3DDeviceImpl_7_GetInfo
6910 const IDirect3DDevice7Vtbl IDirect3DDevice7_FPUPreserve_Vtbl =
6912 /*** IUnknown Methods ***/
6913 IDirect3DDeviceImpl_7_QueryInterface,
6914 IDirect3DDeviceImpl_7_AddRef,
6915 IDirect3DDeviceImpl_7_Release,
6916 /*** IDirect3DDevice7 ***/
6917 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6918 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6919 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6920 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6921 IDirect3DDeviceImpl_7_GetDirect3D,
6922 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6923 IDirect3DDeviceImpl_7_GetRenderTarget,
6924 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6925 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6926 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6927 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6928 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6929 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6930 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6931 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6932 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6933 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6934 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6935 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6936 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6937 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6938 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6939 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6940 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6941 IDirect3DDeviceImpl_7_SetClipStatus,
6942 IDirect3DDeviceImpl_7_GetClipStatus,
6943 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6944 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6945 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6946 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6947 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6948 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6949 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6950 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6951 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6952 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6953 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6954 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6955 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6956 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6957 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6958 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6959 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6960 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6961 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6962 IDirect3DDeviceImpl_7_GetInfo
6965 const IDirect3DDevice3Vtbl IDirect3DDevice3_Vtbl =
6967 /*** IUnknown Methods ***/
6968 Thunk_IDirect3DDeviceImpl_3_QueryInterface,
6969 Thunk_IDirect3DDeviceImpl_3_AddRef,
6970 Thunk_IDirect3DDeviceImpl_3_Release,
6971 /*** IDirect3DDevice3 ***/
6972 IDirect3DDeviceImpl_3_GetCaps,
6973 IDirect3DDeviceImpl_3_GetStats,
6974 IDirect3DDeviceImpl_3_AddViewport,
6975 IDirect3DDeviceImpl_3_DeleteViewport,
6976 IDirect3DDeviceImpl_3_NextViewport,
6977 Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
6978 Thunk_IDirect3DDeviceImpl_3_BeginScene,
6979 Thunk_IDirect3DDeviceImpl_3_EndScene,
6980 Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
6981 IDirect3DDeviceImpl_3_SetCurrentViewport,
6982 IDirect3DDeviceImpl_3_GetCurrentViewport,
6983 Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
6984 Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
6985 IDirect3DDeviceImpl_3_Begin,
6986 IDirect3DDeviceImpl_3_BeginIndexed,
6987 IDirect3DDeviceImpl_3_Vertex,
6988 IDirect3DDeviceImpl_3_Index,
6989 IDirect3DDeviceImpl_3_End,
6990 IDirect3DDeviceImpl_3_GetRenderState,
6991 IDirect3DDeviceImpl_3_SetRenderState,
6992 IDirect3DDeviceImpl_3_GetLightState,
6993 IDirect3DDeviceImpl_3_SetLightState,
6994 Thunk_IDirect3DDeviceImpl_3_SetTransform,
6995 Thunk_IDirect3DDeviceImpl_3_GetTransform,
6996 Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
6997 Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
6998 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6999 Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
7000 Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
7001 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
7002 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
7003 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
7004 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
7005 Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
7006 Thunk_IDirect3DDeviceImpl_3_GetTexture,
7007 IDirect3DDeviceImpl_3_SetTexture,
7008 Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
7009 Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
7010 Thunk_IDirect3DDeviceImpl_3_ValidateDevice
7013 const IDirect3DDevice2Vtbl IDirect3DDevice2_Vtbl =
7015 /*** IUnknown Methods ***/
7016 Thunk_IDirect3DDeviceImpl_2_QueryInterface,
7017 Thunk_IDirect3DDeviceImpl_2_AddRef,
7018 Thunk_IDirect3DDeviceImpl_2_Release,
7019 /*** IDirect3DDevice2 ***/
7020 Thunk_IDirect3DDeviceImpl_2_GetCaps,
7021 IDirect3DDeviceImpl_2_SwapTextureHandles,
7022 Thunk_IDirect3DDeviceImpl_2_GetStats,
7023 Thunk_IDirect3DDeviceImpl_2_AddViewport,
7024 Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
7025 Thunk_IDirect3DDeviceImpl_2_NextViewport,
7026 IDirect3DDeviceImpl_2_EnumTextureFormats,
7027 Thunk_IDirect3DDeviceImpl_2_BeginScene,
7028 Thunk_IDirect3DDeviceImpl_2_EndScene,
7029 Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
7030 Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
7031 Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
7032 Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
7033 Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
7034 Thunk_IDirect3DDeviceImpl_2_Begin,
7035 Thunk_IDirect3DDeviceImpl_2_BeginIndexed,
7036 Thunk_IDirect3DDeviceImpl_2_Vertex,
7037 Thunk_IDirect3DDeviceImpl_2_Index,
7038 Thunk_IDirect3DDeviceImpl_2_End,
7039 Thunk_IDirect3DDeviceImpl_2_GetRenderState,
7040 Thunk_IDirect3DDeviceImpl_2_SetRenderState,
7041 Thunk_IDirect3DDeviceImpl_2_GetLightState,
7042 Thunk_IDirect3DDeviceImpl_2_SetLightState,
7043 Thunk_IDirect3DDeviceImpl_2_SetTransform,
7044 Thunk_IDirect3DDeviceImpl_2_GetTransform,
7045 Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
7046 Thunk_IDirect3DDeviceImpl_2_DrawPrimitive,
7047 Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
7048 Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
7049 Thunk_IDirect3DDeviceImpl_2_GetClipStatus
7052 const IDirect3DDeviceVtbl IDirect3DDevice1_Vtbl =
7054 /*** IUnknown Methods ***/
7055 Thunk_IDirect3DDeviceImpl_1_QueryInterface,
7056 Thunk_IDirect3DDeviceImpl_1_AddRef,
7057 Thunk_IDirect3DDeviceImpl_1_Release,
7058 /*** IDirect3DDevice1 ***/
7059 IDirect3DDeviceImpl_1_Initialize,
7060 Thunk_IDirect3DDeviceImpl_1_GetCaps,
7061 Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
7062 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
7063 Thunk_IDirect3DDeviceImpl_1_GetStats,
7064 IDirect3DDeviceImpl_1_Execute,
7065 Thunk_IDirect3DDeviceImpl_1_AddViewport,
7066 Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
7067 Thunk_IDirect3DDeviceImpl_1_NextViewport,
7068 IDirect3DDeviceImpl_1_Pick,
7069 IDirect3DDeviceImpl_1_GetPickRecords,
7070 Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
7071 IDirect3DDeviceImpl_1_CreateMatrix,
7072 IDirect3DDeviceImpl_1_SetMatrix,
7073 IDirect3DDeviceImpl_1_GetMatrix,
7074 IDirect3DDeviceImpl_1_DeleteMatrix,
7075 Thunk_IDirect3DDeviceImpl_1_BeginScene,
7076 Thunk_IDirect3DDeviceImpl_1_EndScene,
7077 Thunk_IDirect3DDeviceImpl_1_GetDirect3D
7080 /*****************************************************************************
7081 * IDirect3DDeviceImpl_CreateHandle
7083 * Not called from the VTable
7085 * Some older interface versions operate with handles, which are basically
7086 * DWORDs which identify an interface, for example
7087 * IDirect3DDevice::SetRenderState with DIRECT3DRENDERSTATE_TEXTUREHANDLE
7089 * Those handle could be just casts to the interface pointers or vice versa,
7090 * but that is not 64 bit safe and would mean blindly derefering a DWORD
7091 * passed by the app. Instead there is a dynamic array in the device which
7092 * keeps a DWORD to pointer information and a type for the handle.
7094 * Basically this array only grows, when a handle is freed its pointer is
7095 * just set to NULL. There will be much more reads from the array than
7096 * insertion operations, so a dynamic array is fine.
7098 * Params:
7099 * This: D3DDevice implementation for which this handle should be created
7101 * Returns:
7102 * A free handle on success
7103 * 0 on failure
7105 *****************************************************************************/
7106 DWORD
7107 IDirect3DDeviceImpl_CreateHandle(IDirect3DDeviceImpl *This)
7109 DWORD i;
7110 struct HandleEntry *oldHandles = This->Handles;
7112 TRACE("(%p)\n", This);
7114 for(i = 0; i < This->numHandles; i++)
7116 if(This->Handles[i].ptr == NULL &&
7117 This->Handles[i].type == DDrawHandle_Unknown)
7119 TRACE("Reusing freed handle %d\n", i + 1);
7120 return i + 1;
7124 TRACE("Growing the handle array\n");
7126 This->numHandles++;
7127 This->Handles = HeapAlloc(GetProcessHeap(), 0, sizeof(struct HandleEntry) * This->numHandles);
7128 if(!This->Handles)
7130 ERR("Out of memory\n");
7131 This->Handles = oldHandles;
7132 This->numHandles--;
7133 return 0;
7135 if(oldHandles)
7137 memcpy(This->Handles, oldHandles, (This->numHandles - 1) * sizeof(struct HandleEntry));
7138 HeapFree(GetProcessHeap(), 0, oldHandles);
7141 TRACE("Returning %d\n", This->numHandles);
7142 return This->numHandles;
7145 /*****************************************************************************
7146 * IDirect3DDeviceImpl_UpdateDepthStencil
7148 * Checks the current render target for attached depth stencils and sets the
7149 * WineD3D depth stencil accordingly.
7151 * Returns:
7152 * The depth stencil state to set if creating the device
7154 *****************************************************************************/
7155 WINED3DZBUFFERTYPE
7156 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
7158 IDirectDrawSurface7 *depthStencil = NULL;
7159 IDirectDrawSurfaceImpl *dsi;
7160 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
7162 IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(This->target, IDirectDrawSurface7),
7163 &depthcaps,
7164 &depthStencil);
7165 if(!depthStencil)
7167 TRACE("Setting wined3d depth stencil to NULL\n");
7168 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
7169 NULL);
7170 return WINED3DZB_FALSE;
7173 dsi = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, depthStencil);
7174 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->WineD3DSurface);
7175 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
7176 dsi->WineD3DSurface);
7178 IDirectDrawSurface7_Release(depthStencil);
7179 return WINED3DZB_TRUE;