wined3d: Move position_transformed out of u.s in struct WineDirect3DVertexStridedData.
[wine/multimedia.git] / dlls / ddraw / device.c
blobd35a297dfbc63d94b52c75f333658e0cfcedcc09
1 /*
2 * Copyright (c) 1998-2004 Lionel Ulmer
3 * Copyright (c) 2002-2005 Christian Costa
4 * Copyright (c) 2006 Stefan Dösinger
5 * Copyright (c) 2008 Alexander Dorofeyev
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * IDirect3DDevice implementation, version 1, 2, 3 and 7. Rendering is relayed
22 * to WineD3D, some minimal DirectDraw specific management is handled here.
23 * The Direct3DDevice is NOT the parent of the WineD3DDevice, because d3d
24 * is initialized when DirectDraw creates the primary surface.
25 * Some type management is necessary, because some D3D types changed between
26 * D3D7 and D3D9.
30 #include "config.h"
31 #include "wine/port.h"
33 #include <assert.h>
34 #include <stdarg.h>
35 #include <string.h>
36 #include <stdlib.h>
38 #define COBJMACROS
39 #define NONAMELESSUNION
41 #include "windef.h"
42 #include "winbase.h"
43 #include "winerror.h"
44 #include "wingdi.h"
45 #include "wine/exception.h"
47 #include "ddraw.h"
48 #include "d3d.h"
50 #include "ddraw_private.h"
51 #include "wine/debug.h"
53 WINE_DEFAULT_DEBUG_CHANNEL(d3d7);
54 WINE_DECLARE_DEBUG_CHANNEL(ddraw_thunk);
56 /* The device ID */
57 const GUID IID_D3DDEVICE_WineD3D = {
58 0xaef72d43,
59 0xb09a,
60 0x4b7b,
61 { 0xb7,0x98,0xc6,0x8a,0x77,0x2d,0x72,0x2a }
64 static inline void set_fpu_control_word(WORD fpucw)
66 #if defined(__i386__) && defined(__GNUC__)
67 __asm__ volatile ("fldcw %0" : : "m" (fpucw));
68 #elif defined(__i386__) && defined(_MSC_VER)
69 __asm fldcw fpucw;
70 #endif
73 static inline WORD d3d_fpu_setup(void)
75 WORD oldcw;
77 #if defined(__i386__) && defined(__GNUC__)
78 __asm__ volatile ("fnstcw %0" : "=m" (oldcw));
79 #elif defined(__i386__) && defined(_MSC_VER)
80 __asm fnstcw oldcw;
81 #else
82 static BOOL warned = FALSE;
83 if(!warned)
85 FIXME("FPUPRESERVE not implemented for this platform / compiler\n");
86 warned = TRUE;
88 #endif
90 set_fpu_control_word(0x37f);
92 return oldcw;
95 /*****************************************************************************
96 * IUnknown Methods. Common for Version 1, 2, 3 and 7
97 *****************************************************************************/
99 /*****************************************************************************
100 * IDirect3DDevice7::QueryInterface
102 * Used to query other interfaces from a Direct3DDevice interface.
103 * It can return interface pointers to all Direct3DDevice versions as well
104 * as IDirectDraw and IDirect3D. For a link to QueryInterface
105 * rules see ddraw.c, IDirectDraw7::QueryInterface
107 * Exists in Version 1, 2, 3 and 7
109 * Params:
110 * refiid: Interface ID queried for
111 * obj: Used to return the interface pointer
113 * Returns:
114 * D3D_OK or E_NOINTERFACE
116 *****************************************************************************/
117 static HRESULT WINAPI
118 IDirect3DDeviceImpl_7_QueryInterface(IDirect3DDevice7 *iface,
119 REFIID refiid,
120 void **obj)
122 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
123 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(refiid), obj);
125 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
126 *obj = NULL;
128 if(!refiid)
129 return DDERR_INVALIDPARAMS;
131 if ( IsEqualGUID( &IID_IUnknown, refiid ) )
133 *obj = ICOM_INTERFACE(This, IDirect3DDevice7);
136 /* Check DirectDraw Interfac\x01s */
137 else if( IsEqualGUID( &IID_IDirectDraw7, refiid ) )
139 *obj = ICOM_INTERFACE(This->ddraw, IDirectDraw7);
140 TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
142 else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
144 *obj = ICOM_INTERFACE(This->ddraw, IDirectDraw4);
145 TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
147 else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
149 *obj = ICOM_INTERFACE(This->ddraw, IDirectDraw2);
150 TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
152 else if( IsEqualGUID( &IID_IDirectDraw, refiid ) )
154 *obj = ICOM_INTERFACE(This->ddraw, IDirectDraw);
155 TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
158 /* Direct3D */
159 else if ( IsEqualGUID( &IID_IDirect3D , refiid ) )
161 *obj = ICOM_INTERFACE(This->ddraw, IDirect3D);
162 TRACE("(%p) Returning IDirect3D interface at %p\n", This, *obj);
164 else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) )
166 *obj = ICOM_INTERFACE(This->ddraw, IDirect3D2);
167 TRACE("(%p) Returning IDirect3D2 interface at %p\n", This, *obj);
169 else if ( IsEqualGUID( &IID_IDirect3D3 , refiid ) )
171 *obj = ICOM_INTERFACE(This->ddraw, IDirect3D3);
172 TRACE("(%p) Returning IDirect3D3 interface at %p\n", This, *obj);
174 else if ( IsEqualGUID( &IID_IDirect3D7 , refiid ) )
176 *obj = ICOM_INTERFACE(This->ddraw, IDirect3D7);
177 TRACE("(%p) Returning IDirect3D7 interface at %p\n", This, *obj);
180 /* Direct3DDevice */
181 else if ( IsEqualGUID( &IID_IDirect3DDevice , refiid ) )
183 *obj = ICOM_INTERFACE(This, IDirect3DDevice);
184 TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
186 else if ( IsEqualGUID( &IID_IDirect3DDevice2 , refiid ) ) {
187 *obj = ICOM_INTERFACE(This, IDirect3DDevice2);
188 TRACE("(%p) Returning IDirect3DDevice2 interface at %p\n", This, *obj);
190 else if ( IsEqualGUID( &IID_IDirect3DDevice3 , refiid ) ) {
191 *obj = ICOM_INTERFACE(This, IDirect3DDevice3);
192 TRACE("(%p) Returning IDirect3DDevice3 interface at %p\n", This, *obj);
194 else if ( IsEqualGUID( &IID_IDirect3DDevice7 , refiid ) ) {
195 *obj = ICOM_INTERFACE(This, IDirect3DDevice7);
196 TRACE("(%p) Returning IDirect3DDevice7 interface at %p\n", This, *obj);
199 /* Unknown interface */
200 else
202 ERR("(%p)->(%s, %p): No interface found\n", This, debugstr_guid(refiid), obj);
203 return E_NOINTERFACE;
206 /* AddRef the returned interface */
207 IUnknown_AddRef( (IUnknown *) *obj);
208 return D3D_OK;
211 static HRESULT WINAPI
212 Thunk_IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface,
213 REFIID riid,
214 void **obj)
216 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
217 TRACE_(ddraw_thunk)("(%p)->(%s,%p) thunking to IDirect3DDevice7 interface.\n", This, debugstr_guid(riid), obj);
218 return IDirect3DDevice7_QueryInterface(ICOM_INTERFACE(This, IDirect3DDevice7),
219 riid,
220 obj);
223 static HRESULT WINAPI
224 Thunk_IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface,
225 REFIID riid,
226 void **obj)
228 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
229 TRACE_(ddraw_thunk)("(%p)->(%s,%p) thunking to IDirect3DDevice7 interface.\n", This, debugstr_guid(riid), obj);
230 return IDirect3DDevice7_QueryInterface(ICOM_INTERFACE(This, IDirect3DDevice7),
231 riid,
232 obj);
235 static HRESULT WINAPI
236 Thunk_IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface,
237 REFIID riid,
238 void **obp)
240 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
241 TRACE_(ddraw_thunk)("(%p)->(%s,%p) thunking to IDirect3DDevice7 interface.\n", This, debugstr_guid(riid), obp);
242 return IDirect3DDevice7_QueryInterface(ICOM_INTERFACE(This, IDirect3DDevice7),
243 riid,
244 obp);
247 /*****************************************************************************
248 * IDirect3DDevice7::AddRef
250 * Increases the refcount....
251 * The most exciting Method, definitely
253 * Exists in Version 1, 2, 3 and 7
255 * Returns:
256 * The new refcount
258 *****************************************************************************/
259 static ULONG WINAPI
260 IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
262 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
263 ULONG ref = InterlockedIncrement(&This->ref);
265 TRACE("(%p) : incrementing from %u.\n", This, ref -1);
267 return ref;
270 static ULONG WINAPI
271 Thunk_IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
273 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
274 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
275 return IDirect3DDevice7_AddRef(ICOM_INTERFACE(This, IDirect3DDevice7));
278 static ULONG WINAPI
279 Thunk_IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
281 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
282 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
283 return IDirect3DDevice7_AddRef(ICOM_INTERFACE(This, IDirect3DDevice7));
286 static ULONG WINAPI
287 Thunk_IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
289 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", iface);
290 return IDirect3DDevice7_AddRef(COM_INTERFACE_CAST(IDirect3DDeviceImpl, IDirect3DDevice, IDirect3DDevice7, iface));
293 /*****************************************************************************
294 * IDirect3DDevice7::Release
296 * Decreases the refcount of the interface
297 * When the refcount is reduced to 0, the object is destroyed.
299 * Exists in Version 1, 2, 3 and 7
301 * Returns:d
302 * The new refcount
304 *****************************************************************************/
305 static ULONG WINAPI
306 IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
308 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
309 ULONG ref = InterlockedDecrement(&This->ref);
311 TRACE("(%p)->() decrementing from %u.\n", This, ref +1);
313 /* This method doesn't destroy the WineD3DDevice, because it's still in use for
314 * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
315 * when the render target is released
317 if (ref == 0)
319 IParent *IndexBufferParent;
320 DWORD i;
322 EnterCriticalSection(&ddraw_cs);
323 /* Free the index buffer. */
324 IWineD3DDevice_SetIndices(This->wineD3DDevice, NULL);
325 IWineD3DIndexBuffer_GetParent(This->indexbuffer,
326 (IUnknown **) &IndexBufferParent);
327 IParent_Release(IndexBufferParent); /* Once for the getParent */
328 if( IParent_Release(IndexBufferParent) != 0) /* And now to destroy it */
330 ERR(" (%p) Something is still holding the index buffer parent %p\n", This, IndexBufferParent);
333 /* There is no need to unset the vertex buffer here, IWineD3DDevice_Uninit3D will do that when
334 * destroying the primary stateblock. If a vertex buffer is destroyed while it is bound
335 * IDirect3DVertexBuffer::Release will unset it.
338 /* Restore the render targets */
339 if(This->OffScreenTarget)
341 WINED3DVIEWPORT vp;
343 vp.X = 0;
344 vp.Y = 0;
345 vp.Width = This->ddraw->d3d_target->surface_desc.dwWidth;
346 vp.Height = This->ddraw->d3d_target->surface_desc.dwHeight;
347 vp.MinZ = 0.0;
348 vp.MaxZ = 1.0;
349 IWineD3DDevice_SetViewport(This->wineD3DDevice,
350 &vp);
352 /* Set the device up to render to the front buffer since the back buffer will
353 * vanish soon.
355 IWineD3DDevice_SetRenderTarget(This->wineD3DDevice, 0,
356 This->ddraw->d3d_target->WineD3DSurface);
357 /* This->target is the offscreen target.
358 * This->ddraw->d3d_target is the target used by DDraw
360 TRACE("(%p) Release: Using %p as front buffer, %p as back buffer\n", This, This->ddraw->d3d_target, NULL);
361 IWineD3DDevice_SetFrontBackBuffers(This->wineD3DDevice,
362 This->ddraw->d3d_target->WineD3DSurface,
363 NULL);
366 /* Release the WineD3DDevice. This won't destroy it */
367 if(IWineD3DDevice_Release(This->wineD3DDevice) <= 0)
369 ERR(" (%p) The wineD3D device %p was destroyed unexpectedly. Prepare for trouble\n", This, This->wineD3DDevice);
372 /* The texture handles should be unset by now, but there might be some bits
373 * missing in our reference counting(needs test). Do a sanity check
375 for(i = 0; i < This->numHandles; i++)
377 if(This->Handles[i].ptr)
379 switch(This->Handles[i].type)
381 case DDrawHandle_Texture:
383 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *) This->Handles[i].ptr;
384 FIXME("Texture Handle %d not unset properly\n", i + 1);
385 surf->Handle = 0;
387 break;
389 case DDrawHandle_Material:
391 IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) This->Handles[i].ptr;
392 FIXME("Material handle %d not unset properly\n", i + 1);
393 mat->Handle = 0;
395 break;
397 case DDrawHandle_Matrix:
399 /* No fixme here because this might happen because of sloppy apps */
400 WARN("Leftover matrix handle %d, deleting\n", i + 1);
401 IDirect3DDevice_DeleteMatrix(ICOM_INTERFACE(This, IDirect3DDevice),
402 i + 1);
404 break;
406 case DDrawHandle_StateBlock:
408 /* No fixme here because this might happen because of sloppy apps */
409 WARN("Leftover stateblock handle %d, deleting\n", i + 1);
410 IDirect3DDevice7_DeleteStateBlock(ICOM_INTERFACE(This, IDirect3DDevice7),
411 i + 1);
413 break;
415 default:
416 FIXME("Unknown handle %d not unset properly\n", i + 1);
421 HeapFree(GetProcessHeap(), 0, This->Handles);
423 TRACE("Releasing target %p %p\n", This->target, This->ddraw->d3d_target);
424 /* Release the render target and the WineD3D render target
425 * (See IDirect3D7::CreateDevice for more comments on this)
427 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->target, IDirectDrawSurface7));
428 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->ddraw->d3d_target,IDirectDrawSurface7));
429 TRACE("Target release done\n");
431 This->ddraw->d3ddevice = NULL;
433 /* Now free the structure */
434 HeapFree(GetProcessHeap(), 0, This);
435 LeaveCriticalSection(&ddraw_cs);
438 TRACE("Done\n");
439 return ref;
442 static ULONG WINAPI
443 Thunk_IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
445 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
446 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
447 return IDirect3DDevice7_Release(ICOM_INTERFACE(This, IDirect3DDevice7));
450 static ULONG WINAPI
451 Thunk_IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
453 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
454 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
455 return IDirect3DDevice7_Release(ICOM_INTERFACE(This, IDirect3DDevice7));
458 static ULONG WINAPI
459 Thunk_IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
461 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
462 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
463 return IDirect3DDevice7_Release(ICOM_INTERFACE(This, IDirect3DDevice7));
466 /*****************************************************************************
467 * IDirect3DDevice Methods
468 *****************************************************************************/
470 /*****************************************************************************
471 * IDirect3DDevice::Initialize
473 * Initializes a Direct3DDevice. This implementation is a no-op, as all
474 * initialization is done at create time.
476 * Exists in Version 1
478 * Parameters:
479 * No idea what they mean, as the MSDN page is gone
481 * Returns: DD_OK
483 *****************************************************************************/
484 static HRESULT WINAPI
485 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
486 IDirect3D *Direct3D, GUID *guid,
487 D3DDEVICEDESC *Desc)
489 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
491 /* It shouldn't be crucial, but print a FIXME, I'm interested if
492 * any game calls it and when
494 FIXME("(%p)->(%p,%p,%p): No-op!\n", This, Direct3D, guid, Desc);
496 return D3D_OK;
499 /*****************************************************************************
500 * IDirect3DDevice7::GetCaps
502 * Retrieves the device's capabilities
504 * This implementation is used for Version 7 only, the older versions have
505 * their own implementation.
507 * Parameters:
508 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
510 * Returns:
511 * D3D_OK on success
512 * D3DERR_* if a problem occurs. See WineD3D
514 *****************************************************************************/
515 static HRESULT
516 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
517 D3DDEVICEDESC7 *Desc)
519 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
520 D3DDEVICEDESC OldDesc;
521 TRACE("(%p)->(%p)\n", This, Desc);
523 /* Call the same function used by IDirect3D, this saves code */
524 return IDirect3DImpl_GetCaps(This->ddraw->wineD3D, &OldDesc, Desc);
527 static HRESULT WINAPI
528 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
529 D3DDEVICEDESC7 *Desc)
531 return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
534 static HRESULT WINAPI
535 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
536 D3DDEVICEDESC7 *Desc)
538 HRESULT hr;
539 WORD old_fpucw;
541 old_fpucw = d3d_fpu_setup();
542 hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
543 set_fpu_control_word(old_fpucw);
545 return hr;
547 /*****************************************************************************
548 * IDirect3DDevice3::GetCaps
550 * Retrieves the capabilities of the hardware device and the emulation
551 * device. For Wine, hardware and emulation are the same (it's all HW).
553 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
555 * Parameters:
556 * HWDesc: Structure to fill with the HW caps
557 * HelDesc: Structure to fill with the hardware emulation caps
559 * Returns:
560 * D3D_OK on success
561 * D3DERR_* if a problem occurs. See WineD3D
563 *****************************************************************************/
564 static HRESULT WINAPI
565 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
566 D3DDEVICEDESC *HWDesc,
567 D3DDEVICEDESC *HelDesc)
569 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
570 D3DDEVICEDESC7 newDesc;
571 HRESULT hr;
572 TRACE("(%p)->(%p,%p)\n", iface, HWDesc, HelDesc);
574 hr = IDirect3DImpl_GetCaps(This->ddraw->wineD3D, HWDesc, &newDesc);
575 if(hr != D3D_OK) return hr;
577 *HelDesc = *HWDesc;
578 return D3D_OK;
581 static HRESULT WINAPI
582 Thunk_IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
583 D3DDEVICEDESC *D3DHWDevDesc,
584 D3DDEVICEDESC *D3DHELDevDesc)
586 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
587 TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice3 interface.\n", This, D3DHWDevDesc, D3DHELDevDesc);
588 return IDirect3DDevice3_GetCaps(ICOM_INTERFACE(This, IDirect3DDevice3),
589 D3DHWDevDesc,
590 D3DHELDevDesc);
593 static HRESULT WINAPI
594 Thunk_IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
595 D3DDEVICEDESC *D3DHWDevDesc,
596 D3DDEVICEDESC *D3DHELDevDesc)
598 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
599 TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice3 interface.\n", This, D3DHWDevDesc, D3DHELDevDesc);
600 return IDirect3DDevice3_GetCaps(ICOM_INTERFACE(This, IDirect3DDevice3),
601 D3DHWDevDesc,
602 D3DHELDevDesc);
605 /*****************************************************************************
606 * IDirect3DDevice2::SwapTextureHandles
608 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
610 * Parameters:
611 * Tex1, Tex2: The 2 Textures to swap
613 * Returns:
614 * D3D_OK
616 *****************************************************************************/
617 static HRESULT WINAPI
618 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
619 IDirect3DTexture2 *Tex1,
620 IDirect3DTexture2 *Tex2)
622 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
623 DWORD swap;
624 IDirectDrawSurfaceImpl *surf1 = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture2, Tex1);
625 IDirectDrawSurfaceImpl *surf2 = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture2, Tex2);
626 TRACE("(%p)->(%p,%p)\n", This, surf1, surf2);
628 EnterCriticalSection(&ddraw_cs);
629 This->Handles[surf1->Handle - 1].ptr = surf2;
630 This->Handles[surf2->Handle - 1].ptr = surf1;
632 swap = surf2->Handle;
633 surf2->Handle = surf1->Handle;
634 surf1->Handle = swap;
635 LeaveCriticalSection(&ddraw_cs);
637 return D3D_OK;
640 static HRESULT WINAPI
641 Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
642 IDirect3DTexture *D3DTex1,
643 IDirect3DTexture *D3DTex2)
645 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
646 IDirectDrawSurfaceImpl *surf1 = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture, D3DTex1);
647 IDirectDrawSurfaceImpl *surf2 = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture, D3DTex2);
648 TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice2 interface.\n", This, surf1, surf2);
649 return IDirect3DDevice2_SwapTextureHandles(ICOM_INTERFACE(This, IDirect3DDevice2),
650 ICOM_INTERFACE(surf1, IDirect3DTexture2),
651 ICOM_INTERFACE(surf2, IDirect3DTexture2));
654 /*****************************************************************************
655 * IDirect3DDevice3::GetStats
657 * This method seems to retrieve some stats from the device.
658 * The MSDN documentation doesn't exist any more, but the D3DSTATS
659 * structure suggests that the amount of drawn primitives and processed
660 * vertices is returned.
662 * Exists in Version 1, 2 and 3
664 * Parameters:
665 * Stats: Pointer to a D3DSTATS structure to be filled
667 * Returns:
668 * D3D_OK on success
669 * DDERR_INVALIDPARAMS if Stats == NULL
671 *****************************************************************************/
672 static HRESULT WINAPI
673 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
674 D3DSTATS *Stats)
676 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
677 FIXME("(%p)->(%p): Stub!\n", This, Stats);
679 if(!Stats)
680 return DDERR_INVALIDPARAMS;
682 /* Fill the Stats with 0 */
683 Stats->dwTrianglesDrawn = 0;
684 Stats->dwLinesDrawn = 0;
685 Stats->dwPointsDrawn = 0;
686 Stats->dwSpansDrawn = 0;
687 Stats->dwVerticesProcessed = 0;
689 return D3D_OK;
692 static HRESULT WINAPI
693 Thunk_IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface,
694 D3DSTATS *Stats)
696 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
697 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, Stats);
698 return IDirect3DDevice3_GetStats(ICOM_INTERFACE(This, IDirect3DDevice3),
699 Stats);
702 static HRESULT WINAPI
703 Thunk_IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface,
704 D3DSTATS *Stats)
706 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
707 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, Stats);
708 return IDirect3DDevice3_GetStats(ICOM_INTERFACE(This, IDirect3DDevice3),
709 Stats);
712 /*****************************************************************************
713 * IDirect3DDevice::CreateExecuteBuffer
715 * Creates an IDirect3DExecuteBuffer, used for rendering with a
716 * Direct3DDevice.
718 * Version 1 only.
720 * Params:
721 * Desc: Buffer description
722 * ExecuteBuffer: Address to return the Interface pointer at
723 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
724 * support
726 * Returns:
727 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
728 * DDERR_OUTOFMEMORY if we ran out of memory
729 * D3D_OK on success
731 *****************************************************************************/
732 static HRESULT WINAPI
733 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
734 D3DEXECUTEBUFFERDESC *Desc,
735 IDirect3DExecuteBuffer **ExecuteBuffer,
736 IUnknown *UnkOuter)
738 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
739 IDirect3DExecuteBufferImpl* object;
740 TRACE("(%p)->(%p,%p,%p)!\n", This, Desc, ExecuteBuffer, UnkOuter);
742 if(UnkOuter)
743 return CLASS_E_NOAGGREGATION;
745 /* Allocate the new Execute Buffer */
746 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
747 if(!object)
749 ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
750 return DDERR_OUTOFMEMORY;
753 ICOM_INIT_INTERFACE(object, IDirect3DExecuteBuffer, IDirect3DExecuteBuffer_Vtbl);
755 object->ref = 1;
756 object->d3ddev = This;
758 /* Initializes memory */
759 memcpy(&object->desc, Desc, Desc->dwSize);
761 /* No buffer given */
762 if ((object->desc.dwFlags & D3DDEB_LPDATA) == 0)
763 object->desc.lpData = NULL;
765 /* No buffer size given */
766 if ((object->desc.dwFlags & D3DDEB_BUFSIZE) == 0)
767 object->desc.dwBufferSize = 0;
769 /* Create buffer if asked */
770 if ((object->desc.lpData == NULL) && (object->desc.dwBufferSize > 0))
772 object->need_free = TRUE;
773 object->desc.lpData = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,object->desc.dwBufferSize);
774 if(!object->desc.lpData)
776 ERR("Out of memory when allocating the execute buffer data\n");
777 HeapFree(GetProcessHeap(), 0, object);
778 return DDERR_OUTOFMEMORY;
781 else
783 object->need_free = FALSE;
786 /* No vertices for the moment */
787 object->vertex_data = NULL;
789 object->desc.dwFlags |= D3DDEB_LPDATA;
791 object->indices = NULL;
792 object->nb_indices = 0;
794 *ExecuteBuffer = ICOM_INTERFACE(object, IDirect3DExecuteBuffer);
796 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
798 return D3D_OK;
801 /*****************************************************************************
802 * IDirect3DDevice::Execute
804 * Executes all the stuff in an execute buffer.
806 * Params:
807 * ExecuteBuffer: The buffer to execute
808 * Viewport: The viewport used for rendering
809 * Flags: Some flags
811 * Returns:
812 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
813 * D3D_OK on success
815 *****************************************************************************/
816 static HRESULT WINAPI
817 IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
818 IDirect3DExecuteBuffer *ExecuteBuffer,
819 IDirect3DViewport *Viewport,
820 DWORD Flags)
822 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
823 IDirect3DExecuteBufferImpl *Direct3DExecuteBufferImpl = ICOM_OBJECT(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, ExecuteBuffer);
824 IDirect3DViewportImpl *Direct3DViewportImpl = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Viewport);
826 TRACE("(%p)->(%p,%p,%08x)\n", This, Direct3DExecuteBufferImpl, Direct3DViewportImpl, Flags);
828 if(!Direct3DExecuteBufferImpl)
829 return DDERR_INVALIDPARAMS;
831 /* Execute... */
832 EnterCriticalSection(&ddraw_cs);
833 IDirect3DExecuteBufferImpl_Execute(Direct3DExecuteBufferImpl, This, Direct3DViewportImpl);
834 LeaveCriticalSection(&ddraw_cs);
836 return D3D_OK;
839 /*****************************************************************************
840 * IDirect3DDevice3::AddViewport
842 * Add a Direct3DViewport to the device's viewport list. These viewports
843 * are wrapped to IDirect3DDevice7 viewports in viewport.c
845 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
846 * are the same interfaces.
848 * Params:
849 * Viewport: The viewport to add
851 * Returns:
852 * DDERR_INVALIDPARAMS if Viewport == NULL
853 * D3D_OK on success
855 *****************************************************************************/
856 static HRESULT WINAPI
857 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
858 IDirect3DViewport3 *Viewport)
860 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
861 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Viewport);
863 TRACE("(%p)->(%p)\n", This, vp);
865 /* Sanity check */
866 if(!vp)
867 return DDERR_INVALIDPARAMS;
869 EnterCriticalSection(&ddraw_cs);
870 vp->next = This->viewport_list;
871 This->viewport_list = vp;
872 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
873 so set active_device here. */
874 LeaveCriticalSection(&ddraw_cs);
876 return D3D_OK;
879 static HRESULT WINAPI
880 Thunk_IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
881 IDirect3DViewport2 *Direct3DViewport2)
883 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
884 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Direct3DViewport2);
885 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
886 return IDirect3DDevice3_AddViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
887 ICOM_INTERFACE(vp, IDirect3DViewport3));
890 static HRESULT WINAPI
891 Thunk_IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
892 IDirect3DViewport *Direct3DViewport)
894 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
895 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Direct3DViewport);
896 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
897 return IDirect3DDevice3_AddViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
898 ICOM_INTERFACE(vp, IDirect3DViewport3));
901 /*****************************************************************************
902 * IDirect3DDevice3::DeleteViewport
904 * Deletes a Direct3DViewport from the device's viewport list.
906 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
907 * are equal.
909 * Params:
910 * Viewport: The viewport to delete
912 * Returns:
913 * D3D_OK on success
914 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
916 *****************************************************************************/
917 static HRESULT WINAPI
918 IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface,
919 IDirect3DViewport3 *Viewport)
921 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
922 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *) Viewport;
923 IDirect3DViewportImpl *cur_viewport, *prev_viewport = NULL;
925 TRACE("(%p)->(%p)\n", This, vp);
927 EnterCriticalSection(&ddraw_cs);
928 cur_viewport = This->viewport_list;
929 while (cur_viewport != NULL)
931 if (cur_viewport == vp)
933 if (prev_viewport == NULL) This->viewport_list = cur_viewport->next;
934 else prev_viewport->next = cur_viewport->next;
935 /* TODO : add desactivate of the viewport and all associated lights... */
936 LeaveCriticalSection(&ddraw_cs);
937 return D3D_OK;
939 prev_viewport = cur_viewport;
940 cur_viewport = cur_viewport->next;
943 LeaveCriticalSection(&ddraw_cs);
944 return DDERR_INVALIDPARAMS;
947 static HRESULT WINAPI
948 Thunk_IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
949 IDirect3DViewport2 *Direct3DViewport2)
951 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
952 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Direct3DViewport2);
953 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
954 return IDirect3DDevice3_DeleteViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
955 ICOM_INTERFACE(vp, IDirect3DViewport3));
958 static HRESULT WINAPI
959 Thunk_IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
960 IDirect3DViewport *Direct3DViewport)
962 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
963 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Direct3DViewport);
964 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
965 return IDirect3DDevice3_DeleteViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
966 ICOM_INTERFACE(vp, IDirect3DViewport3));
969 /*****************************************************************************
970 * IDirect3DDevice3::NextViewport
972 * Returns a viewport from the viewport list, depending on the
973 * passed viewport and the flags.
975 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
976 * are equal.
978 * Params:
979 * Viewport: Viewport to use for beginning the search
980 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
982 * Returns:
983 * D3D_OK on success
984 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
986 *****************************************************************************/
987 static HRESULT WINAPI
988 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
989 IDirect3DViewport3 *Viewport3,
990 IDirect3DViewport3 **lplpDirect3DViewport3,
991 DWORD Flags)
993 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
994 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Viewport3);
995 IDirect3DViewportImpl *res = NULL;
997 TRACE("(%p)->(%p,%p,%08x)\n", This, vp, lplpDirect3DViewport3, Flags);
999 if(!vp)
1001 *lplpDirect3DViewport3 = NULL;
1002 return DDERR_INVALIDPARAMS;
1006 EnterCriticalSection(&ddraw_cs);
1007 switch (Flags)
1009 case D3DNEXT_NEXT:
1011 res = vp->next;
1013 break;
1014 case D3DNEXT_HEAD:
1016 res = This->viewport_list;
1018 break;
1019 case D3DNEXT_TAIL:
1021 IDirect3DViewportImpl *cur_viewport = This->viewport_list;
1022 if (cur_viewport != NULL)
1024 while (cur_viewport->next != NULL) cur_viewport = cur_viewport->next;
1026 res = cur_viewport;
1028 break;
1029 default:
1030 *lplpDirect3DViewport3 = NULL;
1031 LeaveCriticalSection(&ddraw_cs);
1032 return DDERR_INVALIDPARAMS;
1035 *lplpDirect3DViewport3 = ICOM_INTERFACE(res, IDirect3DViewport3);
1036 LeaveCriticalSection(&ddraw_cs);
1037 return D3D_OK;
1040 static HRESULT WINAPI
1041 Thunk_IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
1042 IDirect3DViewport2 *Viewport2,
1043 IDirect3DViewport2 **lplpDirect3DViewport2,
1044 DWORD Flags)
1046 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1047 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Viewport2);
1048 IDirect3DViewport3 *res;
1049 HRESULT hr;
1050 TRACE_(ddraw_thunk)("(%p)->(%p,%p,%08x) thunking to IDirect3DDevice3 interface.\n", This, vp, lplpDirect3DViewport2, Flags);
1051 hr = IDirect3DDevice3_NextViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
1052 ICOM_INTERFACE(vp, IDirect3DViewport3),
1053 &res,
1054 Flags);
1055 *lplpDirect3DViewport2 = (IDirect3DViewport2 *) COM_INTERFACE_CAST(IDirect3DViewportImpl, IDirect3DViewport3, IDirect3DViewport3, res);
1056 return hr;
1059 static HRESULT WINAPI
1060 Thunk_IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
1061 IDirect3DViewport *Viewport,
1062 IDirect3DViewport **lplpDirect3DViewport,
1063 DWORD Flags)
1065 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1066 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Viewport);
1067 IDirect3DViewport3 *res;
1068 HRESULT hr;
1069 TRACE_(ddraw_thunk)("(%p)->(%p,%p,%08x) thunking to IDirect3DDevice3 interface.\n", This, vp, lplpDirect3DViewport, Flags);
1070 hr = IDirect3DDevice3_NextViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
1071 ICOM_INTERFACE(vp, IDirect3DViewport3),
1072 &res,
1073 Flags);
1074 *lplpDirect3DViewport = (IDirect3DViewport *) COM_INTERFACE_CAST(IDirect3DViewportImpl, IDirect3DViewport3, IDirect3DViewport3, res);
1075 return hr;
1078 /*****************************************************************************
1079 * IDirect3DDevice::Pick
1081 * Executes an execute buffer without performing rendering. Instead, a
1082 * list of primitives that intersect with (x1,y1) of the passed rectangle
1083 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
1084 * this list.
1086 * Version 1 only
1088 * Params:
1089 * ExecuteBuffer: Buffer to execute
1090 * Viewport: Viewport to use for execution
1091 * Flags: None are defined, according to the SDK
1092 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
1093 * x2 and y2 are ignored.
1095 * Returns:
1096 * D3D_OK because it's a stub
1098 *****************************************************************************/
1099 static HRESULT WINAPI
1100 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
1101 IDirect3DExecuteBuffer *ExecuteBuffer,
1102 IDirect3DViewport *Viewport,
1103 DWORD Flags,
1104 D3DRECT *Rect)
1106 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1107 IDirect3DExecuteBufferImpl *execbuf = ICOM_OBJECT(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, ExecuteBuffer);
1108 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Viewport);
1109 FIXME("(%p)->(%p,%p,%08x,%p): stub!\n", This, execbuf, vp, Flags, Rect);
1111 return D3D_OK;
1114 /*****************************************************************************
1115 * IDirect3DDevice::GetPickRecords
1117 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1119 * Version 1 only
1121 * Params:
1122 * Count: Pointer to a DWORD containing the numbers of pick records to
1123 * retrieve
1124 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1126 * Returns:
1127 * D3D_OK, because it's a stub
1129 *****************************************************************************/
1130 static HRESULT WINAPI
1131 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1132 DWORD *Count,
1133 D3DPICKRECORD *D3DPickRec)
1135 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1136 FIXME("(%p)->(%p,%p): stub!\n", This, Count, D3DPickRec);
1138 return D3D_OK;
1141 /*****************************************************************************
1142 * IDirect3DDevice7::EnumTextureformats
1144 * Enumerates the supported texture formats. It has a list of all possible
1145 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1146 * WineD3D supports it. If so, then it is passed to the app.
1148 * This is for Version 7 and 3, older versions have a different
1149 * callback function and their own implementation
1151 * Params:
1152 * Callback: Callback to call for each enumerated format
1153 * Arg: Argument to pass to the callback
1155 * Returns:
1156 * D3D_OK on success
1157 * DDERR_INVALIDPARAMS if Callback == NULL
1159 *****************************************************************************/
1160 static HRESULT
1161 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1162 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1163 void *Arg)
1165 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1166 HRESULT hr;
1167 WINED3DDISPLAYMODE mode;
1168 unsigned int i;
1170 WINED3DFORMAT FormatList[] = {
1171 /* 32 bit */
1172 WINED3DFMT_A8R8G8B8,
1173 WINED3DFMT_X8R8G8B8,
1174 /* 24 bit */
1175 WINED3DFMT_R8G8B8,
1176 /* 16 Bit */
1177 WINED3DFMT_A1R5G5B5,
1178 WINED3DFMT_A4R4G4B4,
1179 WINED3DFMT_R5G6B5,
1180 WINED3DFMT_X1R5G5B5,
1181 /* 8 Bit */
1182 WINED3DFMT_R3G3B2,
1183 WINED3DFMT_P8,
1184 /* FOURCC codes */
1185 WINED3DFMT_DXT1,
1186 WINED3DFMT_DXT3,
1187 WINED3DFMT_DXT5,
1190 WINED3DFORMAT BumpFormatList[] = {
1191 WINED3DFMT_V8U8,
1192 WINED3DFMT_L6V5U5,
1193 WINED3DFMT_X8L8V8U8,
1194 WINED3DFMT_Q8W8V8U8,
1195 WINED3DFMT_V16U16,
1196 WINED3DFMT_W11V11U10,
1197 WINED3DFMT_A2W10V10U10
1200 TRACE("(%p)->(%p,%p): Relay\n", This, Callback, Arg);
1202 if(!Callback)
1203 return DDERR_INVALIDPARAMS;
1205 EnterCriticalSection(&ddraw_cs);
1207 memset(&mode, 0, sizeof(mode));
1208 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1210 &mode);
1211 if(FAILED(hr)) {
1212 LeaveCriticalSection(&ddraw_cs);
1213 WARN("Cannot get the current adapter format\n");
1214 return hr;
1217 for(i = 0; i < sizeof(FormatList) / sizeof(WINED3DFORMAT); i++)
1219 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1220 WINED3DADAPTER_DEFAULT,
1221 WINED3DDEVTYPE_HAL,
1222 mode.Format,
1223 0 /* Usage */,
1224 WINED3DRTYPE_TEXTURE,
1225 FormatList[i],
1226 SURFACE_OPENGL);
1227 if(hr == D3D_OK)
1229 DDPIXELFORMAT pformat;
1231 memset(&pformat, 0, sizeof(pformat));
1232 pformat.dwSize = sizeof(pformat);
1233 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1235 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1236 hr = Callback(&pformat, Arg);
1237 if(hr != DDENUMRET_OK)
1239 TRACE("Format enumeration cancelled by application\n");
1240 LeaveCriticalSection(&ddraw_cs);
1241 return D3D_OK;
1246 for(i = 0; i < sizeof(BumpFormatList) / sizeof(WINED3DFORMAT); i++)
1248 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1249 WINED3DADAPTER_DEFAULT,
1250 WINED3DDEVTYPE_HAL,
1251 mode.Format,
1252 WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1253 WINED3DRTYPE_TEXTURE,
1254 BumpFormatList[i],
1255 SURFACE_OPENGL);
1256 if(hr == D3D_OK)
1258 DDPIXELFORMAT pformat;
1260 memset(&pformat, 0, sizeof(pformat));
1261 pformat.dwSize = sizeof(pformat);
1262 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1264 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1265 hr = Callback(&pformat, Arg);
1266 if(hr != DDENUMRET_OK)
1268 TRACE("Format enumeration cancelled by application\n");
1269 LeaveCriticalSection(&ddraw_cs);
1270 return D3D_OK;
1274 TRACE("End of enumeration\n");
1275 LeaveCriticalSection(&ddraw_cs);
1276 return D3D_OK;
1279 static HRESULT WINAPI
1280 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1281 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1282 void *Arg)
1284 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1287 static HRESULT WINAPI
1288 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1289 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1290 void *Arg)
1292 HRESULT hr;
1293 WORD old_fpucw;
1295 old_fpucw = d3d_fpu_setup();
1296 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1297 set_fpu_control_word(old_fpucw);
1299 return hr;
1302 static HRESULT WINAPI
1303 Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1304 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1305 void *Arg)
1307 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1308 TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice7 interface.\n", This, Callback, Arg);
1309 return IDirect3DDevice7_EnumTextureFormats(ICOM_INTERFACE(This, IDirect3DDevice7),
1310 Callback,
1311 Arg);
1314 /*****************************************************************************
1315 * IDirect3DDevice2::EnumTextureformats
1317 * EnumTextureFormats for Version 1 and 2, see
1318 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1320 * This version has a different callback and does not enumerate FourCC
1321 * formats
1323 *****************************************************************************/
1324 static HRESULT WINAPI
1325 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1326 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1327 void *Arg)
1329 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1330 HRESULT hr;
1331 unsigned int i;
1332 WINED3DDISPLAYMODE mode;
1334 WINED3DFORMAT FormatList[] = {
1335 /* 32 bit */
1336 WINED3DFMT_A8R8G8B8,
1337 WINED3DFMT_X8R8G8B8,
1338 /* 24 bit */
1339 WINED3DFMT_R8G8B8,
1340 /* 16 Bit */
1341 WINED3DFMT_A1R5G5B5,
1342 WINED3DFMT_A4R4G4B4,
1343 WINED3DFMT_R5G6B5,
1344 WINED3DFMT_X1R5G5B5,
1345 /* 8 Bit */
1346 WINED3DFMT_R3G3B2,
1347 WINED3DFMT_P8,
1348 /* FOURCC codes - Not in this version*/
1351 TRACE("(%p)->(%p,%p): Relay\n", This, Callback, Arg);
1353 if(!Callback)
1354 return DDERR_INVALIDPARAMS;
1356 EnterCriticalSection(&ddraw_cs);
1358 memset(&mode, 0, sizeof(mode));
1359 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1361 &mode);
1362 if(FAILED(hr)) {
1363 LeaveCriticalSection(&ddraw_cs);
1364 WARN("Cannot get the current adapter format\n");
1365 return hr;
1368 for(i = 0; i < sizeof(FormatList) / sizeof(WINED3DFORMAT); i++)
1370 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1371 0 /* Adapter */,
1372 WINED3DDEVTYPE_HAL,
1373 mode.Format,
1374 0 /* Usage */,
1375 WINED3DRTYPE_TEXTURE,
1376 FormatList[i],
1377 SURFACE_OPENGL);
1378 if(hr == D3D_OK)
1380 DDSURFACEDESC sdesc;
1382 memset(&sdesc, 0, sizeof(sdesc));
1383 sdesc.dwSize = sizeof(sdesc);
1384 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1385 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1386 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1387 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1389 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1390 hr = Callback(&sdesc, Arg);
1391 if(hr != DDENUMRET_OK)
1393 TRACE("Format enumeration cancelled by application\n");
1394 LeaveCriticalSection(&ddraw_cs);
1395 return D3D_OK;
1399 TRACE("End of enumeration\n");
1400 LeaveCriticalSection(&ddraw_cs);
1401 return D3D_OK;
1404 static HRESULT WINAPI
1405 Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1406 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1407 void *Arg)
1409 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1410 TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice2 interface.\n", This, Callback, Arg);
1411 return IDirect3DDevice2_EnumTextureFormats(ICOM_INTERFACE(This, IDirect3DDevice2),
1412 Callback,
1413 Arg);
1416 /*****************************************************************************
1417 * IDirect3DDevice::CreateMatrix
1419 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1420 * allocated for the handle.
1422 * Version 1 only
1424 * Params
1425 * D3DMatHandle: Address to return the handle at
1427 * Returns:
1428 * D3D_OK on success
1429 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1431 *****************************************************************************/
1432 static HRESULT WINAPI
1433 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1435 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1436 D3DMATRIX *Matrix;
1437 TRACE("(%p)->(%p)\n", This, D3DMatHandle);
1439 if(!D3DMatHandle)
1440 return DDERR_INVALIDPARAMS;
1442 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1443 if(!Matrix)
1445 ERR("Out of memory when allocating a D3DMATRIX\n");
1446 return DDERR_OUTOFMEMORY;
1449 EnterCriticalSection(&ddraw_cs);
1450 *D3DMatHandle = IDirect3DDeviceImpl_CreateHandle(This);
1451 if(!(*D3DMatHandle))
1453 ERR("Failed to create a matrix handle\n");
1454 HeapFree(GetProcessHeap(), 0, Matrix);
1455 LeaveCriticalSection(&ddraw_cs);
1456 return DDERR_OUTOFMEMORY;
1458 This->Handles[*D3DMatHandle - 1].ptr = Matrix;
1459 This->Handles[*D3DMatHandle - 1].type = DDrawHandle_Matrix;
1460 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1462 LeaveCriticalSection(&ddraw_cs);
1463 return D3D_OK;
1466 /*****************************************************************************
1467 * IDirect3DDevice::SetMatrix
1469 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1470 * allocated for the handle
1472 * Version 1 only
1474 * Params:
1475 * D3DMatHandle: Handle to set the matrix to
1476 * D3DMatrix: Matrix to set
1478 * Returns:
1479 * D3D_OK on success
1480 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1481 * to set is NULL
1483 *****************************************************************************/
1484 static HRESULT WINAPI
1485 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1486 D3DMATRIXHANDLE D3DMatHandle,
1487 D3DMATRIX *D3DMatrix)
1489 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1490 TRACE("(%p)->(%08x,%p)\n", This, D3DMatHandle, D3DMatrix);
1492 if( (!D3DMatHandle) || (!D3DMatrix) )
1493 return DDERR_INVALIDPARAMS;
1495 EnterCriticalSection(&ddraw_cs);
1496 if(D3DMatHandle > This->numHandles)
1498 ERR("Handle %d out of range\n", D3DMatHandle);
1499 LeaveCriticalSection(&ddraw_cs);
1500 return DDERR_INVALIDPARAMS;
1502 else if(This->Handles[D3DMatHandle - 1].type != DDrawHandle_Matrix)
1504 ERR("Handle %d is not a matrix handle\n", D3DMatHandle);
1505 LeaveCriticalSection(&ddraw_cs);
1506 return DDERR_INVALIDPARAMS;
1509 if (TRACE_ON(d3d7))
1510 dump_D3DMATRIX(D3DMatrix);
1512 *((D3DMATRIX *) This->Handles[D3DMatHandle - 1].ptr) = *D3DMatrix;
1514 if(This->world == D3DMatHandle)
1516 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1517 WINED3DTS_WORLDMATRIX(0),
1518 (WINED3DMATRIX *) D3DMatrix);
1520 if(This->view == D3DMatHandle)
1522 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1523 WINED3DTS_VIEW,
1524 (WINED3DMATRIX *) D3DMatrix);
1526 if(This->proj == D3DMatHandle)
1528 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1529 WINED3DTS_PROJECTION,
1530 (WINED3DMATRIX *) D3DMatrix);
1533 LeaveCriticalSection(&ddraw_cs);
1534 return D3D_OK;
1537 /*****************************************************************************
1538 * IDirect3DDevice::SetMatrix
1540 * Returns the content of a D3DMATRIX handle
1542 * Version 1 only
1544 * Params:
1545 * D3DMatHandle: Matrix handle to read the content from
1546 * D3DMatrix: Address to store the content at
1548 * Returns:
1549 * D3D_OK on success
1550 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1552 *****************************************************************************/
1553 static HRESULT WINAPI
1554 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1555 D3DMATRIXHANDLE D3DMatHandle,
1556 D3DMATRIX *D3DMatrix)
1558 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1559 TRACE("(%p)->(%08x,%p)\n", This, D3DMatHandle, D3DMatrix);
1561 if(!D3DMatrix)
1562 return DDERR_INVALIDPARAMS;
1563 if(!D3DMatHandle)
1564 return DDERR_INVALIDPARAMS;
1566 EnterCriticalSection(&ddraw_cs);
1567 if(D3DMatHandle > This->numHandles)
1569 ERR("Handle %d out of range\n", D3DMatHandle);
1570 LeaveCriticalSection(&ddraw_cs);
1571 return DDERR_INVALIDPARAMS;
1573 else if(This->Handles[D3DMatHandle - 1].type != DDrawHandle_Matrix)
1575 ERR("Handle %d is not a matrix handle\n", D3DMatHandle);
1576 LeaveCriticalSection(&ddraw_cs);
1577 return DDERR_INVALIDPARAMS;
1580 /* The handle is simply a pointer to a D3DMATRIX structure */
1581 *D3DMatrix = *((D3DMATRIX *) This->Handles[D3DMatHandle - 1].ptr);
1583 LeaveCriticalSection(&ddraw_cs);
1584 return D3D_OK;
1587 /*****************************************************************************
1588 * IDirect3DDevice::DeleteMatrix
1590 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1592 * Version 1 only
1594 * Params:
1595 * D3DMatHandle: Handle to destroy
1597 * Returns:
1598 * D3D_OK on success
1599 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1601 *****************************************************************************/
1602 static HRESULT WINAPI
1603 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1604 D3DMATRIXHANDLE D3DMatHandle)
1606 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1607 TRACE("(%p)->(%08x)\n", This, D3DMatHandle);
1609 if(!D3DMatHandle)
1610 return DDERR_INVALIDPARAMS;
1612 EnterCriticalSection(&ddraw_cs);
1613 if(D3DMatHandle > This->numHandles)
1615 ERR("Handle %d out of range\n", D3DMatHandle);
1616 LeaveCriticalSection(&ddraw_cs);
1617 return DDERR_INVALIDPARAMS;
1619 else if(This->Handles[D3DMatHandle - 1].type != DDrawHandle_Matrix)
1621 ERR("Handle %d is not a matrix handle\n", D3DMatHandle);
1622 LeaveCriticalSection(&ddraw_cs);
1623 return DDERR_INVALIDPARAMS;
1626 HeapFree(GetProcessHeap(), 0, This->Handles[D3DMatHandle - 1].ptr);
1627 This->Handles[D3DMatHandle - 1].ptr = NULL;
1628 This->Handles[D3DMatHandle - 1].type = DDrawHandle_Unknown;
1630 LeaveCriticalSection(&ddraw_cs);
1631 return D3D_OK;
1634 /*****************************************************************************
1635 * IDirect3DDevice7::BeginScene
1637 * This method must be called before any rendering is performed.
1638 * IDirect3DDevice::EndScene has to be called after the scene is complete
1640 * Version 1, 2, 3 and 7
1642 * Returns:
1643 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1644 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1645 * started scene).
1647 *****************************************************************************/
1648 static HRESULT
1649 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1651 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1652 HRESULT hr;
1653 TRACE("(%p): Relay\n", This);
1655 EnterCriticalSection(&ddraw_cs);
1656 hr = IWineD3DDevice_BeginScene(This->wineD3DDevice);
1657 LeaveCriticalSection(&ddraw_cs);
1658 if(hr == WINED3D_OK) return D3D_OK;
1659 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1662 static HRESULT WINAPI
1663 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1665 return IDirect3DDeviceImpl_7_BeginScene(iface);
1668 static HRESULT WINAPI
1669 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1671 HRESULT hr;
1672 WORD old_fpucw;
1674 old_fpucw = d3d_fpu_setup();
1675 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1676 set_fpu_control_word(old_fpucw);
1678 return hr;
1681 static HRESULT WINAPI
1682 Thunk_IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1684 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1685 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1686 return IDirect3DDevice7_BeginScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1689 static HRESULT WINAPI
1690 Thunk_IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1692 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1693 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1694 return IDirect3DDevice7_BeginScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1697 static HRESULT WINAPI
1698 Thunk_IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1700 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1701 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1702 return IDirect3DDevice7_BeginScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1705 /*****************************************************************************
1706 * IDirect3DDevice7::EndScene
1708 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1709 * This method must be called after rendering is finished.
1711 * Version 1, 2, 3 and 7
1713 * Returns:
1714 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1715 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1716 * that only if the scene was already ended.
1718 *****************************************************************************/
1719 static HRESULT
1720 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1722 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1723 HRESULT hr;
1724 TRACE("(%p): Relay\n", This);
1726 EnterCriticalSection(&ddraw_cs);
1727 hr = IWineD3DDevice_EndScene(This->wineD3DDevice);
1728 LeaveCriticalSection(&ddraw_cs);
1729 if(hr == WINED3D_OK) return D3D_OK;
1730 else return D3DERR_SCENE_NOT_IN_SCENE;
1733 static HRESULT WINAPI
1734 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1736 return IDirect3DDeviceImpl_7_EndScene(iface);
1739 static HRESULT WINAPI
1740 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1742 HRESULT hr;
1743 WORD old_fpucw;
1745 old_fpucw = d3d_fpu_setup();
1746 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1747 set_fpu_control_word(old_fpucw);
1749 return hr;
1752 static HRESULT WINAPI
1753 Thunk_IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1755 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1756 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1757 return IDirect3DDevice7_EndScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1760 static HRESULT WINAPI
1761 Thunk_IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1763 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1764 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1765 return IDirect3DDevice7_EndScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1768 static HRESULT WINAPI
1769 Thunk_IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1771 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1772 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1773 return IDirect3DDevice7_EndScene(ICOM_INTERFACE(This, IDirect3DDevice7));
1776 /*****************************************************************************
1777 * IDirect3DDevice7::GetDirect3D
1779 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1780 * this device.
1782 * Params:
1783 * Direct3D7: Address to store the interface pointer at
1785 * Returns:
1786 * D3D_OK on success
1787 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1789 *****************************************************************************/
1790 static HRESULT WINAPI
1791 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1792 IDirect3D7 **Direct3D7)
1794 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1795 TRACE("(%p)->(%p)\n", This, Direct3D7);
1797 if(!Direct3D7)
1798 return DDERR_INVALIDPARAMS;
1800 *Direct3D7 = ICOM_INTERFACE(This->ddraw, IDirect3D7);
1801 IDirect3D7_AddRef(*Direct3D7);
1803 TRACE(" returning interface %p\n", *Direct3D7);
1804 return D3D_OK;
1807 static HRESULT WINAPI
1808 Thunk_IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1809 IDirect3D3 **Direct3D3)
1811 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1812 HRESULT ret;
1813 IDirect3D7 *ret_ptr;
1815 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Direct3D3);
1816 ret = IDirect3DDevice7_GetDirect3D(ICOM_INTERFACE(This, IDirect3DDevice7),
1817 &ret_ptr);
1818 if(ret != D3D_OK)
1819 return ret;
1820 *Direct3D3 = COM_INTERFACE_CAST(IDirectDrawImpl, IDirect3D7, IDirect3D3, ret_ptr);
1821 TRACE(" returning interface %p\n", *Direct3D3);
1822 return D3D_OK;
1825 static HRESULT WINAPI
1826 Thunk_IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1827 IDirect3D2 **Direct3D2)
1829 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1830 HRESULT ret;
1831 IDirect3D7 *ret_ptr;
1833 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Direct3D2);
1834 ret = IDirect3DDevice7_GetDirect3D(ICOM_INTERFACE(This, IDirect3DDevice7),
1835 &ret_ptr);
1836 if(ret != D3D_OK)
1837 return ret;
1838 *Direct3D2 = COM_INTERFACE_CAST(IDirectDrawImpl, IDirect3D7, IDirect3D2, ret_ptr);
1839 TRACE(" returning interface %p\n", *Direct3D2);
1840 return D3D_OK;
1843 static HRESULT WINAPI
1844 Thunk_IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1845 IDirect3D **Direct3D)
1847 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1848 HRESULT ret;
1849 IDirect3D7 *ret_ptr;
1851 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Direct3D);
1852 ret = IDirect3DDevice7_GetDirect3D(ICOM_INTERFACE(This, IDirect3DDevice7),
1853 &ret_ptr);
1854 if(ret != D3D_OK)
1855 return ret;
1856 *Direct3D = COM_INTERFACE_CAST(IDirectDrawImpl, IDirect3D7, IDirect3D, ret_ptr);
1857 TRACE(" returning interface %p\n", *Direct3D);
1858 return D3D_OK;
1861 /*****************************************************************************
1862 * IDirect3DDevice3::SetCurrentViewport
1864 * Sets a Direct3DViewport as the current viewport.
1865 * For the thunks note that all viewport interface versions are equal
1867 * Params:
1868 * Direct3DViewport3: The viewport to set
1870 * Version 2 and 3
1872 * Returns:
1873 * D3D_OK on success
1874 * (Is a NULL viewport valid?)
1876 *****************************************************************************/
1877 static HRESULT WINAPI
1878 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1879 IDirect3DViewport3 *Direct3DViewport3)
1881 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1882 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Direct3DViewport3);
1883 TRACE("(%p)->(%p)\n", This, Direct3DViewport3);
1885 EnterCriticalSection(&ddraw_cs);
1886 /* Do nothing if the specified viewport is the same as the current one */
1887 if (This->current_viewport == vp )
1889 LeaveCriticalSection(&ddraw_cs);
1890 return D3D_OK;
1893 /* Should check if the viewport was added or not */
1895 /* Release previous viewport and AddRef the new one */
1896 if (This->current_viewport)
1898 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport, ICOM_INTERFACE(This->current_viewport, IDirect3DViewport3));
1899 IDirect3DViewport3_Release( ICOM_INTERFACE(This->current_viewport, IDirect3DViewport3) );
1901 IDirect3DViewport3_AddRef(Direct3DViewport3);
1903 /* Set this viewport as the current viewport */
1904 This->current_viewport = vp;
1906 /* Activate this viewport */
1907 This->current_viewport->active_device = This;
1908 This->current_viewport->activate(This->current_viewport, FALSE);
1910 LeaveCriticalSection(&ddraw_cs);
1911 return D3D_OK;
1914 static HRESULT WINAPI
1915 Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1916 IDirect3DViewport2 *Direct3DViewport2)
1918 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1919 IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, Direct3DViewport2);
1920 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
1921 return IDirect3DDevice3_SetCurrentViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
1922 ICOM_INTERFACE(vp, IDirect3DViewport3));
1925 /*****************************************************************************
1926 * IDirect3DDevice3::GetCurrentViewport
1928 * Returns the currently active viewport.
1930 * Version 2 and 3
1932 * Params:
1933 * Direct3DViewport3: Address to return the interface pointer at
1935 * Returns:
1936 * D3D_OK on success
1937 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1939 *****************************************************************************/
1940 static HRESULT WINAPI
1941 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1942 IDirect3DViewport3 **Direct3DViewport3)
1944 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1945 TRACE("(%p)->(%p)\n", This, Direct3DViewport3);
1947 if(!Direct3DViewport3)
1948 return DDERR_INVALIDPARAMS;
1950 EnterCriticalSection(&ddraw_cs);
1951 *Direct3DViewport3 = ICOM_INTERFACE(This->current_viewport, IDirect3DViewport3);
1953 /* AddRef the returned viewport */
1954 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1956 TRACE(" returning interface %p\n", *Direct3DViewport3);
1958 LeaveCriticalSection(&ddraw_cs);
1959 return D3D_OK;
1962 static HRESULT WINAPI
1963 Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1964 IDirect3DViewport2 **Direct3DViewport2)
1966 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1967 HRESULT hr;
1968 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, Direct3DViewport2);
1969 hr = IDirect3DDevice3_GetCurrentViewport(ICOM_INTERFACE(This, IDirect3DDevice3),
1970 (IDirect3DViewport3 **) Direct3DViewport2);
1971 if(hr != D3D_OK) return hr;
1972 *Direct3DViewport2 = (IDirect3DViewport2 *) COM_INTERFACE_CAST(IDirect3DViewportImpl, IDirect3DViewport3, IDirect3DViewport3, *Direct3DViewport2);
1973 return D3D_OK;
1976 /*****************************************************************************
1977 * IDirect3DDevice7::SetRenderTarget
1979 * Sets the render target for the Direct3DDevice.
1980 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1981 * IDirectDrawSurface3 == IDirectDrawSurface
1983 * Version 2, 3 and 7
1985 * Params:
1986 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1987 * render target
1988 * Flags: Some flags
1990 * Returns:
1991 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1993 *****************************************************************************/
1994 static HRESULT
1995 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1996 IDirectDrawSurface7 *NewTarget,
1997 DWORD Flags)
1999 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2000 IDirectDrawSurfaceImpl *Target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, NewTarget);
2001 HRESULT hr;
2002 TRACE("(%p)->(%p,%08x): Relay\n", This, NewTarget, Flags);
2004 EnterCriticalSection(&ddraw_cs);
2005 /* Flags: Not used */
2007 if(This->target == Target)
2009 TRACE("No-op SetRenderTarget operation, not doing anything\n");
2010 LeaveCriticalSection(&ddraw_cs);
2011 return D3D_OK;
2014 hr = IWineD3DDevice_SetRenderTarget(This->wineD3DDevice,
2016 Target ? Target->WineD3DSurface : NULL);
2017 if(hr != D3D_OK)
2019 LeaveCriticalSection(&ddraw_cs);
2020 return hr;
2022 IDirectDrawSurface7_AddRef(NewTarget);
2023 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->target, IDirectDrawSurface7));
2024 This->target = Target;
2025 IDirect3DDeviceImpl_UpdateDepthStencil(This);
2026 LeaveCriticalSection(&ddraw_cs);
2027 return D3D_OK;
2030 static HRESULT WINAPI
2031 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
2032 IDirectDrawSurface7 *NewTarget,
2033 DWORD Flags)
2035 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
2038 static HRESULT WINAPI
2039 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
2040 IDirectDrawSurface7 *NewTarget,
2041 DWORD Flags)
2043 HRESULT hr;
2044 WORD old_fpucw;
2046 old_fpucw = d3d_fpu_setup();
2047 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
2048 set_fpu_control_word(old_fpucw);
2050 return hr;
2053 static HRESULT WINAPI
2054 Thunk_IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
2055 IDirectDrawSurface4 *NewRenderTarget,
2056 DWORD Flags)
2058 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2059 IDirectDrawSurfaceImpl *Target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, NewRenderTarget);
2060 TRACE_(ddraw_thunk)("(%p)->(%p,%08x) thunking to IDirect3DDevice7 interface.\n", This, Target, Flags);
2061 return IDirect3DDevice7_SetRenderTarget(ICOM_INTERFACE(This, IDirect3DDevice7),
2062 ICOM_INTERFACE(Target, IDirectDrawSurface7),
2063 Flags);
2066 static HRESULT WINAPI
2067 Thunk_IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
2068 IDirectDrawSurface *NewRenderTarget,
2069 DWORD Flags)
2071 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2072 IDirectDrawSurfaceImpl *Target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface3, NewRenderTarget);
2073 TRACE_(ddraw_thunk)("(%p)->(%p,%08x) thunking to IDirect3DDevice7 interface.\n", This, Target, Flags);
2074 return IDirect3DDevice7_SetRenderTarget(ICOM_INTERFACE(This, IDirect3DDevice7),
2075 ICOM_INTERFACE(Target, IDirectDrawSurface7),
2076 Flags);
2079 /*****************************************************************************
2080 * IDirect3DDevice7::GetRenderTarget
2082 * Returns the current render target.
2083 * This is handled locally, because the WineD3D render target's parent
2084 * is an IParent
2086 * Version 2, 3 and 7
2088 * Params:
2089 * RenderTarget: Address to store the surface interface pointer
2091 * Returns:
2092 * D3D_OK on success
2093 * DDERR_INVALIDPARAMS if RenderTarget == NULL
2095 *****************************************************************************/
2096 static HRESULT WINAPI
2097 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
2098 IDirectDrawSurface7 **RenderTarget)
2100 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2101 TRACE("(%p)->(%p): Relay\n", This, RenderTarget);
2103 if(!RenderTarget)
2104 return DDERR_INVALIDPARAMS;
2106 EnterCriticalSection(&ddraw_cs);
2107 *RenderTarget = ICOM_INTERFACE(This->target, IDirectDrawSurface7);
2108 IDirectDrawSurface7_AddRef(*RenderTarget);
2110 LeaveCriticalSection(&ddraw_cs);
2111 return D3D_OK;
2114 static HRESULT WINAPI
2115 Thunk_IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
2116 IDirectDrawSurface4 **RenderTarget)
2118 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2119 HRESULT hr;
2120 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, RenderTarget);
2121 hr = IDirect3DDevice7_GetRenderTarget(ICOM_INTERFACE(This, IDirect3DDevice7),
2122 (IDirectDrawSurface7 **) RenderTarget);
2123 if(hr != D3D_OK) return hr;
2124 *RenderTarget = (IDirectDrawSurface4 *) COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirectDrawSurface7, IDirectDrawSurface7, *RenderTarget);
2125 return D3D_OK;
2128 static HRESULT WINAPI
2129 Thunk_IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
2130 IDirectDrawSurface **RenderTarget)
2132 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2133 HRESULT hr;
2134 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, RenderTarget);
2135 hr = IDirect3DDevice7_GetRenderTarget(ICOM_INTERFACE(This, IDirect3DDevice7),
2136 (IDirectDrawSurface7 **) RenderTarget);
2137 if(hr != D3D_OK) return hr;
2138 *RenderTarget = (IDirectDrawSurface *) COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirectDrawSurface7, IDirectDrawSurface3, *RenderTarget);
2139 return D3D_OK;
2142 /*****************************************************************************
2143 * IDirect3DDevice3::Begin
2145 * Begins a description block of vertices. This is similar to glBegin()
2146 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2147 * described with IDirect3DDevice::Vertex are drawn.
2149 * Version 2 and 3
2151 * Params:
2152 * PrimitiveType: The type of primitives to draw
2153 * VertexTypeDesc: A flexible vertex format description of the vertices
2154 * Flags: Some flags..
2156 * Returns:
2157 * D3D_OK on success
2159 *****************************************************************************/
2160 static HRESULT WINAPI
2161 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2162 D3DPRIMITIVETYPE PrimitiveType,
2163 DWORD VertexTypeDesc,
2164 DWORD Flags)
2166 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2167 TRACE("(%p)->(%d,%d,%08x)\n", This, PrimitiveType, VertexTypeDesc, Flags);
2169 EnterCriticalSection(&ddraw_cs);
2170 This->primitive_type = PrimitiveType;
2171 This->vertex_type = VertexTypeDesc;
2172 This->render_flags = Flags;
2173 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2174 This->nb_vertices = 0;
2175 LeaveCriticalSection(&ddraw_cs);
2177 return D3D_OK;
2180 static HRESULT WINAPI
2181 Thunk_IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface,
2182 D3DPRIMITIVETYPE d3dpt,
2183 D3DVERTEXTYPE dwVertexTypeDesc,
2184 DWORD dwFlags)
2186 DWORD FVF;
2187 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2188 TRACE_(ddraw_thunk)("(%p/%p)->(%08x,%08x,%08x): Thunking to IDirect3DDevice3\n", This, iface, d3dpt, dwVertexTypeDesc, dwFlags);
2190 switch(dwVertexTypeDesc)
2192 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2193 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2194 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2195 default:
2196 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2197 return DDERR_INVALIDPARAMS; /* Should never happen */
2200 return IDirect3DDevice3_Begin(ICOM_INTERFACE(This, IDirect3DDevice3),
2201 d3dpt,
2202 FVF,
2203 dwFlags);
2206 /*****************************************************************************
2207 * IDirect3DDevice3::BeginIndexed
2209 * Draws primitives based on vertices in a vertex array which are specified
2210 * by indices.
2212 * Version 2 and 3
2214 * Params:
2215 * PrimitiveType: Primitive type to draw
2216 * VertexType: A FVF description of the vertex format
2217 * Vertices: pointer to an array containing the vertices
2218 * NumVertices: The number of vertices in the vertex array
2219 * Flags: Some flags ...
2221 * Returns:
2222 * D3D_OK, because it's a stub
2224 *****************************************************************************/
2225 static HRESULT WINAPI
2226 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2227 D3DPRIMITIVETYPE PrimitiveType,
2228 DWORD VertexType,
2229 void *Vertices,
2230 DWORD NumVertices,
2231 DWORD Flags)
2233 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2234 FIXME("(%p)->(%08x,%08x,%p,%08x,%08x): stub!\n", This, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2235 return D3D_OK;
2239 static HRESULT WINAPI
2240 Thunk_IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2241 D3DPRIMITIVETYPE d3dptPrimitiveType,
2242 D3DVERTEXTYPE d3dvtVertexType,
2243 void *lpvVertices,
2244 DWORD dwNumVertices,
2245 DWORD dwFlags)
2247 DWORD FVF;
2248 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2249 TRACE_(ddraw_thunk)("(%p/%p)->(%08x,%08x,%p,%08x,%08x): Thunking to IDirect3DDevice3\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2251 switch(d3dvtVertexType)
2253 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2254 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2255 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2256 default:
2257 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2258 return DDERR_INVALIDPARAMS; /* Should never happen */
2261 return IDirect3DDevice3_BeginIndexed(ICOM_INTERFACE(This,IDirect3DDevice3),
2262 d3dptPrimitiveType,
2263 FVF,
2264 lpvVertices,
2265 dwNumVertices,
2266 dwFlags);
2269 /*****************************************************************************
2270 * IDirect3DDevice3::Vertex
2272 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2273 * drawn vertices in a vertex buffer. If the buffer is too small, its
2274 * size is increased.
2276 * Version 2 and 3
2278 * Params:
2279 * Vertex: Pointer to the vertex
2281 * Returns:
2282 * D3D_OK, on success
2283 * DDERR_INVALIDPARAMS if Vertex is NULL
2285 *****************************************************************************/
2286 static HRESULT WINAPI
2287 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2288 void *Vertex)
2290 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2291 TRACE("(%p)->(%p)\n", This, Vertex);
2293 if(!Vertex)
2294 return DDERR_INVALIDPARAMS;
2296 EnterCriticalSection(&ddraw_cs);
2297 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2299 BYTE *old_buffer;
2300 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2301 old_buffer = This->vertex_buffer;
2302 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2303 if (old_buffer)
2305 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2306 HeapFree(GetProcessHeap(), 0, old_buffer);
2310 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2312 LeaveCriticalSection(&ddraw_cs);
2313 return D3D_OK;
2316 static HRESULT WINAPI
2317 Thunk_IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface,
2318 void *lpVertexType)
2320 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2321 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, lpVertexType);
2322 return IDirect3DDevice3_Vertex(ICOM_INTERFACE(This, IDirect3DDevice3),
2323 lpVertexType);
2326 /*****************************************************************************
2327 * IDirect3DDevice3::Index
2329 * Specifies an index to a vertex to be drawn. The vertex array has to
2330 * be specified with BeginIndexed first.
2332 * Parameters:
2333 * VertexIndex: The index of the vertex to draw
2335 * Returns:
2336 * D3D_OK because it's a stub
2338 *****************************************************************************/
2339 static HRESULT WINAPI
2340 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2341 WORD VertexIndex)
2343 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2344 FIXME("(%p)->(%04x): stub!\n", This, VertexIndex);
2345 return D3D_OK;
2348 static HRESULT WINAPI
2349 Thunk_IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface,
2350 WORD wVertexIndex)
2352 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2353 TRACE_(ddraw_thunk)("(%p)->(%04x) thunking to IDirect3DDevice3 interface.\n", This, wVertexIndex);
2354 return IDirect3DDevice3_Index(ICOM_INTERFACE(This, IDirect3DDevice3),
2355 wVertexIndex);
2358 /*****************************************************************************
2359 * IDirect3DDevice3::End
2361 * Ends a draw begun with IDirect3DDevice3::Begin or
2362 * IDirect3DDevice::BeginIndexed. The vertices specified with
2363 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2364 * the IDirect3DDevice7::DrawPrimitive method. So far only
2365 * non-indexed mode is supported
2367 * Version 2 and 3
2369 * Params:
2370 * Flags: Some flags, as usual. Don't know which are defined
2372 * Returns:
2373 * The return value of IDirect3DDevice7::DrawPrimitive
2375 *****************************************************************************/
2376 static HRESULT WINAPI
2377 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2378 DWORD Flags)
2380 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2381 TRACE("(%p)->(%08x)\n", This, Flags);
2383 return IDirect3DDevice7_DrawPrimitive(ICOM_INTERFACE(This, IDirect3DDevice7),
2384 This->primitive_type, This->vertex_type,
2385 This->vertex_buffer, This->nb_vertices,
2386 This->render_flags);
2389 static HRESULT WINAPI
2390 Thunk_IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface,
2391 DWORD dwFlags)
2393 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2394 TRACE_(ddraw_thunk)("(%p)->(%08x) thunking to IDirect3DDevice3 interface.\n", This, dwFlags);
2395 return IDirect3DDevice3_End(ICOM_INTERFACE(This, IDirect3DDevice3),
2396 dwFlags);
2399 /*****************************************************************************
2400 * IDirect3DDevice7::GetRenderState
2402 * Returns the value of a render state. The possible render states are
2403 * defined in include/d3dtypes.h
2405 * Version 2, 3 and 7
2407 * Params:
2408 * RenderStateType: Render state to return the current setting of
2409 * Value: Address to store the value at
2411 * Returns:
2412 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2413 * DDERR_INVALIDPARAMS if Value == NULL
2415 *****************************************************************************/
2416 static HRESULT
2417 IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2418 D3DRENDERSTATETYPE RenderStateType,
2419 DWORD *Value)
2421 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2422 HRESULT hr;
2423 TRACE("(%p)->(%08x,%p): Relay\n", This, RenderStateType, Value);
2425 if(!Value)
2426 return DDERR_INVALIDPARAMS;
2428 EnterCriticalSection(&ddraw_cs);
2429 switch(RenderStateType)
2431 case D3DRENDERSTATE_TEXTUREMAG:
2433 WINED3DTEXTUREFILTERTYPE tex_mag;
2435 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2436 0, WINED3DSAMP_MAGFILTER,
2437 &tex_mag);
2439 switch (tex_mag)
2441 case WINED3DTEXF_POINT:
2442 *Value = D3DFILTER_NEAREST;
2443 break;
2444 case WINED3DTEXF_LINEAR:
2445 *Value = D3DFILTER_LINEAR;
2446 break;
2447 default:
2448 ERR("Unhandled texture mag %d !\n",tex_mag);
2449 *Value = 0;
2451 break;
2454 case D3DRENDERSTATE_TEXTUREMIN:
2456 WINED3DTEXTUREFILTERTYPE tex_min;
2458 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2459 0, WINED3DSAMP_MINFILTER,
2460 &tex_min);
2462 switch (tex_min)
2464 case WINED3DTEXF_POINT:
2465 *Value = D3DFILTER_NEAREST;
2466 break;
2467 case WINED3DTEXF_LINEAR:
2468 *Value = D3DFILTER_LINEAR;
2469 break;
2470 default:
2471 ERR("Unhandled texture mag %d !\n",tex_min);
2472 *Value = 0;
2474 break;
2477 case D3DRENDERSTATE_TEXTUREADDRESS:
2478 case D3DRENDERSTATE_TEXTUREADDRESSU:
2479 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2480 0, WINED3DSAMP_ADDRESSU,
2481 Value);
2482 break;
2483 case D3DRENDERSTATE_TEXTUREADDRESSV:
2484 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2485 0, WINED3DSAMP_ADDRESSV,
2486 Value);
2487 break;
2489 default:
2490 /* FIXME: Unhandled: D3DRENDERSTATE_STIPPLEPATTERN00 - 31 */
2491 hr = IWineD3DDevice_GetRenderState(This->wineD3DDevice,
2492 RenderStateType,
2493 Value);
2495 LeaveCriticalSection(&ddraw_cs);
2496 return hr;
2499 static HRESULT WINAPI
2500 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2501 D3DRENDERSTATETYPE RenderStateType,
2502 DWORD *Value)
2504 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2507 static HRESULT WINAPI
2508 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2509 D3DRENDERSTATETYPE RenderStateType,
2510 DWORD *Value)
2512 HRESULT hr;
2513 WORD old_fpucw;
2515 old_fpucw = d3d_fpu_setup();
2516 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2517 set_fpu_control_word(old_fpucw);
2519 return hr;
2522 static HRESULT WINAPI
2523 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2524 D3DRENDERSTATETYPE dwRenderStateType,
2525 DWORD *lpdwRenderState)
2527 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2528 HRESULT hr;
2529 TRACE("(%p)->(%08x,%p)\n", This, dwRenderStateType, lpdwRenderState);
2531 switch(dwRenderStateType)
2533 case D3DRENDERSTATE_TEXTUREHANDLE:
2535 /* This state is wrapped to SetTexture in SetRenderState, so
2536 * it has to be wrapped to GetTexture here
2538 IWineD3DBaseTexture *tex = NULL;
2539 *lpdwRenderState = 0;
2541 EnterCriticalSection(&ddraw_cs);
2543 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2545 &tex);
2547 if(hr == WINED3D_OK && tex)
2549 IDirectDrawSurface7 *parent = NULL;
2550 hr = IWineD3DBaseTexture_GetParent(tex,
2551 (IUnknown **) &parent);
2552 if(parent)
2554 /* The parent of the texture is the IDirectDrawSurface7 interface
2555 * of the ddraw surface
2557 IDirectDrawSurfaceImpl *texImpl = ICOM_OBJECT(IDirectDrawSurfaceImpl,
2558 IDirectDrawSurface7,
2559 parent);
2560 *lpdwRenderState = texImpl->Handle;
2561 IDirectDrawSurface7_Release(parent);
2563 IWineD3DBaseTexture_Release(tex);
2566 LeaveCriticalSection(&ddraw_cs);
2568 return hr;
2571 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2573 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2574 the mapping to get the value. */
2575 DWORD colorop, colorarg1, colorarg2;
2576 DWORD alphaop, alphaarg1, alphaarg2;
2578 EnterCriticalSection(&ddraw_cs);
2580 This->legacyTextureBlending = TRUE;
2582 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, &colorop);
2583 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, &colorarg1);
2584 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, &colorarg2);
2585 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, &alphaop);
2586 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2587 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2589 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2590 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2592 *lpdwRenderState = D3DTBLEND_DECAL;
2594 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2595 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2597 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2599 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2600 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2602 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2604 else
2606 HRESULT hr;
2607 BOOL tex_alpha = FALSE;
2608 IWineD3DBaseTexture *tex = NULL;
2609 WINED3DSURFACE_DESC desc;
2610 WINED3DFORMAT fmt;
2611 DDPIXELFORMAT ddfmt;
2613 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2615 &tex);
2617 if(hr == WINED3D_OK && tex)
2619 memset(&desc, 0, sizeof(desc));
2620 desc.Format = &fmt;
2621 hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2622 if (SUCCEEDED(hr))
2624 ddfmt.dwSize = sizeof(ddfmt);
2625 PixelFormat_WineD3DtoDD(&ddfmt, fmt);
2626 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2629 IWineD3DBaseTexture_Release(tex);
2632 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2633 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == (tex_alpha ? WINED3DTA_TEXTURE : WINED3DTA_CURRENT)))
2635 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2638 *lpdwRenderState = D3DTBLEND_MODULATE;
2641 LeaveCriticalSection(&ddraw_cs);
2643 return D3D_OK;
2646 default:
2647 return IDirect3DDevice7_GetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
2648 dwRenderStateType,
2649 lpdwRenderState);
2653 static HRESULT WINAPI
2654 Thunk_IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2655 D3DRENDERSTATETYPE dwRenderStateType,
2656 DWORD *lpdwRenderState)
2658 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2659 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice3 interface.\n", This, dwRenderStateType, lpdwRenderState);
2660 return IDirect3DDevice3_GetRenderState(ICOM_INTERFACE(This, IDirect3DDevice3),
2661 dwRenderStateType,
2662 lpdwRenderState);
2665 /*****************************************************************************
2666 * IDirect3DDevice7::SetRenderState
2668 * Sets a render state. The possible render states are defined in
2669 * include/d3dtypes.h
2671 * Version 2, 3 and 7
2673 * Params:
2674 * RenderStateType: State to set
2675 * Value: Value to assign to that state
2677 * Returns:
2678 * D3D_OK on success,
2679 * for details see IWineD3DDevice::SetRenderState
2681 *****************************************************************************/
2682 static HRESULT
2683 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2684 D3DRENDERSTATETYPE RenderStateType,
2685 DWORD Value)
2687 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2688 HRESULT hr;
2689 TRACE("(%p)->(%08x,%d): Relay\n", This, RenderStateType, Value);
2691 EnterCriticalSection(&ddraw_cs);
2692 /* Some render states need special care */
2693 switch(RenderStateType)
2695 case D3DRENDERSTATE_TEXTUREMAG:
2697 WINED3DTEXTUREFILTERTYPE tex_mag = WINED3DTEXF_NONE;
2699 switch ((D3DTEXTUREFILTER) Value)
2701 case D3DFILTER_NEAREST:
2702 case D3DFILTER_LINEARMIPNEAREST:
2703 tex_mag = WINED3DTEXF_POINT;
2704 break;
2705 case D3DFILTER_LINEAR:
2706 case D3DFILTER_LINEARMIPLINEAR:
2707 tex_mag = WINED3DTEXF_LINEAR;
2708 break;
2709 default:
2710 ERR("Unhandled texture mag %d !\n",Value);
2713 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2714 0, WINED3DSAMP_MAGFILTER,
2715 tex_mag);
2716 break;
2719 case D3DRENDERSTATE_TEXTUREMIN:
2721 WINED3DTEXTUREFILTERTYPE tex_min = WINED3DTEXF_NONE;
2722 WINED3DTEXTUREFILTERTYPE tex_mip = WINED3DTEXF_NONE;
2724 switch ((D3DTEXTUREFILTER) Value)
2726 case D3DFILTER_NEAREST:
2727 tex_min = WINED3DTEXF_POINT;
2728 break;
2729 case D3DFILTER_LINEAR:
2730 tex_min = WINED3DTEXF_LINEAR;
2731 break;
2732 case D3DFILTER_MIPNEAREST:
2733 tex_min = WINED3DTEXF_NONE;
2734 tex_mip = WINED3DTEXF_POINT;
2735 break;
2736 case D3DFILTER_MIPLINEAR:
2737 tex_min = WINED3DTEXF_NONE;
2738 tex_mip = WINED3DTEXF_LINEAR;
2739 break;
2740 case D3DFILTER_LINEARMIPNEAREST:
2741 tex_min = WINED3DTEXF_POINT;
2742 tex_mip = WINED3DTEXF_LINEAR;
2743 break;
2744 case D3DFILTER_LINEARMIPLINEAR:
2745 tex_min = WINED3DTEXF_LINEAR;
2746 tex_mip = WINED3DTEXF_LINEAR;
2747 break;
2749 default:
2750 ERR("Unhandled texture min %d !\n",Value);
2753 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2754 0, WINED3DSAMP_MIPFILTER,
2755 tex_mip);
2756 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2757 0, WINED3DSAMP_MINFILTER,
2758 tex_min);
2759 break;
2762 case D3DRENDERSTATE_TEXTUREADDRESS:
2763 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2764 0, WINED3DSAMP_ADDRESSV,
2765 Value);
2766 /* Drop through */
2767 case D3DRENDERSTATE_TEXTUREADDRESSU:
2768 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2769 0, WINED3DSAMP_ADDRESSU,
2770 Value);
2771 break;
2772 case D3DRENDERSTATE_TEXTUREADDRESSV:
2773 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2774 0, WINED3DSAMP_ADDRESSV,
2775 Value);
2776 break;
2778 default:
2780 /* FIXME: Unhandled: D3DRENDERSTATE_STIPPLEPATTERN00 - 31 */
2782 hr = IWineD3DDevice_SetRenderState(This->wineD3DDevice,
2783 RenderStateType,
2784 Value);
2785 break;
2787 LeaveCriticalSection(&ddraw_cs);
2788 return hr;
2791 static HRESULT WINAPI
2792 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2793 D3DRENDERSTATETYPE RenderStateType,
2794 DWORD Value)
2796 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2799 static HRESULT WINAPI
2800 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2801 D3DRENDERSTATETYPE RenderStateType,
2802 DWORD Value)
2804 HRESULT hr;
2805 WORD old_fpucw;
2807 old_fpucw = d3d_fpu_setup();
2808 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2809 set_fpu_control_word(old_fpucw);
2811 return hr;
2814 static HRESULT WINAPI
2815 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2816 D3DRENDERSTATETYPE RenderStateType,
2817 DWORD Value)
2819 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2820 for this state can be directly mapped to texture stage colorop and alphaop, but
2821 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2822 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2823 alphaarg when needed.
2825 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2827 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2828 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2829 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2830 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2831 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2832 in device - TRUE if the app is using TEXTUREMAPBLEND.
2834 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2835 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2836 unless some broken game will be found that cares. */
2838 HRESULT hr;
2839 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
2840 TRACE("(%p)->(%08x,%d)\n", This, RenderStateType, Value);
2842 EnterCriticalSection(&ddraw_cs);
2844 switch(RenderStateType)
2846 case D3DRENDERSTATE_TEXTUREHANDLE:
2848 if(Value == 0)
2850 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
2852 NULL);
2853 break;
2856 if(Value > This->numHandles)
2858 FIXME("Specified handle %d out of range\n", Value);
2859 hr = DDERR_INVALIDPARAMS;
2860 break;
2862 if(This->Handles[Value - 1].type != DDrawHandle_Texture)
2864 FIXME("Handle %d isn't a texture handle\n", Value);
2865 hr = DDERR_INVALIDPARAMS;
2866 break;
2868 else
2870 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *) This->Handles[Value - 1].ptr;
2871 hr = IDirect3DDevice3_SetTexture(iface, 0, ICOM_INTERFACE(surf, IDirect3DTexture2));
2872 break;
2876 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2878 This->legacyTextureBlending = TRUE;
2880 switch ( (D3DTEXTUREBLEND) Value)
2882 case D3DTBLEND_MODULATE:
2884 BOOL tex_alpha = FALSE;
2885 IWineD3DBaseTexture *tex = NULL;
2886 WINED3DSURFACE_DESC desc;
2887 WINED3DFORMAT fmt;
2888 DDPIXELFORMAT ddfmt;
2890 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2892 &tex);
2894 if(hr == WINED3D_OK && tex)
2896 memset(&desc, 0, sizeof(desc));
2897 desc.Format = &fmt;
2898 hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2899 if (SUCCEEDED(hr))
2901 ddfmt.dwSize = sizeof(ddfmt);
2902 PixelFormat_WineD3DtoDD(&ddfmt, fmt);
2903 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2906 IWineD3DBaseTexture_Release(tex);
2909 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2910 if (tex_alpha)
2912 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2914 else
2916 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_CURRENT);
2919 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2920 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2921 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2923 break;
2926 case D3DTBLEND_ADD:
2927 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2928 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2929 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2930 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2931 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2932 break;
2934 case D3DTBLEND_MODULATEALPHA:
2935 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2936 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2937 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2938 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2939 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2940 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2941 break;
2943 case D3DTBLEND_COPY:
2944 case D3DTBLEND_DECAL:
2945 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2946 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2947 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2948 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2949 break;
2951 case D3DTBLEND_DECALALPHA:
2952 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2953 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2954 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2955 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2956 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2957 break;
2959 default:
2960 ERR("Unhandled texture environment %d !\n",Value);
2963 hr = D3D_OK;
2964 break;
2967 default:
2968 hr = IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
2969 RenderStateType,
2970 Value);
2971 break;
2974 LeaveCriticalSection(&ddraw_cs);
2976 return hr;
2979 static HRESULT WINAPI
2980 Thunk_IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2981 D3DRENDERSTATETYPE RenderStateType,
2982 DWORD Value)
2984 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
2985 TRACE_(ddraw_thunk)("(%p)->(%08x,%d) thunking to IDirect3DDevice3 interface.\n", This, RenderStateType, Value);
2986 return IDirect3DDevice3_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice3), RenderStateType, Value);
2989 /*****************************************************************************
2990 * Direct3DDevice3::SetLightState
2992 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2993 * light states are forwarded to Direct3DDevice7 render states
2995 * Version 2 and 3
2997 * Params:
2998 * LightStateType: The light state to change
2999 * Value: The value to assign to that light state
3001 * Returns:
3002 * D3D_OK on success
3003 * DDERR_INVALIDPARAMS if the parameters were incorrect
3004 * Also check IDirect3DDevice7::SetRenderState
3006 *****************************************************************************/
3007 static HRESULT WINAPI
3008 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
3009 D3DLIGHTSTATETYPE LightStateType,
3010 DWORD Value)
3012 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3013 HRESULT hr;
3015 TRACE("(%p)->(%08x,%08x)\n", This, LightStateType, Value);
3017 if (!LightStateType && (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3019 TRACE("Unexpected Light State Type\n");
3020 return DDERR_INVALIDPARAMS;
3023 EnterCriticalSection(&ddraw_cs);
3024 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3026 IDirect3DMaterialImpl *mat;
3028 if(Value == 0) mat = NULL;
3029 else if(Value > This->numHandles)
3031 ERR("Material handle out of range(%d)\n", Value);
3032 LeaveCriticalSection(&ddraw_cs);
3033 return DDERR_INVALIDPARAMS;
3035 else if(This->Handles[Value - 1].type != DDrawHandle_Material)
3037 ERR("Invalid handle %d\n", Value);
3038 LeaveCriticalSection(&ddraw_cs);
3039 return DDERR_INVALIDPARAMS;
3041 else
3043 mat = (IDirect3DMaterialImpl *) This->Handles[Value - 1].ptr;
3046 if (mat != NULL)
3048 TRACE(" activating material %p.\n", mat);
3049 mat->activate(mat);
3051 else
3053 FIXME(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
3055 This->material = Value;
3057 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3059 switch (Value)
3061 case D3DCOLOR_MONO:
3062 ERR("DDCOLOR_MONO should not happen!\n");
3063 break;
3064 case D3DCOLOR_RGB:
3065 /* We are already in this mode */
3066 TRACE("Setting color model to RGB (no-op).\n");
3067 break;
3068 default:
3069 ERR("Unknown color model!\n");
3070 LeaveCriticalSection(&ddraw_cs);
3071 return DDERR_INVALIDPARAMS;
3074 else
3076 D3DRENDERSTATETYPE rs;
3077 switch (LightStateType)
3079 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3080 rs = D3DRENDERSTATE_AMBIENT;
3081 break;
3082 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3083 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3084 break;
3085 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3086 rs = D3DRENDERSTATE_FOGSTART;
3087 break;
3088 case D3DLIGHTSTATE_FOGEND: /* 6 */
3089 rs = D3DRENDERSTATE_FOGEND;
3090 break;
3091 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3092 rs = D3DRENDERSTATE_FOGDENSITY;
3093 break;
3094 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3095 rs = D3DRENDERSTATE_COLORVERTEX;
3096 break;
3097 default:
3098 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3099 LeaveCriticalSection(&ddraw_cs);
3100 return DDERR_INVALIDPARAMS;
3103 hr = IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
3105 Value);
3106 LeaveCriticalSection(&ddraw_cs);
3107 return hr;
3110 LeaveCriticalSection(&ddraw_cs);
3111 return D3D_OK;
3114 static HRESULT WINAPI
3115 Thunk_IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3116 D3DLIGHTSTATETYPE LightStateType,
3117 DWORD Value)
3119 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3120 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x) thunking to IDirect3DDevice3 interface.\n", This, LightStateType, Value);
3121 return IDirect3DDevice3_SetLightState(ICOM_INTERFACE(This, IDirect3DDevice3),
3122 LightStateType,
3123 Value);
3126 /*****************************************************************************
3127 * IDirect3DDevice3::GetLightState
3129 * Returns the current setting of a light state. The state is read from
3130 * the Direct3DDevice7 render state.
3132 * Version 2 and 3
3134 * Params:
3135 * LightStateType: The light state to return
3136 * Value: The address to store the light state setting at
3138 * Returns:
3139 * D3D_OK on success
3140 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3141 * Also see IDirect3DDevice7::GetRenderState
3143 *****************************************************************************/
3144 static HRESULT WINAPI
3145 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3146 D3DLIGHTSTATETYPE LightStateType,
3147 DWORD *Value)
3149 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3150 HRESULT hr;
3152 TRACE("(%p)->(%08x,%p)\n", This, LightStateType, Value);
3154 if (!LightStateType && (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3156 TRACE("Unexpected Light State Type\n");
3157 return DDERR_INVALIDPARAMS;
3160 if(!Value)
3161 return DDERR_INVALIDPARAMS;
3163 EnterCriticalSection(&ddraw_cs);
3164 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3166 *Value = This->material;
3168 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3170 *Value = D3DCOLOR_RGB;
3172 else
3174 D3DRENDERSTATETYPE rs;
3175 switch (LightStateType)
3177 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3178 rs = D3DRENDERSTATE_AMBIENT;
3179 break;
3180 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3181 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3182 break;
3183 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3184 rs = D3DRENDERSTATE_FOGSTART;
3185 break;
3186 case D3DLIGHTSTATE_FOGEND: /* 6 */
3187 rs = D3DRENDERSTATE_FOGEND;
3188 break;
3189 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3190 rs = D3DRENDERSTATE_FOGDENSITY;
3191 break;
3192 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3193 rs = D3DRENDERSTATE_COLORVERTEX;
3194 break;
3195 default:
3196 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3197 LeaveCriticalSection(&ddraw_cs);
3198 return DDERR_INVALIDPARAMS;
3201 hr = IDirect3DDevice7_GetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
3203 Value);
3204 LeaveCriticalSection(&ddraw_cs);
3205 return hr;
3208 LeaveCriticalSection(&ddraw_cs);
3209 return D3D_OK;
3212 static HRESULT WINAPI
3213 Thunk_IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3214 D3DLIGHTSTATETYPE LightStateType,
3215 DWORD *Value)
3217 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3218 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice3 interface.\n", This, LightStateType, Value);
3219 return IDirect3DDevice3_GetLightState(ICOM_INTERFACE(This, IDirect3DDevice3),
3220 LightStateType,
3221 Value);
3224 /*****************************************************************************
3225 * IDirect3DDevice7::SetTransform
3227 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3228 * in include/d3dtypes.h.
3229 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3230 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3231 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3233 * Version 2, 3 and 7
3235 * Params:
3236 * TransformStateType: transform state to set
3237 * Matrix: Matrix to assign to the state
3239 * Returns:
3240 * D3D_OK on success
3241 * DDERR_INVALIDPARAMS if Matrix == NULL
3242 * For details see IWineD3DDevice::SetTransform
3244 *****************************************************************************/
3245 static HRESULT
3246 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3247 D3DTRANSFORMSTATETYPE TransformStateType,
3248 D3DMATRIX *Matrix)
3250 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3251 D3DTRANSFORMSTATETYPE type;
3252 HRESULT hr;
3253 TRACE("(%p)->(%08x,%p): Relay\n", This, TransformStateType, Matrix);
3255 switch(TransformStateType)
3257 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3258 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3259 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3260 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3261 default: type = TransformStateType;
3264 if(!Matrix)
3265 return DDERR_INVALIDPARAMS;
3267 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3268 EnterCriticalSection(&ddraw_cs);
3269 hr = IWineD3DDevice_SetTransform(This->wineD3DDevice,
3270 type,
3271 (WINED3DMATRIX*) Matrix);
3272 LeaveCriticalSection(&ddraw_cs);
3273 return hr;
3276 static HRESULT WINAPI
3277 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3278 D3DTRANSFORMSTATETYPE TransformStateType,
3279 D3DMATRIX *Matrix)
3281 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3284 static HRESULT WINAPI
3285 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3286 D3DTRANSFORMSTATETYPE TransformStateType,
3287 D3DMATRIX *Matrix)
3289 HRESULT hr;
3290 WORD old_fpucw;
3292 old_fpucw = d3d_fpu_setup();
3293 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3294 set_fpu_control_word(old_fpucw);
3296 return hr;
3299 static HRESULT WINAPI
3300 Thunk_IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3301 D3DTRANSFORMSTATETYPE TransformStateType,
3302 D3DMATRIX *D3DMatrix)
3304 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3305 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3306 return IDirect3DDevice7_SetTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
3307 TransformStateType,
3308 D3DMatrix);
3311 static HRESULT WINAPI
3312 Thunk_IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3313 D3DTRANSFORMSTATETYPE TransformStateType,
3314 D3DMATRIX *D3DMatrix)
3316 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3317 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3318 return IDirect3DDevice7_SetTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
3319 TransformStateType,
3320 D3DMatrix);
3323 /*****************************************************************************
3324 * IDirect3DDevice7::GetTransform
3326 * Returns the matrix assigned to a transform state
3327 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3328 * SetTransform
3330 * Params:
3331 * TransformStateType: State to read the matrix from
3332 * Matrix: Address to store the matrix at
3334 * Returns:
3335 * D3D_OK on success
3336 * DDERR_INVALIDPARAMS if Matrix == NULL
3337 * For details, see IWineD3DDevice::GetTransform
3339 *****************************************************************************/
3340 static HRESULT
3341 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3342 D3DTRANSFORMSTATETYPE TransformStateType,
3343 D3DMATRIX *Matrix)
3345 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3346 D3DTRANSFORMSTATETYPE type;
3347 HRESULT hr;
3348 TRACE("(%p)->(%08x,%p): Relay\n", This, TransformStateType, Matrix);
3350 switch(TransformStateType)
3352 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3353 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3354 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3355 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3356 default: type = TransformStateType;
3359 if(!Matrix)
3360 return DDERR_INVALIDPARAMS;
3362 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3363 EnterCriticalSection(&ddraw_cs);
3364 hr = IWineD3DDevice_GetTransform(This->wineD3DDevice, type, (WINED3DMATRIX*) Matrix);
3365 LeaveCriticalSection(&ddraw_cs);
3366 return hr;
3369 static HRESULT WINAPI
3370 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3371 D3DTRANSFORMSTATETYPE TransformStateType,
3372 D3DMATRIX *Matrix)
3374 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3377 static HRESULT WINAPI
3378 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3379 D3DTRANSFORMSTATETYPE TransformStateType,
3380 D3DMATRIX *Matrix)
3382 HRESULT hr;
3383 WORD old_fpucw;
3385 old_fpucw = d3d_fpu_setup();
3386 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3387 set_fpu_control_word(old_fpucw);
3389 return hr;
3392 static HRESULT WINAPI
3393 Thunk_IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3394 D3DTRANSFORMSTATETYPE TransformStateType,
3395 D3DMATRIX *D3DMatrix)
3397 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3398 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3399 return IDirect3DDevice7_GetTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
3400 TransformStateType,
3401 D3DMatrix);
3404 static HRESULT WINAPI
3405 Thunk_IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3406 D3DTRANSFORMSTATETYPE TransformStateType,
3407 D3DMATRIX *D3DMatrix)
3409 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3410 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3411 return IDirect3DDevice7_GetTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
3412 TransformStateType,
3413 D3DMatrix);
3416 /*****************************************************************************
3417 * IDirect3DDevice7::MultiplyTransform
3419 * Multiplies the already-set transform matrix of a transform state
3420 * with another matrix. For the world matrix, see SetTransform
3422 * Version 2, 3 and 7
3424 * Params:
3425 * TransformStateType: Transform state to multiply
3426 * D3DMatrix Matrix to multiply with.
3428 * Returns
3429 * D3D_OK on success
3430 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3431 * For details, see IWineD3DDevice::MultiplyTransform
3433 *****************************************************************************/
3434 static HRESULT
3435 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3436 D3DTRANSFORMSTATETYPE TransformStateType,
3437 D3DMATRIX *D3DMatrix)
3439 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3440 HRESULT hr;
3441 D3DTRANSFORMSTATETYPE type;
3442 TRACE("(%p)->(%08x,%p): Relay\n", This, TransformStateType, D3DMatrix);
3444 switch(TransformStateType)
3446 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3447 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3448 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3449 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3450 default: type = TransformStateType;
3453 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3454 EnterCriticalSection(&ddraw_cs);
3455 hr = IWineD3DDevice_MultiplyTransform(This->wineD3DDevice,
3456 type,
3457 (WINED3DMATRIX*) D3DMatrix);
3458 LeaveCriticalSection(&ddraw_cs);
3459 return hr;
3462 static HRESULT WINAPI
3463 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3464 D3DTRANSFORMSTATETYPE TransformStateType,
3465 D3DMATRIX *D3DMatrix)
3467 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3470 static HRESULT WINAPI
3471 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3472 D3DTRANSFORMSTATETYPE TransformStateType,
3473 D3DMATRIX *D3DMatrix)
3475 HRESULT hr;
3476 WORD old_fpucw;
3478 old_fpucw = d3d_fpu_setup();
3479 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3480 set_fpu_control_word(old_fpucw);
3482 return hr;
3485 static HRESULT WINAPI
3486 Thunk_IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3487 D3DTRANSFORMSTATETYPE TransformStateType,
3488 D3DMATRIX *D3DMatrix)
3490 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3491 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3492 return IDirect3DDevice7_MultiplyTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
3493 TransformStateType,
3494 D3DMatrix);
3497 static HRESULT WINAPI
3498 Thunk_IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3499 D3DTRANSFORMSTATETYPE TransformStateType,
3500 D3DMATRIX *D3DMatrix)
3502 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3503 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3504 return IDirect3DDevice7_MultiplyTransform(ICOM_INTERFACE(This, IDirect3DDevice7),
3505 TransformStateType,
3506 D3DMatrix);
3509 /*****************************************************************************
3510 * IDirect3DDevice7::DrawPrimitive
3512 * Draws primitives based on vertices in an application-provided pointer
3514 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3515 * an FVF format for D3D7
3517 * Params:
3518 * PrimitiveType: The type of the primitives to draw
3519 * Vertex type: Flexible vertex format vertex description
3520 * Vertices: Pointer to the vertex array
3521 * VertexCount: The number of vertices to draw
3522 * Flags: As usual a few flags
3524 * Returns:
3525 * D3D_OK on success
3526 * DDERR_INVALIDPARAMS if Vertices is NULL
3527 * For details, see IWineD3DDevice::DrawPrimitiveUP
3529 *****************************************************************************/
3530 static HRESULT
3531 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3532 D3DPRIMITIVETYPE PrimitiveType,
3533 DWORD VertexType,
3534 void *Vertices,
3535 DWORD VertexCount,
3536 DWORD Flags)
3538 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3539 UINT PrimitiveCount, stride;
3540 HRESULT hr;
3541 TRACE("(%p)->(%08x,%08x,%p,%08x,%08x): Relay!\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3543 if(!Vertices)
3544 return DDERR_INVALIDPARAMS;
3546 /* Get the vertex count */
3547 switch(PrimitiveType)
3549 case D3DPT_POINTLIST:
3550 PrimitiveCount = VertexCount;
3551 break;
3553 case D3DPT_LINELIST:
3554 PrimitiveCount = VertexCount / 2;
3555 break;
3557 case D3DPT_LINESTRIP:
3558 PrimitiveCount = VertexCount - 1;
3559 break;
3561 case D3DPT_TRIANGLELIST:
3562 PrimitiveCount = VertexCount / 3;
3563 break;
3565 case D3DPT_TRIANGLESTRIP:
3566 PrimitiveCount = VertexCount - 2;
3567 break;
3569 case D3DPT_TRIANGLEFAN:
3570 PrimitiveCount = VertexCount - 2;
3571 break;
3573 default:
3574 return DDERR_INVALIDPARAMS;
3577 /* Get the stride */
3578 stride = get_flexible_vertex_size(VertexType);
3580 /* Set the FVF */
3581 EnterCriticalSection(&ddraw_cs);
3582 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
3583 IDirectDrawImpl_FindDecl(This->ddraw, VertexType));
3584 if(hr != D3D_OK)
3586 LeaveCriticalSection(&ddraw_cs);
3587 return hr;
3590 /* This method translates to the user pointer draw of WineD3D */
3591 hr = IWineD3DDevice_DrawPrimitiveUP(This->wineD3DDevice,
3592 PrimitiveType,
3593 PrimitiveCount,
3594 Vertices,
3595 stride);
3596 LeaveCriticalSection(&ddraw_cs);
3597 return hr;
3600 static HRESULT WINAPI
3601 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3602 D3DPRIMITIVETYPE PrimitiveType,
3603 DWORD VertexType,
3604 void *Vertices,
3605 DWORD VertexCount,
3606 DWORD Flags)
3608 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3611 static HRESULT WINAPI
3612 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3613 D3DPRIMITIVETYPE PrimitiveType,
3614 DWORD VertexType,
3615 void *Vertices,
3616 DWORD VertexCount,
3617 DWORD Flags)
3619 HRESULT hr;
3620 WORD old_fpucw;
3622 old_fpucw = d3d_fpu_setup();
3623 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3624 set_fpu_control_word(old_fpucw);
3626 return hr;
3629 static HRESULT WINAPI
3630 Thunk_IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3631 D3DPRIMITIVETYPE PrimitiveType,
3632 DWORD VertexType,
3633 void *Vertices,
3634 DWORD VertexCount,
3635 DWORD Flags)
3637 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3638 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3639 return IDirect3DDevice7_DrawPrimitive(ICOM_INTERFACE(This, IDirect3DDevice7),
3640 PrimitiveType,
3641 VertexType,
3642 Vertices,
3643 VertexCount,
3644 Flags);
3647 static HRESULT WINAPI
3648 Thunk_IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3649 D3DPRIMITIVETYPE PrimitiveType,
3650 D3DVERTEXTYPE VertexType,
3651 void *Vertices,
3652 DWORD VertexCount,
3653 DWORD Flags)
3655 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3656 DWORD FVF;
3657 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3659 switch(VertexType)
3661 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3662 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3663 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3664 default:
3665 ERR("Unexpected vertex type %d\n", VertexType);
3666 return DDERR_INVALIDPARAMS; /* Should never happen */
3669 return IDirect3DDevice7_DrawPrimitive(ICOM_INTERFACE(This, IDirect3DDevice7),
3670 PrimitiveType,
3671 FVF,
3672 Vertices,
3673 VertexCount,
3674 Flags);
3677 /*****************************************************************************
3678 * IDirect3DDevice7::DrawIndexedPrimitive
3680 * Draws vertices from an application-provided pointer, based on the index
3681 * numbers in a WORD array.
3683 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3684 * an FVF format for D3D7
3686 * Params:
3687 * PrimitiveType: The primitive type to draw
3688 * VertexType: The FVF vertex description
3689 * Vertices: Pointer to the vertex array
3690 * VertexCount: ?
3691 * Indices: Pointer to the index array
3692 * IndexCount: Number of indices = Number of vertices to draw
3693 * Flags: As usual, some flags
3695 * Returns:
3696 * D3D_OK on success
3697 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3698 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3700 *****************************************************************************/
3701 static HRESULT
3702 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3703 D3DPRIMITIVETYPE PrimitiveType,
3704 DWORD VertexType,
3705 void *Vertices,
3706 DWORD VertexCount,
3707 WORD *Indices,
3708 DWORD IndexCount,
3709 DWORD Flags)
3711 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3712 UINT PrimitiveCount = 0;
3713 HRESULT hr;
3714 TRACE("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x): Relay!\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3716 /* Get the primitive number */
3717 switch(PrimitiveType)
3719 case D3DPT_POINTLIST:
3720 PrimitiveCount = IndexCount;
3721 break;
3723 case D3DPT_LINELIST:
3724 PrimitiveCount = IndexCount / 2;
3725 break;
3727 case D3DPT_LINESTRIP:
3728 PrimitiveCount = IndexCount - 1;
3729 break;
3731 case D3DPT_TRIANGLELIST:
3732 PrimitiveCount = IndexCount / 3;
3733 break;
3735 case D3DPT_TRIANGLESTRIP:
3736 PrimitiveCount = IndexCount - 2;
3737 break;
3739 case D3DPT_TRIANGLEFAN:
3740 PrimitiveCount = IndexCount - 2;
3741 break;
3743 default:
3744 return DDERR_INVALIDPARAMS;
3747 /* Set the D3DDevice's FVF */
3748 EnterCriticalSection(&ddraw_cs);
3749 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
3750 IDirectDrawImpl_FindDecl(This->ddraw, VertexType));
3751 if(FAILED(hr))
3753 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3754 LeaveCriticalSection(&ddraw_cs);
3755 return hr;
3758 hr = IWineD3DDevice_DrawIndexedPrimitiveUP(This->wineD3DDevice,
3759 PrimitiveType,
3760 0 /* MinVertexIndex */,
3761 VertexCount /* UINT NumVertexIndex */,
3762 PrimitiveCount,
3763 Indices,
3764 WINED3DFMT_INDEX16,
3765 Vertices,
3766 get_flexible_vertex_size(VertexType));
3767 LeaveCriticalSection(&ddraw_cs);
3768 return hr;
3771 static HRESULT WINAPI
3772 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3773 D3DPRIMITIVETYPE PrimitiveType,
3774 DWORD VertexType,
3775 void *Vertices,
3776 DWORD VertexCount,
3777 WORD *Indices,
3778 DWORD IndexCount,
3779 DWORD Flags)
3781 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3784 static HRESULT WINAPI
3785 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3786 D3DPRIMITIVETYPE PrimitiveType,
3787 DWORD VertexType,
3788 void *Vertices,
3789 DWORD VertexCount,
3790 WORD *Indices,
3791 DWORD IndexCount,
3792 DWORD Flags)
3794 HRESULT hr;
3795 WORD old_fpucw;
3797 old_fpucw = d3d_fpu_setup();
3798 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3799 set_fpu_control_word(old_fpucw);
3801 return hr;
3804 static HRESULT WINAPI
3805 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3806 D3DPRIMITIVETYPE PrimitiveType,
3807 DWORD VertexType,
3808 void *Vertices,
3809 DWORD VertexCount,
3810 WORD *Indices,
3811 DWORD IndexCount,
3812 DWORD Flags)
3814 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3815 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3816 return IDirect3DDevice7_DrawIndexedPrimitive(ICOM_INTERFACE(This, IDirect3DDevice7),
3817 PrimitiveType,
3818 VertexType,
3819 Vertices,
3820 VertexCount,
3821 Indices,
3822 IndexCount,
3823 Flags);
3826 static HRESULT WINAPI
3827 Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3828 D3DPRIMITIVETYPE PrimitiveType,
3829 D3DVERTEXTYPE VertexType,
3830 void *Vertices,
3831 DWORD VertexCount,
3832 WORD *Indices,
3833 DWORD IndexCount,
3834 DWORD Flags)
3836 DWORD FVF;
3837 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3838 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3840 switch(VertexType)
3842 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3843 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3844 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3845 default:
3846 ERR("Unexpected vertex type %d\n", VertexType);
3847 return DDERR_INVALIDPARAMS; /* Should never happen */
3850 return IDirect3DDevice7_DrawIndexedPrimitive(ICOM_INTERFACE(This, IDirect3DDevice7),
3851 PrimitiveType,
3852 FVF,
3853 Vertices,
3854 VertexCount,
3855 Indices,
3856 IndexCount,
3857 Flags);
3860 /*****************************************************************************
3861 * IDirect3DDevice7::SetClipStatus
3863 * Sets the clip status. This defines things as clipping conditions and
3864 * the extents of the clipping region.
3866 * Version 2, 3 and 7
3868 * Params:
3869 * ClipStatus:
3871 * Returns:
3872 * D3D_OK because it's a stub
3873 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3875 *****************************************************************************/
3876 static HRESULT WINAPI
3877 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3878 D3DCLIPSTATUS *ClipStatus)
3880 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3881 FIXME("(%p)->(%p): Stub!\n", This, ClipStatus);
3883 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3884 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3886 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3887 return D3D_OK;
3890 static HRESULT WINAPI
3891 Thunk_IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3892 D3DCLIPSTATUS *ClipStatus)
3894 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3895 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3896 return IDirect3DDevice7_SetClipStatus(ICOM_INTERFACE(This, IDirect3DDevice7),
3897 ClipStatus);
3900 static HRESULT WINAPI
3901 Thunk_IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3902 D3DCLIPSTATUS *ClipStatus)
3904 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3905 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3906 return IDirect3DDevice7_SetClipStatus(ICOM_INTERFACE(This, IDirect3DDevice7),
3907 ClipStatus);
3910 /*****************************************************************************
3911 * IDirect3DDevice7::GetClipStatus
3913 * Returns the clip status
3915 * Params:
3916 * ClipStatus: Address to write the clip status to
3918 * Returns:
3919 * D3D_OK because it's a stub
3921 *****************************************************************************/
3922 static HRESULT WINAPI
3923 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3924 D3DCLIPSTATUS *ClipStatus)
3926 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3927 FIXME("(%p)->(%p): Stub!\n", This, ClipStatus);
3929 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3930 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3931 return D3D_OK;
3934 static HRESULT WINAPI
3935 Thunk_IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3936 D3DCLIPSTATUS *ClipStatus)
3938 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
3939 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3940 return IDirect3DDevice7_GetClipStatus(ICOM_INTERFACE(This, IDirect3DDevice7),
3941 ClipStatus);
3944 static HRESULT WINAPI
3945 Thunk_IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3946 D3DCLIPSTATUS *ClipStatus)
3948 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
3949 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3950 return IDirect3DDevice7_GetClipStatus(ICOM_INTERFACE(This, IDirect3DDevice7),
3951 ClipStatus);
3954 /*****************************************************************************
3955 * IDirect3DDevice::DrawPrimitiveStrided
3957 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3959 * Version 3 and 7
3961 * Params:
3962 * PrimitiveType: The primitive type to draw
3963 * VertexType: The FVF description of the vertices to draw (for the stride??)
3964 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3965 * the vertex data locations
3966 * VertexCount: The number of vertices to draw
3967 * Flags: Some flags
3969 * Returns:
3970 * D3D_OK, because it's a stub
3971 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3972 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3974 *****************************************************************************/
3975 static HRESULT
3976 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3977 D3DPRIMITIVETYPE PrimitiveType,
3978 DWORD VertexType,
3979 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3980 DWORD VertexCount,
3981 DWORD Flags)
3983 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
3984 WineDirect3DVertexStridedData WineD3DStrided;
3985 DWORD i;
3986 UINT PrimitiveCount;
3987 HRESULT hr;
3989 TRACE("(%p)->(%08x,%08x,%p,%08x,%08x): stub!\n", This, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3991 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3992 /* Get the strided data right. the wined3d structure is a bit bigger
3993 * Watch out: The contents of the strided data are determined by the fvf,
3994 * not by the members set in D3DDrawPrimStrideData. So it's valid
3995 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3996 * not set in the fvf.
3998 if(VertexType & D3DFVF_POSITION_MASK)
4000 WineD3DStrided.u.s.position.lpData = D3DDrawPrimStrideData->position.lpvData;
4001 WineD3DStrided.u.s.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
4002 WineD3DStrided.u.s.position.dwType = WINED3DDECLTYPE_FLOAT3;
4003 if (VertexType & D3DFVF_XYZRHW)
4005 WineD3DStrided.u.s.position.dwType = WINED3DDECLTYPE_FLOAT4;
4006 WineD3DStrided.position_transformed = TRUE;
4007 } else
4008 WineD3DStrided.position_transformed = FALSE;
4011 if(VertexType & D3DFVF_NORMAL)
4013 WineD3DStrided.u.s.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
4014 WineD3DStrided.u.s.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
4015 WineD3DStrided.u.s.normal.dwType = WINED3DDECLTYPE_FLOAT3;
4018 if(VertexType & D3DFVF_DIFFUSE)
4020 WineD3DStrided.u.s.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
4021 WineD3DStrided.u.s.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
4022 WineD3DStrided.u.s.diffuse.dwType = WINED3DDECLTYPE_D3DCOLOR;
4025 if(VertexType & D3DFVF_SPECULAR)
4027 WineD3DStrided.u.s.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
4028 WineD3DStrided.u.s.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
4029 WineD3DStrided.u.s.specular.dwType = WINED3DDECLTYPE_D3DCOLOR;
4032 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
4034 WineD3DStrided.u.s.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4035 WineD3DStrided.u.s.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4036 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
4038 case 1: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT1; break;
4039 case 2: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT2; break;
4040 case 3: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT3; break;
4041 case 4: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT4; break;
4042 default: ERR("Unexpected texture coordinate size %d\n",
4043 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4047 /* Get the primitive count */
4048 switch(PrimitiveType)
4050 case D3DPT_POINTLIST:
4051 PrimitiveCount = VertexCount;
4052 break;
4054 case D3DPT_LINELIST:
4055 PrimitiveCount = VertexCount / 2;
4056 break;
4058 case D3DPT_LINESTRIP:
4059 PrimitiveCount = VertexCount - 1;
4060 break;
4062 case D3DPT_TRIANGLELIST:
4063 PrimitiveCount = VertexCount / 3;
4064 break;
4066 case D3DPT_TRIANGLESTRIP:
4067 PrimitiveCount = VertexCount - 2;
4068 break;
4070 case D3DPT_TRIANGLEFAN:
4071 PrimitiveCount = VertexCount - 2;
4072 break;
4074 default: return DDERR_INVALIDPARAMS;
4077 /* WineD3D doesn't need the FVF here */
4078 EnterCriticalSection(&ddraw_cs);
4079 hr = IWineD3DDevice_DrawPrimitiveStrided(This->wineD3DDevice,
4080 PrimitiveType,
4081 PrimitiveCount,
4082 &WineD3DStrided);
4083 LeaveCriticalSection(&ddraw_cs);
4084 return hr;
4087 static HRESULT WINAPI
4088 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4089 D3DPRIMITIVETYPE PrimitiveType,
4090 DWORD VertexType,
4091 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4092 DWORD VertexCount,
4093 DWORD Flags)
4095 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4098 static HRESULT WINAPI
4099 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4100 D3DPRIMITIVETYPE PrimitiveType,
4101 DWORD VertexType,
4102 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4103 DWORD VertexCount,
4104 DWORD Flags)
4106 HRESULT hr;
4107 WORD old_fpucw;
4109 old_fpucw = d3d_fpu_setup();
4110 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4111 set_fpu_control_word(old_fpucw);
4113 return hr;
4116 static HRESULT WINAPI
4117 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
4118 D3DPRIMITIVETYPE PrimitiveType,
4119 DWORD VertexType,
4120 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4121 DWORD VertexCount,
4122 DWORD Flags)
4124 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4125 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4126 return IDirect3DDevice7_DrawPrimitiveStrided(ICOM_INTERFACE(This, IDirect3DDevice7),
4127 PrimitiveType,
4128 VertexType,
4129 D3DDrawPrimStrideData,
4130 VertexCount,
4131 Flags);
4134 /*****************************************************************************
4135 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
4137 * Draws primitives specified by strided data locations based on indices
4139 * Version 3 and 7
4141 * Params:
4142 * PrimitiveType:
4144 * Returns:
4145 * D3D_OK, because it's a stub
4146 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
4147 * (DDERR_INVALIDPARAMS if Indices is NULL)
4148 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
4150 *****************************************************************************/
4151 static HRESULT
4152 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
4153 D3DPRIMITIVETYPE PrimitiveType,
4154 DWORD VertexType,
4155 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4156 DWORD VertexCount,
4157 WORD *Indices,
4158 DWORD IndexCount,
4159 DWORD Flags)
4161 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4162 WineDirect3DVertexStridedData WineD3DStrided;
4163 DWORD i;
4164 UINT PrimitiveCount;
4165 HRESULT hr;
4167 TRACE("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x)\n", This, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4169 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
4170 /* Get the strided data right. the wined3d structure is a bit bigger
4171 * Watch out: The contents of the strided data are determined by the fvf,
4172 * not by the members set in D3DDrawPrimStrideData. So it's valid
4173 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
4174 * not set in the fvf.
4176 if(VertexType & D3DFVF_POSITION_MASK)
4178 WineD3DStrided.u.s.position.lpData = D3DDrawPrimStrideData->position.lpvData;
4179 WineD3DStrided.u.s.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
4180 WineD3DStrided.u.s.position.dwType = WINED3DDECLTYPE_FLOAT3;
4181 if (VertexType & D3DFVF_XYZRHW)
4183 WineD3DStrided.u.s.position.dwType = WINED3DDECLTYPE_FLOAT4;
4184 WineD3DStrided.position_transformed = TRUE;
4185 } else
4186 WineD3DStrided.position_transformed = FALSE;
4189 if(VertexType & D3DFVF_NORMAL)
4191 WineD3DStrided.u.s.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
4192 WineD3DStrided.u.s.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
4193 WineD3DStrided.u.s.normal.dwType = WINED3DDECLTYPE_FLOAT3;
4196 if(VertexType & D3DFVF_DIFFUSE)
4198 WineD3DStrided.u.s.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
4199 WineD3DStrided.u.s.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
4200 WineD3DStrided.u.s.diffuse.dwType = WINED3DDECLTYPE_D3DCOLOR;
4203 if(VertexType & D3DFVF_SPECULAR)
4205 WineD3DStrided.u.s.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
4206 WineD3DStrided.u.s.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
4207 WineD3DStrided.u.s.specular.dwType = WINED3DDECLTYPE_D3DCOLOR;
4210 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
4212 WineD3DStrided.u.s.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4213 WineD3DStrided.u.s.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4214 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
4216 case 1: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT1; break;
4217 case 2: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT2; break;
4218 case 3: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT3; break;
4219 case 4: WineD3DStrided.u.s.texCoords[i].dwType = WINED3DDECLTYPE_FLOAT4; break;
4220 default: ERR("Unexpected texture coordinate size %d\n",
4221 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4225 /* Get the primitive count */
4226 switch(PrimitiveType)
4228 case D3DPT_POINTLIST:
4229 PrimitiveCount = IndexCount;
4230 break;
4232 case D3DPT_LINELIST:
4233 PrimitiveCount = IndexCount / 2;
4234 break;
4236 case D3DPT_LINESTRIP:
4237 PrimitiveCount = IndexCount - 1;
4238 break;
4240 case D3DPT_TRIANGLELIST:
4241 PrimitiveCount = IndexCount / 3;
4242 break;
4244 case D3DPT_TRIANGLESTRIP:
4245 PrimitiveCount = IndexCount - 2;
4246 break;
4248 case D3DPT_TRIANGLEFAN:
4249 PrimitiveCount = IndexCount - 2;
4250 break;
4252 default: return DDERR_INVALIDPARAMS;
4255 /* WineD3D doesn't need the FVF here */
4256 EnterCriticalSection(&ddraw_cs);
4257 hr = IWineD3DDevice_DrawIndexedPrimitiveStrided(This->wineD3DDevice,
4258 PrimitiveType,
4259 PrimitiveCount,
4260 &WineD3DStrided,
4261 VertexCount,
4262 Indices,
4263 WINED3DFMT_INDEX16);
4264 LeaveCriticalSection(&ddraw_cs);
4265 return hr;
4268 static HRESULT WINAPI
4269 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4270 D3DPRIMITIVETYPE PrimitiveType,
4271 DWORD VertexType,
4272 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4273 DWORD VertexCount,
4274 WORD *Indices,
4275 DWORD IndexCount,
4276 DWORD Flags)
4278 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4281 static HRESULT WINAPI
4282 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4283 D3DPRIMITIVETYPE PrimitiveType,
4284 DWORD VertexType,
4285 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4286 DWORD VertexCount,
4287 WORD *Indices,
4288 DWORD IndexCount,
4289 DWORD Flags)
4291 HRESULT hr;
4292 WORD old_fpucw;
4294 old_fpucw = d3d_fpu_setup();
4295 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4296 set_fpu_control_word(old_fpucw);
4298 return hr;
4301 static HRESULT WINAPI
4302 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4303 D3DPRIMITIVETYPE PrimitiveType,
4304 DWORD VertexType,
4305 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4306 DWORD VertexCount,
4307 WORD *Indices,
4308 DWORD IndexCount,
4309 DWORD Flags)
4311 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4312 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4313 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(ICOM_INTERFACE(This, IDirect3DDevice7),
4314 PrimitiveType,
4315 VertexType,
4316 D3DDrawPrimStrideData,
4317 VertexCount,
4318 Indices,
4319 IndexCount,
4320 Flags);
4323 /*****************************************************************************
4324 * IDirect3DDevice7::DrawPrimitiveVB
4326 * Draws primitives from a vertex buffer to the screen.
4328 * Version 3 and 7
4330 * Params:
4331 * PrimitiveType: Type of primitive to be rendered.
4332 * D3DVertexBuf: Source Vertex Buffer
4333 * StartVertex: Index of the first vertex from the buffer to be rendered
4334 * NumVertices: Number of vertices to be rendered
4335 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4337 * Return values
4338 * D3D_OK on success
4339 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4341 *****************************************************************************/
4342 static HRESULT
4343 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4344 D3DPRIMITIVETYPE PrimitiveType,
4345 IDirect3DVertexBuffer7 *D3DVertexBuf,
4346 DWORD StartVertex,
4347 DWORD NumVertices,
4348 DWORD Flags)
4350 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4351 IDirect3DVertexBufferImpl *vb = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, D3DVertexBuf);
4352 UINT PrimitiveCount;
4353 HRESULT hr;
4354 DWORD stride;
4355 WINED3DVERTEXBUFFER_DESC Desc;
4357 TRACE("(%p)->(%08x,%p,%08x,%08x,%08x)\n", This, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4359 /* Sanity checks */
4360 if(!vb)
4362 ERR("(%p) No Vertex buffer specified\n", This);
4363 return DDERR_INVALIDPARAMS;
4366 /* Get the primitive count */
4367 switch(PrimitiveType)
4369 case D3DPT_POINTLIST:
4370 PrimitiveCount = NumVertices;
4371 break;
4373 case D3DPT_LINELIST:
4374 PrimitiveCount = NumVertices / 2;
4375 break;
4377 case D3DPT_LINESTRIP:
4378 PrimitiveCount = NumVertices - 1;
4379 break;
4381 case D3DPT_TRIANGLELIST:
4382 PrimitiveCount = NumVertices / 3;
4383 break;
4385 case D3DPT_TRIANGLESTRIP:
4386 PrimitiveCount = NumVertices - 2;
4387 break;
4389 case D3DPT_TRIANGLEFAN:
4390 PrimitiveCount = NumVertices - 2;
4391 break;
4393 default:
4394 return DDERR_INVALIDPARAMS;
4397 /* Get the FVF of the vertex buffer, and its stride */
4398 EnterCriticalSection(&ddraw_cs);
4399 hr = IWineD3DVertexBuffer_GetDesc(vb->wineD3DVertexBuffer,
4400 &Desc);
4401 if(hr != D3D_OK)
4403 ERR("(%p) IWineD3DVertexBuffer::GetDesc failed with hr = %08x\n", This, hr);
4404 LeaveCriticalSection(&ddraw_cs);
4405 return hr;
4407 stride = get_flexible_vertex_size(Desc.FVF);
4409 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4410 vb->wineD3DVertexDeclaration);
4411 if(FAILED(hr))
4413 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4414 LeaveCriticalSection(&ddraw_cs);
4415 return hr;
4418 /* Set the vertex stream source */
4419 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4420 0 /* StreamNumber */,
4421 vb->wineD3DVertexBuffer,
4422 0 /* StartVertex - we pass this to DrawPrimitive */,
4423 stride);
4424 if(hr != D3D_OK)
4426 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4427 LeaveCriticalSection(&ddraw_cs);
4428 return hr;
4431 /* Now draw the primitives */
4432 hr = IWineD3DDevice_DrawPrimitive(This->wineD3DDevice,
4433 PrimitiveType,
4434 StartVertex,
4435 PrimitiveCount);
4436 LeaveCriticalSection(&ddraw_cs);
4437 return hr;
4440 static HRESULT WINAPI
4441 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4442 D3DPRIMITIVETYPE PrimitiveType,
4443 IDirect3DVertexBuffer7 *D3DVertexBuf,
4444 DWORD StartVertex,
4445 DWORD NumVertices,
4446 DWORD Flags)
4448 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4451 static HRESULT WINAPI
4452 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4453 D3DPRIMITIVETYPE PrimitiveType,
4454 IDirect3DVertexBuffer7 *D3DVertexBuf,
4455 DWORD StartVertex,
4456 DWORD NumVertices,
4457 DWORD Flags)
4459 HRESULT hr;
4460 WORD old_fpucw;
4462 old_fpucw = d3d_fpu_setup();
4463 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4464 set_fpu_control_word(old_fpucw);
4466 return hr;
4469 static HRESULT WINAPI
4470 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4471 D3DPRIMITIVETYPE PrimitiveType,
4472 IDirect3DVertexBuffer *D3DVertexBuf,
4473 DWORD StartVertex,
4474 DWORD NumVertices,
4475 DWORD Flags)
4477 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4478 IDirect3DVertexBufferImpl *vb = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, D3DVertexBuf);
4479 TRACE_(ddraw_thunk)("(%p)->(%08x,%p,%08x,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, vb, StartVertex, NumVertices, Flags);
4480 return IDirect3DDevice7_DrawPrimitiveVB(ICOM_INTERFACE(This, IDirect3DDevice7),
4481 PrimitiveType,
4482 ICOM_INTERFACE(vb, IDirect3DVertexBuffer7),
4483 StartVertex,
4484 NumVertices,
4485 Flags);
4489 /*****************************************************************************
4490 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4492 * Draws primitives from a vertex buffer to the screen
4494 * Params:
4495 * PrimitiveType: Type of primitive to be rendered.
4496 * D3DVertexBuf: Source Vertex Buffer
4497 * StartVertex: Index of the first vertex from the buffer to be rendered
4498 * NumVertices: Number of vertices to be rendered
4499 * Indices: Array of DWORDs used to index into the Vertices
4500 * IndexCount: Number of indices in Indices
4501 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4503 * Return values
4505 *****************************************************************************/
4506 static HRESULT
4507 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4508 D3DPRIMITIVETYPE PrimitiveType,
4509 IDirect3DVertexBuffer7 *D3DVertexBuf,
4510 DWORD StartVertex,
4511 DWORD NumVertices,
4512 WORD *Indices,
4513 DWORD IndexCount,
4514 DWORD Flags)
4516 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4517 IDirect3DVertexBufferImpl *vb = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, D3DVertexBuf);
4518 DWORD stride;
4519 UINT PrimitiveCount;
4520 WORD *LockedIndices;
4521 HRESULT hr;
4522 WINED3DVERTEXBUFFER_DESC Desc;
4524 TRACE("(%p)->(%08x,%p,%d,%d,%p,%d,%08x)\n", This, PrimitiveType, vb, StartVertex, NumVertices, Indices, IndexCount, Flags);
4526 /* Steps:
4527 * 1) Calculate some things: Vertex count -> Primitive count, stride, ...
4528 * 2) Upload the Indices to the index buffer
4529 * 3) Set the index source
4530 * 4) Set the Vertex Buffer as the Stream source
4531 * 5) Call IWineD3DDevice::DrawIndexedPrimitive
4534 /* Get the primitive count */
4535 switch(PrimitiveType)
4537 case D3DPT_POINTLIST:
4538 PrimitiveCount = IndexCount;
4539 break;
4541 case D3DPT_LINELIST:
4542 PrimitiveCount = IndexCount / 2;
4543 break;
4545 case D3DPT_LINESTRIP:
4546 PrimitiveCount = IndexCount - 1;
4547 break;
4549 case D3DPT_TRIANGLELIST:
4550 PrimitiveCount = IndexCount / 3;
4551 break;
4553 case D3DPT_TRIANGLESTRIP:
4554 PrimitiveCount = IndexCount - 2;
4555 break;
4557 case D3DPT_TRIANGLEFAN:
4558 PrimitiveCount = IndexCount - 2;
4559 break;
4561 default: return DDERR_INVALIDPARAMS;
4564 EnterCriticalSection(&ddraw_cs);
4565 /* Get the FVF of the vertex buffer, and its stride */
4566 hr = IWineD3DVertexBuffer_GetDesc(vb->wineD3DVertexBuffer,
4567 &Desc);
4568 if(hr != D3D_OK)
4570 ERR("(%p) IWineD3DVertexBuffer::GetDesc failed with hr = %08x\n", This, hr);
4571 LeaveCriticalSection(&ddraw_cs);
4572 return hr;
4574 stride = get_flexible_vertex_size(Desc.FVF);
4575 TRACE("Vertex buffer FVF = %08x, stride=%d\n", Desc.FVF, stride);
4577 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4578 vb->wineD3DVertexDeclaration);
4579 if(FAILED(hr))
4581 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4582 LeaveCriticalSection(&ddraw_cs);
4583 return hr;
4586 /* copy the index stream into the index buffer.
4587 * A new IWineD3DDevice method could be created
4588 * which takes an user pointer containing the indices
4589 * or a SetData-Method for the index buffer, which
4590 * overrides the index buffer data with our pointer.
4592 hr = IWineD3DIndexBuffer_Lock(This->indexbuffer,
4593 0 /* OffSetToLock */,
4594 IndexCount * sizeof(WORD),
4595 (BYTE **) &LockedIndices,
4596 0 /* Flags */);
4597 assert(IndexCount < 0x100000);
4598 if(hr != D3D_OK)
4600 ERR("(%p) IWineD3DIndexBuffer::Lock failed with hr = %08x\n", This, hr);
4601 LeaveCriticalSection(&ddraw_cs);
4602 return hr;
4604 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4605 hr = IWineD3DIndexBuffer_Unlock(This->indexbuffer);
4606 if(hr != D3D_OK)
4608 ERR("(%p) IWineD3DIndexBuffer::Unlock failed with hr = %08x\n", This, hr);
4609 LeaveCriticalSection(&ddraw_cs);
4610 return hr;
4613 /* Set the index stream */
4614 IWineD3DDevice_SetBaseVertexIndex(This->wineD3DDevice, StartVertex);
4615 hr = IWineD3DDevice_SetIndices(This->wineD3DDevice, This->indexbuffer);
4617 /* Set the vertex stream source */
4618 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4619 0 /* StreamNumber */,
4620 vb->wineD3DVertexBuffer,
4621 0 /* offset, we pass this to DrawIndexedPrimitive */,
4622 stride);
4623 if(hr != D3D_OK)
4625 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4626 LeaveCriticalSection(&ddraw_cs);
4627 return hr;
4631 hr = IWineD3DDevice_DrawIndexedPrimitive(This->wineD3DDevice,
4632 PrimitiveType,
4633 0 /* minIndex */,
4634 NumVertices,
4635 0 /* StartIndex */,
4636 PrimitiveCount);
4638 LeaveCriticalSection(&ddraw_cs);
4639 return hr;
4642 static HRESULT WINAPI
4643 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4644 D3DPRIMITIVETYPE PrimitiveType,
4645 IDirect3DVertexBuffer7 *D3DVertexBuf,
4646 DWORD StartVertex,
4647 DWORD NumVertices,
4648 WORD *Indices,
4649 DWORD IndexCount,
4650 DWORD Flags)
4652 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4655 static HRESULT WINAPI
4656 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4657 D3DPRIMITIVETYPE PrimitiveType,
4658 IDirect3DVertexBuffer7 *D3DVertexBuf,
4659 DWORD StartVertex,
4660 DWORD NumVertices,
4661 WORD *Indices,
4662 DWORD IndexCount,
4663 DWORD Flags)
4665 HRESULT hr;
4666 WORD old_fpucw;
4668 old_fpucw = d3d_fpu_setup();
4669 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4670 set_fpu_control_word(old_fpucw);
4672 return hr;
4675 static HRESULT WINAPI
4676 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4677 D3DPRIMITIVETYPE PrimitiveType,
4678 IDirect3DVertexBuffer *D3DVertexBuf,
4679 WORD *Indices,
4680 DWORD IndexCount,
4681 DWORD Flags)
4683 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4684 IDirect3DVertexBufferImpl *VB = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, D3DVertexBuf);
4685 TRACE_(ddraw_thunk)("(%p)->(%08x,%p,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VB, Indices, IndexCount, Flags);
4687 return IDirect3DDevice7_DrawIndexedPrimitiveVB(ICOM_INTERFACE(This, IDirect3DDevice7),
4688 PrimitiveType,
4689 ICOM_INTERFACE(VB, IDirect3DVertexBuffer7),
4691 IndexCount,
4692 Indices,
4693 IndexCount,
4694 Flags);
4697 /*****************************************************************************
4698 * IDirect3DDevice7::ComputeSphereVisibility
4700 * Calculates the visibility of spheres in the current viewport. The spheres
4701 * are passed in the Centers and Radii arrays, the results are passed back
4702 * in the ReturnValues array. Return values are either completely visible,
4703 * partially visible or completely invisible.
4704 * The return value consist of a combination of D3DCLIP_* flags, or it's
4705 * 0 if the sphere is completely visible(according to the SDK, not checked)
4707 * Sounds like an overdose of math ;)
4709 * Version 3 and 7
4711 * Params:
4712 * Centers: Array containing the sphere centers
4713 * Radii: Array containing the sphere radii
4714 * NumSpheres: The number of centers and radii in the arrays
4715 * Flags: Some flags
4716 * ReturnValues: Array to write the results to
4718 * Returns:
4719 * D3D_OK because it's a stub
4720 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4721 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4722 * is singular)
4724 *****************************************************************************/
4725 static HRESULT WINAPI
4726 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4727 D3DVECTOR *Centers,
4728 D3DVALUE *Radii,
4729 DWORD NumSpheres,
4730 DWORD Flags,
4731 DWORD *ReturnValues)
4733 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4734 FIXME("(%p)->(%p,%p,%08x,%08x,%p): stub!\n", This, Centers, Radii, NumSpheres, Flags, ReturnValues);
4736 /* the DirectX 7 sdk says that the visibility is computed by
4737 * back-transforming the viewing frustum to model space
4738 * using the inverse of the combined world, view and projection
4739 * matrix. If the matrix can't be reversed, D3DERR_INVALIDMATRIX
4740 * is returned.
4742 * Basic implementation idea:
4743 * 1) Check if the center is in the viewing frustum
4744 * 2) Cut the sphere with the planes of the viewing
4745 * frustum
4747 * ->Center inside the frustum, no intersections:
4748 * Fully visible
4749 * ->Center outside the frustum, no intersections:
4750 * Not visible
4751 * ->Some intersections: Partially visible
4753 * Implement this call in WineD3D. Either implement the
4754 * matrix and vector stuff in WineD3D, or use some external
4755 * math library.
4758 return D3D_OK;
4761 static HRESULT WINAPI
4762 Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4763 D3DVECTOR *Centers,
4764 D3DVALUE *Radii,
4765 DWORD NumSpheres,
4766 DWORD Flags,
4767 DWORD *ReturnValues)
4769 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4770 TRACE_(ddraw_thunk)("(%p)->(%p,%p,%08x,%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, Centers, Radii, NumSpheres, Flags, ReturnValues);
4771 return IDirect3DDevice7_ComputeSphereVisibility(ICOM_INTERFACE(This, IDirect3DDevice7),
4772 Centers,
4773 Radii,
4774 NumSpheres,
4775 Flags,
4776 ReturnValues);
4779 /*****************************************************************************
4780 * IDirect3DDevice7::GetTexture
4782 * Returns the texture interface handle assigned to a texture stage.
4783 * The returned texture is AddRefed. This is taken from old ddraw,
4784 * not checked in Windows.
4786 * Version 3 and 7
4788 * Params:
4789 * Stage: Texture stage to read the texture from
4790 * Texture: Address to store the interface pointer at
4792 * Returns:
4793 * D3D_OK on success
4794 * DDERR_INVALIDPARAMS if Texture is NULL
4795 * For details, see IWineD3DDevice::GetTexture
4797 *****************************************************************************/
4798 static HRESULT
4799 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4800 DWORD Stage,
4801 IDirectDrawSurface7 **Texture)
4803 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4804 IWineD3DBaseTexture *Surf;
4805 HRESULT hr;
4806 TRACE("(%p)->(%d,%p): Relay\n", This, Stage, Texture);
4808 if(!Texture)
4810 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4811 return DDERR_INVALIDPARAMS;
4814 EnterCriticalSection(&ddraw_cs);
4815 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, Stage, &Surf);
4816 if( (hr != D3D_OK) || (!Surf) )
4818 *Texture = NULL;
4819 LeaveCriticalSection(&ddraw_cs);
4820 return hr;
4823 /* GetParent AddRef()s, which is perfectly OK.
4824 * We have passed the IDirectDrawSurface7 interface to WineD3D, so that's OK too.
4826 hr = IWineD3DBaseTexture_GetParent(Surf,
4827 (IUnknown **) Texture);
4828 LeaveCriticalSection(&ddraw_cs);
4829 return hr;
4832 static HRESULT WINAPI
4833 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4834 DWORD Stage,
4835 IDirectDrawSurface7 **Texture)
4837 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4840 static HRESULT WINAPI
4841 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4842 DWORD Stage,
4843 IDirectDrawSurface7 **Texture)
4845 HRESULT hr;
4846 WORD old_fpucw;
4848 old_fpucw = d3d_fpu_setup();
4849 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4850 set_fpu_control_word(old_fpucw);
4852 return hr;
4855 static HRESULT WINAPI
4856 Thunk_IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface,
4857 DWORD Stage,
4858 IDirect3DTexture2 **Texture2)
4860 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4861 HRESULT ret;
4862 IDirectDrawSurface7 *ret_val;
4864 TRACE_(ddraw_thunk)("(%p)->(%d,%p) thunking to IDirect3DDevice7 interface.\n", This, Stage, Texture2);
4865 ret = IDirect3DDevice7_GetTexture(ICOM_INTERFACE(This, IDirect3DDevice7),
4866 Stage,
4867 &ret_val);
4869 *Texture2 = COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirectDrawSurface7, IDirect3DTexture2, ret_val);
4871 TRACE_(ddraw_thunk)(" returning interface %p.\n", *Texture2);
4873 return ret;
4876 /*****************************************************************************
4877 * IDirect3DDevice7::SetTexture
4879 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4881 * Version 3 and 7
4883 * Params:
4884 * Stage: The stage to assign the texture to
4885 * Texture: Interface pointer to the texture surface
4887 * Returns
4888 * D3D_OK on success
4889 * For details, see IWineD3DDevice::SetTexture
4891 *****************************************************************************/
4892 static HRESULT
4893 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4894 DWORD Stage,
4895 IDirectDrawSurface7 *Texture)
4897 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
4898 IDirectDrawSurfaceImpl *surf = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, Texture);
4899 HRESULT hr;
4900 TRACE("(%p)->(%08x,%p): Relay!\n", This, Stage, surf);
4902 /* Texture may be NULL here */
4903 EnterCriticalSection(&ddraw_cs);
4904 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
4905 Stage,
4906 surf ? surf->wineD3DTexture : NULL);
4907 LeaveCriticalSection(&ddraw_cs);
4908 return hr;
4911 static HRESULT WINAPI
4912 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4913 DWORD Stage,
4914 IDirectDrawSurface7 *Texture)
4916 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4919 static HRESULT WINAPI
4920 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4921 DWORD Stage,
4922 IDirectDrawSurface7 *Texture)
4924 HRESULT hr;
4925 WORD old_fpucw;
4927 old_fpucw = d3d_fpu_setup();
4928 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4929 set_fpu_control_word(old_fpucw);
4931 return hr;
4934 static HRESULT WINAPI
4935 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4936 DWORD Stage,
4937 IDirect3DTexture2 *Texture2)
4939 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
4940 IDirectDrawSurfaceImpl *tex = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture2, Texture2);
4941 DWORD texmapblend;
4942 HRESULT hr;
4943 TRACE("(%p)->(%d,%p)\n", This, Stage, tex);
4945 EnterCriticalSection(&ddraw_cs);
4947 if (This->legacyTextureBlending)
4948 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4950 hr = IDirect3DDevice7_SetTexture(ICOM_INTERFACE(This, IDirect3DDevice7),
4951 Stage,
4952 ICOM_INTERFACE(tex, IDirectDrawSurface7));
4954 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4956 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4957 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4958 BOOL tex_alpha = FALSE;
4959 IWineD3DBaseTexture *tex = NULL;
4960 WINED3DSURFACE_DESC desc;
4961 WINED3DFORMAT fmt;
4962 DDPIXELFORMAT ddfmt;
4963 HRESULT result;
4965 result = IWineD3DDevice_GetTexture(This->wineD3DDevice,
4967 &tex);
4969 if(result == WINED3D_OK && tex)
4971 memset(&desc, 0, sizeof(desc));
4972 desc.Format = &fmt;
4973 result = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
4974 if (SUCCEEDED(result))
4976 ddfmt.dwSize = sizeof(ddfmt);
4977 PixelFormat_WineD3DtoDD(&ddfmt, fmt);
4978 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4981 IWineD3DBaseTexture_Release(tex);
4984 /* alphaop is WINED3DTOP_SELECTARG1 if it's D3DTBLEND_MODULATE, so only modify alphaarg1 */
4985 if (tex_alpha)
4987 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
4989 else
4991 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_CURRENT);
4995 LeaveCriticalSection(&ddraw_cs);
4997 return hr;
5000 static const struct tss_lookup
5002 BOOL sampler_state;
5003 DWORD state;
5005 tss_lookup[] =
5007 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
5008 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
5009 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
5010 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
5011 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
5012 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
5013 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
5014 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
5015 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
5016 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
5017 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
5018 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
5019 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
5020 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
5021 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
5022 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
5023 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
5024 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
5025 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
5026 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
5027 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
5028 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
5029 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
5030 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
5031 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
5034 /*****************************************************************************
5035 * IDirect3DDevice7::GetTextureStageState
5037 * Retrieves a state from a texture stage.
5039 * Version 3 and 7
5041 * Params:
5042 * Stage: The stage to retrieve the state from
5043 * TexStageStateType: The state type to retrieve
5044 * State: Address to store the state's value at
5046 * Returns:
5047 * D3D_OK on success
5048 * DDERR_INVALIDPARAMS if State is NULL
5049 * For details, see IWineD3DDevice::GetTextureStageState
5051 *****************************************************************************/
5052 static HRESULT
5053 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
5054 DWORD Stage,
5055 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5056 DWORD *State)
5058 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5059 HRESULT hr;
5060 const struct tss_lookup *l = &tss_lookup[TexStageStateType];
5061 TRACE("(%p)->(%08x,%08x,%p): Relay!\n", This, Stage, TexStageStateType, State);
5063 if(!State)
5064 return DDERR_INVALIDPARAMS;
5066 EnterCriticalSection(&ddraw_cs);
5068 if (l->sampler_state)
5070 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice, Stage, l->state, State);
5072 switch(TexStageStateType)
5074 /* Mipfilter is a sampler state with different values */
5075 case D3DTSS_MIPFILTER:
5077 switch(*State)
5079 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
5080 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
5081 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
5082 default:
5083 ERR("Unexpected mipfilter value %#x\n", *State);
5084 *State = D3DTFP_NONE;
5085 break;
5087 break;
5090 /* Magfilter has slightly different values */
5091 case D3DTSS_MAGFILTER:
5093 switch(*State)
5095 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
5096 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
5097 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
5098 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
5099 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
5100 default:
5101 ERR("Unexpected wined3d mag filter value %#x\n", *State);
5102 *State = D3DTFG_POINT;
5103 break;
5105 break;
5108 default:
5109 break;
5112 else
5114 hr = IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
5117 LeaveCriticalSection(&ddraw_cs);
5118 return hr;
5121 static HRESULT WINAPI
5122 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5123 DWORD Stage,
5124 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5125 DWORD *State)
5127 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
5130 static HRESULT WINAPI
5131 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5132 DWORD Stage,
5133 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5134 DWORD *State)
5136 HRESULT hr;
5137 WORD old_fpucw;
5139 old_fpucw = d3d_fpu_setup();
5140 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
5141 set_fpu_control_word(old_fpucw);
5143 return hr;
5146 static HRESULT WINAPI
5147 Thunk_IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
5148 DWORD Stage,
5149 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5150 DWORD *State)
5152 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
5153 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, Stage, TexStageStateType, State);
5154 return IDirect3DDevice7_GetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
5155 Stage,
5156 TexStageStateType,
5157 State);
5160 /*****************************************************************************
5161 * IDirect3DDevice7::SetTextureStageState
5163 * Sets a texture stage state. Some stage types need to be handled specially,
5164 * because they do not exist in WineD3D and were moved to another place
5166 * Version 3 and 7
5168 * Params:
5169 * Stage: The stage to modify
5170 * TexStageStateType: The state to change
5171 * State: The new value for the state
5173 * Returns:
5174 * D3D_OK on success
5175 * For details, see IWineD3DDevice::SetTextureStageState
5177 *****************************************************************************/
5178 static HRESULT
5179 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
5180 DWORD Stage,
5181 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5182 DWORD State)
5184 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5185 const struct tss_lookup *l = &tss_lookup[TexStageStateType];
5186 HRESULT hr;
5187 TRACE("(%p)->(%08x,%08x,%08x): Relay!\n", This, Stage, TexStageStateType, State);
5189 EnterCriticalSection(&ddraw_cs);
5191 if (l->sampler_state)
5193 switch(TexStageStateType)
5195 /* Mipfilter is a sampler state with different values */
5196 case D3DTSS_MIPFILTER:
5198 switch(State)
5200 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
5201 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
5202 case 0: /* Unchecked */
5203 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
5204 default:
5205 ERR("Unexpected mipfilter value %d\n", State);
5206 State = WINED3DTEXF_NONE;
5207 break;
5209 break;
5212 /* Magfilter has slightly different values */
5213 case D3DTSS_MAGFILTER:
5215 switch(State)
5217 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
5218 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
5219 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
5220 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
5221 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
5222 default:
5223 ERR("Unexpected d3d7 mag filter type %d\n", State);
5224 State = WINED3DTEXF_POINT;
5225 break;
5227 break;
5230 case D3DTSS_ADDRESS:
5231 IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, WINED3DSAMP_ADDRESSV, State);
5232 break;
5234 default:
5235 break;
5238 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, l->state, State);
5240 else
5242 hr = IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
5245 LeaveCriticalSection(&ddraw_cs);
5246 return hr;
5249 static HRESULT WINAPI
5250 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5251 DWORD Stage,
5252 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5253 DWORD State)
5255 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5258 static HRESULT WINAPI
5259 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5260 DWORD Stage,
5261 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5262 DWORD State)
5264 HRESULT hr;
5265 WORD old_fpucw;
5267 old_fpucw = d3d_fpu_setup();
5268 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5269 set_fpu_control_word(old_fpucw);
5271 return hr;
5274 static HRESULT WINAPI
5275 Thunk_IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
5276 DWORD Stage,
5277 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5278 DWORD State)
5280 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
5281 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, Stage, TexStageStateType, State);
5282 return IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
5283 Stage,
5284 TexStageStateType,
5285 State);
5288 /*****************************************************************************
5289 * IDirect3DDevice7::ValidateDevice
5291 * SDK: "Reports the device's ability to render the currently set
5292 * texture-blending operations in a single pass". Whatever that means
5293 * exactly...
5295 * Version 3 and 7
5297 * Params:
5298 * NumPasses: Address to write the number of necessary passes for the
5299 * desired effect to.
5301 * Returns:
5302 * D3D_OK on success
5303 * See IWineD3DDevice::ValidateDevice for more details
5305 *****************************************************************************/
5306 static HRESULT
5307 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
5308 DWORD *NumPasses)
5310 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5311 HRESULT hr;
5312 TRACE("(%p)->(%p): Relay\n", This, NumPasses);
5314 EnterCriticalSection(&ddraw_cs);
5315 hr = IWineD3DDevice_ValidateDevice(This->wineD3DDevice, NumPasses);
5316 LeaveCriticalSection(&ddraw_cs);
5317 return hr;
5320 static HRESULT WINAPI
5321 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
5322 DWORD *NumPasses)
5324 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5327 static HRESULT WINAPI
5328 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
5329 DWORD *NumPasses)
5331 HRESULT hr;
5332 WORD old_fpucw;
5334 old_fpucw = d3d_fpu_setup();
5335 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5336 set_fpu_control_word(old_fpucw);
5338 return hr;
5341 static HRESULT WINAPI
5342 Thunk_IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface,
5343 DWORD *Passes)
5345 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
5346 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Passes);
5347 return IDirect3DDevice7_ValidateDevice(ICOM_INTERFACE(This, IDirect3DDevice7),
5348 Passes);
5351 /*****************************************************************************
5352 * IDirect3DDevice7::Clear
5354 * Fills the render target, the z buffer and the stencil buffer with a
5355 * clear color / value
5357 * Version 7 only
5359 * Params:
5360 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5361 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5362 * Flags: Some flags, as usual
5363 * Color: Clear color for the render target
5364 * Z: Clear value for the Z buffer
5365 * Stencil: Clear value to store in each stencil buffer entry
5367 * Returns:
5368 * D3D_OK on success
5369 * For details, see IWineD3DDevice::Clear
5371 *****************************************************************************/
5372 static HRESULT
5373 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
5374 DWORD Count,
5375 D3DRECT *Rects,
5376 DWORD Flags,
5377 D3DCOLOR Color,
5378 D3DVALUE Z,
5379 DWORD Stencil)
5381 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5382 HRESULT hr;
5383 TRACE("(%p)->(%08x,%p,%08x,%08x,%f,%08x): Relay\n", This, Count, Rects, Flags, Color, Z, Stencil);
5385 /* Note; D3DRECT is compatible with WINED3DRECT */
5386 EnterCriticalSection(&ddraw_cs);
5387 hr = IWineD3DDevice_Clear(This->wineD3DDevice, Count, (WINED3DRECT*) Rects, Flags, Color, Z, Stencil);
5388 LeaveCriticalSection(&ddraw_cs);
5389 return hr;
5392 static HRESULT WINAPI
5393 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5394 DWORD Count,
5395 D3DRECT *Rects,
5396 DWORD Flags,
5397 D3DCOLOR Color,
5398 D3DVALUE Z,
5399 DWORD Stencil)
5401 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5404 static HRESULT WINAPI
5405 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5406 DWORD Count,
5407 D3DRECT *Rects,
5408 DWORD Flags,
5409 D3DCOLOR Color,
5410 D3DVALUE Z,
5411 DWORD Stencil)
5413 HRESULT hr;
5414 WORD old_fpucw;
5416 old_fpucw = d3d_fpu_setup();
5417 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5418 set_fpu_control_word(old_fpucw);
5420 return hr;
5423 /*****************************************************************************
5424 * IDirect3DDevice7::SetViewport
5426 * Sets the current viewport.
5428 * Version 7 only, but IDirect3DViewport uses this call for older
5429 * versions
5431 * Params:
5432 * Data: The new viewport to set
5434 * Returns:
5435 * D3D_OK on success
5436 * DDERR_INVALIDPARAMS if Data is NULL
5437 * For more details, see IWineDDDevice::SetViewport
5439 *****************************************************************************/
5440 static HRESULT
5441 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5442 D3DVIEWPORT7 *Data)
5444 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5445 HRESULT hr;
5446 TRACE("(%p)->(%p) Relay!\n", This, Data);
5448 if(!Data)
5449 return DDERR_INVALIDPARAMS;
5451 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5452 EnterCriticalSection(&ddraw_cs);
5453 hr = IWineD3DDevice_SetViewport(This->wineD3DDevice,
5454 (WINED3DVIEWPORT*) Data);
5455 LeaveCriticalSection(&ddraw_cs);
5456 return hr;
5459 static HRESULT WINAPI
5460 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5461 D3DVIEWPORT7 *Data)
5463 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5466 static HRESULT WINAPI
5467 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5468 D3DVIEWPORT7 *Data)
5470 HRESULT hr;
5471 WORD old_fpucw;
5473 old_fpucw = d3d_fpu_setup();
5474 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5475 set_fpu_control_word(old_fpucw);
5477 return hr;
5480 /*****************************************************************************
5481 * IDirect3DDevice::GetViewport
5483 * Returns the current viewport
5485 * Version 7
5487 * Params:
5488 * Data: D3D7Viewport structure to write the viewport information to
5490 * Returns:
5491 * D3D_OK on success
5492 * DDERR_INVALIDPARAMS if Data is NULL
5493 * For more details, see IWineD3DDevice::GetViewport
5495 *****************************************************************************/
5496 static HRESULT
5497 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5498 D3DVIEWPORT7 *Data)
5500 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5501 HRESULT hr;
5502 TRACE("(%p)->(%p) Relay!\n", This, Data);
5504 if(!Data)
5505 return DDERR_INVALIDPARAMS;
5507 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5508 EnterCriticalSection(&ddraw_cs);
5509 hr = IWineD3DDevice_GetViewport(This->wineD3DDevice,
5510 (WINED3DVIEWPORT*) Data);
5512 LeaveCriticalSection(&ddraw_cs);
5513 return hr_ddraw_from_wined3d(hr);
5516 static HRESULT WINAPI
5517 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5518 D3DVIEWPORT7 *Data)
5520 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5523 static HRESULT WINAPI
5524 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5525 D3DVIEWPORT7 *Data)
5527 HRESULT hr;
5528 WORD old_fpucw;
5530 old_fpucw = d3d_fpu_setup();
5531 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5532 set_fpu_control_word(old_fpucw);
5534 return hr;
5537 /*****************************************************************************
5538 * IDirect3DDevice7::SetMaterial
5540 * Sets the Material
5542 * Version 7
5544 * Params:
5545 * Mat: The material to set
5547 * Returns:
5548 * D3D_OK on success
5549 * DDERR_INVALIDPARAMS if Mat is NULL.
5550 * For more details, see IWineD3DDevice::SetMaterial
5552 *****************************************************************************/
5553 static HRESULT
5554 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5555 D3DMATERIAL7 *Mat)
5557 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5558 HRESULT hr;
5559 TRACE("(%p)->(%p): Relay!\n", This, Mat);
5561 if (!Mat) return DDERR_INVALIDPARAMS;
5562 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5563 EnterCriticalSection(&ddraw_cs);
5564 hr = IWineD3DDevice_SetMaterial(This->wineD3DDevice,
5565 (WINED3DMATERIAL*) Mat);
5566 LeaveCriticalSection(&ddraw_cs);
5567 return hr_ddraw_from_wined3d(hr);
5570 static HRESULT WINAPI
5571 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5572 D3DMATERIAL7 *Mat)
5574 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5577 static HRESULT WINAPI
5578 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5579 D3DMATERIAL7 *Mat)
5581 HRESULT hr;
5582 WORD old_fpucw;
5584 old_fpucw = d3d_fpu_setup();
5585 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5586 set_fpu_control_word(old_fpucw);
5588 return hr;
5591 /*****************************************************************************
5592 * IDirect3DDevice7::GetMaterial
5594 * Returns the current material
5596 * Version 7
5598 * Params:
5599 * Mat: D3DMATERIAL7 structure to write the material parameters to
5601 * Returns:
5602 * D3D_OK on success
5603 * DDERR_INVALIDPARAMS if Mat is NULL
5604 * For more details, see IWineD3DDevice::GetMaterial
5606 *****************************************************************************/
5607 static HRESULT
5608 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5609 D3DMATERIAL7 *Mat)
5611 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5612 HRESULT hr;
5613 TRACE("(%p)->(%p): Relay!\n", This, Mat);
5615 EnterCriticalSection(&ddraw_cs);
5616 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5617 hr = IWineD3DDevice_GetMaterial(This->wineD3DDevice,
5618 (WINED3DMATERIAL*) Mat);
5619 LeaveCriticalSection(&ddraw_cs);
5620 return hr_ddraw_from_wined3d(hr);
5623 static HRESULT WINAPI
5624 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5625 D3DMATERIAL7 *Mat)
5627 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5630 static HRESULT WINAPI
5631 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5632 D3DMATERIAL7 *Mat)
5634 HRESULT hr;
5635 WORD old_fpucw;
5637 old_fpucw = d3d_fpu_setup();
5638 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5639 set_fpu_control_word(old_fpucw);
5641 return hr;
5644 /*****************************************************************************
5645 * IDirect3DDevice7::SetLight
5647 * Assigns a light to a light index, but doesn't activate it yet.
5649 * Version 7, IDirect3DLight uses this method for older versions
5651 * Params:
5652 * LightIndex: The index of the new light
5653 * Light: A D3DLIGHT7 structure describing the light
5655 * Returns:
5656 * D3D_OK on success
5657 * For more details, see IWineD3DDevice::SetLight
5659 *****************************************************************************/
5660 static HRESULT
5661 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5662 DWORD LightIndex,
5663 D3DLIGHT7 *Light)
5665 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5666 HRESULT hr;
5667 TRACE("(%p)->(%08x,%p): Relay!\n", This, LightIndex, Light);
5669 EnterCriticalSection(&ddraw_cs);
5670 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5671 hr = IWineD3DDevice_SetLight(This->wineD3DDevice,
5672 LightIndex,
5673 (WINED3DLIGHT*) Light);
5674 LeaveCriticalSection(&ddraw_cs);
5675 return hr_ddraw_from_wined3d(hr);
5678 static HRESULT WINAPI
5679 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5680 DWORD LightIndex,
5681 D3DLIGHT7 *Light)
5683 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5686 static HRESULT WINAPI
5687 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5688 DWORD LightIndex,
5689 D3DLIGHT7 *Light)
5691 HRESULT hr;
5692 WORD old_fpucw;
5694 old_fpucw = d3d_fpu_setup();
5695 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5696 set_fpu_control_word(old_fpucw);
5698 return hr;
5701 /*****************************************************************************
5702 * IDirect3DDevice7::GetLight
5704 * Returns the light assigned to a light index
5706 * Params:
5707 * Light: Structure to write the light information to
5709 * Returns:
5710 * D3D_OK on success
5711 * DDERR_INVALIDPARAMS if Light is NULL
5712 * For details, see IWineD3DDevice::GetLight
5714 *****************************************************************************/
5715 static HRESULT
5716 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5717 DWORD LightIndex,
5718 D3DLIGHT7 *Light)
5720 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5721 HRESULT rc;
5722 TRACE("(%p)->(%08x,%p): Relay!\n", This, LightIndex, Light);
5724 EnterCriticalSection(&ddraw_cs);
5725 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5726 rc = IWineD3DDevice_GetLight(This->wineD3DDevice,
5727 LightIndex,
5728 (WINED3DLIGHT*) Light);
5730 /* Translate the result. WineD3D returns other values than D3D7 */
5731 LeaveCriticalSection(&ddraw_cs);
5732 return hr_ddraw_from_wined3d(rc);
5735 static HRESULT WINAPI
5736 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5737 DWORD LightIndex,
5738 D3DLIGHT7 *Light)
5740 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5743 static HRESULT WINAPI
5744 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5745 DWORD LightIndex,
5746 D3DLIGHT7 *Light)
5748 HRESULT hr;
5749 WORD old_fpucw;
5751 old_fpucw = d3d_fpu_setup();
5752 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5753 set_fpu_control_word(old_fpucw);
5755 return hr;
5758 /*****************************************************************************
5759 * IDirect3DDevice7::BeginStateBlock
5761 * Begins recording to a stateblock
5763 * Version 7
5765 * Returns:
5766 * D3D_OK on success
5767 * For details see IWineD3DDevice::BeginStateBlock
5769 *****************************************************************************/
5770 static HRESULT
5771 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5773 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5774 HRESULT hr;
5775 TRACE("(%p)->(): Relay!\n", This);
5777 EnterCriticalSection(&ddraw_cs);
5778 hr = IWineD3DDevice_BeginStateBlock(This->wineD3DDevice);
5779 LeaveCriticalSection(&ddraw_cs);
5780 return hr_ddraw_from_wined3d(hr);
5783 static HRESULT WINAPI
5784 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5786 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5789 static HRESULT WINAPI
5790 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5792 HRESULT hr;
5793 WORD old_fpucw;
5795 old_fpucw = d3d_fpu_setup();
5796 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5797 set_fpu_control_word(old_fpucw);
5799 return hr;
5802 /*****************************************************************************
5803 * IDirect3DDevice7::EndStateBlock
5805 * Stops recording to a state block and returns the created stateblock
5806 * handle.
5808 * Version 7
5810 * Params:
5811 * BlockHandle: Address to store the stateblock's handle to
5813 * Returns:
5814 * D3D_OK on success
5815 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5816 * See IWineD3DDevice::EndStateBlock for more details
5818 *****************************************************************************/
5819 static HRESULT
5820 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5821 DWORD *BlockHandle)
5823 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5824 HRESULT hr;
5825 TRACE("(%p)->(%p): Relay!\n", This, BlockHandle);
5827 if(!BlockHandle)
5829 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5830 return DDERR_INVALIDPARAMS;
5833 EnterCriticalSection(&ddraw_cs);
5834 *BlockHandle = IDirect3DDeviceImpl_CreateHandle(This);
5835 if(!*BlockHandle)
5837 ERR("Cannot get a handle number for the stateblock\n");
5838 LeaveCriticalSection(&ddraw_cs);
5839 return DDERR_OUTOFMEMORY;
5841 This->Handles[*BlockHandle - 1].type = DDrawHandle_StateBlock;
5842 hr = IWineD3DDevice_EndStateBlock(This->wineD3DDevice,
5843 (IWineD3DStateBlock **) &This->Handles[*BlockHandle - 1].ptr);
5844 LeaveCriticalSection(&ddraw_cs);
5845 return hr_ddraw_from_wined3d(hr);
5848 static HRESULT WINAPI
5849 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5850 DWORD *BlockHandle)
5852 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5855 static HRESULT WINAPI
5856 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5857 DWORD *BlockHandle)
5859 HRESULT hr;
5860 WORD old_fpucw;
5862 old_fpucw = d3d_fpu_setup();
5863 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5864 set_fpu_control_word(old_fpucw);
5866 return hr;
5869 /*****************************************************************************
5870 * IDirect3DDevice7::PreLoad
5872 * Allows the app to signal that a texture will be used soon, to allow
5873 * the Direct3DDevice to load it to the video card in the meantime.
5875 * Version 7
5877 * Params:
5878 * Texture: The texture to preload
5880 * Returns:
5881 * D3D_OK on success
5882 * DDERR_INVALIDPARAMS if Texture is NULL
5883 * See IWineD3DSurface::PreLoad for details
5885 *****************************************************************************/
5886 static HRESULT
5887 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5888 IDirectDrawSurface7 *Texture)
5890 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5891 IDirectDrawSurfaceImpl *surf = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, Texture);
5893 TRACE("(%p)->(%p): Relay!\n", This, surf);
5895 if(!Texture)
5896 return DDERR_INVALIDPARAMS;
5898 EnterCriticalSection(&ddraw_cs);
5899 IWineD3DSurface_PreLoad(surf->WineD3DSurface);
5900 LeaveCriticalSection(&ddraw_cs);
5901 return D3D_OK;
5904 static HRESULT WINAPI
5905 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5906 IDirectDrawSurface7 *Texture)
5908 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5911 static HRESULT WINAPI
5912 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5913 IDirectDrawSurface7 *Texture)
5915 HRESULT hr;
5916 WORD old_fpucw;
5918 old_fpucw = d3d_fpu_setup();
5919 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5920 set_fpu_control_word(old_fpucw);
5922 return hr;
5925 /*****************************************************************************
5926 * IDirect3DDevice7::ApplyStateBlock
5928 * Activates the state stored in a state block handle.
5930 * Params:
5931 * BlockHandle: The stateblock handle to activate
5933 * Returns:
5934 * D3D_OK on success
5935 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5937 *****************************************************************************/
5938 static HRESULT
5939 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5940 DWORD BlockHandle)
5942 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
5943 HRESULT hr;
5944 TRACE("(%p)->(%08x): Relay!\n", This, BlockHandle);
5946 EnterCriticalSection(&ddraw_cs);
5947 if(!BlockHandle || BlockHandle > This->numHandles)
5949 WARN("Out of range handle %d, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5950 LeaveCriticalSection(&ddraw_cs);
5951 return D3DERR_INVALIDSTATEBLOCK;
5953 if(This->Handles[BlockHandle - 1].type != DDrawHandle_StateBlock)
5955 WARN("Handle %d is not a stateblock, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5956 LeaveCriticalSection(&ddraw_cs);
5957 return D3DERR_INVALIDSTATEBLOCK;
5960 hr = IWineD3DStateBlock_Apply((IWineD3DStateBlock *) This->Handles[BlockHandle - 1].ptr);
5961 LeaveCriticalSection(&ddraw_cs);
5962 return hr_ddraw_from_wined3d(hr);
5965 static HRESULT WINAPI
5966 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5967 DWORD BlockHandle)
5969 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5972 static HRESULT WINAPI
5973 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5974 DWORD BlockHandle)
5976 HRESULT hr;
5977 WORD old_fpucw;
5979 old_fpucw = d3d_fpu_setup();
5980 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5981 set_fpu_control_word(old_fpucw);
5983 return hr;
5986 /*****************************************************************************
5987 * IDirect3DDevice7::CaptureStateBlock
5989 * Updates a stateblock's values to the values currently set for the device
5991 * Version 7
5993 * Params:
5994 * BlockHandle: Stateblock to update
5996 * Returns:
5997 * D3D_OK on success
5998 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5999 * See IWineD3DDevice::CaptureStateBlock for more details
6001 *****************************************************************************/
6002 static HRESULT
6003 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
6004 DWORD BlockHandle)
6006 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6007 HRESULT hr;
6008 TRACE("(%p)->(%08x): Relay!\n", This, BlockHandle);
6010 EnterCriticalSection(&ddraw_cs);
6011 if(BlockHandle == 0 || BlockHandle > This->numHandles)
6013 WARN("Out of range handle %d, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
6014 LeaveCriticalSection(&ddraw_cs);
6015 return D3DERR_INVALIDSTATEBLOCK;
6017 if(This->Handles[BlockHandle - 1].type != DDrawHandle_StateBlock)
6019 WARN("Handle %d is not a stateblock, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
6020 LeaveCriticalSection(&ddraw_cs);
6021 return D3DERR_INVALIDSTATEBLOCK;
6024 hr = IWineD3DStateBlock_Capture((IWineD3DStateBlock *) This->Handles[BlockHandle - 1].ptr);
6025 LeaveCriticalSection(&ddraw_cs);
6026 return hr_ddraw_from_wined3d(hr);
6029 static HRESULT WINAPI
6030 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
6031 DWORD BlockHandle)
6033 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
6036 static HRESULT WINAPI
6037 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
6038 DWORD BlockHandle)
6040 HRESULT hr;
6041 WORD old_fpucw;
6043 old_fpucw = d3d_fpu_setup();
6044 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
6045 set_fpu_control_word(old_fpucw);
6047 return hr;
6050 /*****************************************************************************
6051 * IDirect3DDevice7::DeleteStateBlock
6053 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
6055 * Version 7
6057 * Params:
6058 * BlockHandle: Stateblock handle to delete
6060 * Returns:
6061 * D3D_OK on success
6062 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
6064 *****************************************************************************/
6065 static HRESULT
6066 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
6067 DWORD BlockHandle)
6069 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6070 ULONG ref;
6071 TRACE("(%p)->(%08x): Relay!\n", This, BlockHandle);
6073 EnterCriticalSection(&ddraw_cs);
6074 if(BlockHandle == 0 || BlockHandle > This->numHandles)
6076 WARN("Out of range handle %d, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
6077 LeaveCriticalSection(&ddraw_cs);
6078 return D3DERR_INVALIDSTATEBLOCK;
6080 if(This->Handles[BlockHandle - 1].type != DDrawHandle_StateBlock)
6082 WARN("Handle %d is not a stateblock, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
6083 LeaveCriticalSection(&ddraw_cs);
6084 return D3DERR_INVALIDSTATEBLOCK;
6087 ref = IWineD3DStateBlock_Release((IWineD3DStateBlock *) This->Handles[BlockHandle - 1].ptr);
6088 if(ref)
6090 ERR("Something is still holding the stateblock %p(Handle %d). Ref = %d\n", This->Handles[BlockHandle - 1].ptr, BlockHandle, ref);
6092 This->Handles[BlockHandle - 1].ptr = NULL;
6093 This->Handles[BlockHandle - 1].type = DDrawHandle_Unknown;
6095 LeaveCriticalSection(&ddraw_cs);
6096 return D3D_OK;
6099 static HRESULT WINAPI
6100 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
6101 DWORD BlockHandle)
6103 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
6106 static HRESULT WINAPI
6107 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
6108 DWORD BlockHandle)
6110 HRESULT hr;
6111 WORD old_fpucw;
6113 old_fpucw = d3d_fpu_setup();
6114 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
6115 set_fpu_control_word(old_fpucw);
6117 return hr;
6120 /*****************************************************************************
6121 * IDirect3DDevice7::CreateStateBlock
6123 * Creates a new state block handle.
6125 * Version 7
6127 * Params:
6128 * Type: The state block type
6129 * BlockHandle: Address to write the created handle to
6131 * Returns:
6132 * D3D_OK on success
6133 * DDERR_INVALIDPARAMS if BlockHandle is NULL
6135 *****************************************************************************/
6136 static HRESULT
6137 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
6138 D3DSTATEBLOCKTYPE Type,
6139 DWORD *BlockHandle)
6141 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6142 HRESULT hr;
6143 TRACE("(%p)->(%08x,%p)!\n", This, Type, BlockHandle);
6145 if(!BlockHandle)
6147 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
6148 return DDERR_INVALIDPARAMS;
6150 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
6151 Type != D3DSBT_VERTEXSTATE ) {
6152 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
6153 return DDERR_INVALIDPARAMS;
6156 EnterCriticalSection(&ddraw_cs);
6157 *BlockHandle = IDirect3DDeviceImpl_CreateHandle(This);
6158 if(!*BlockHandle)
6160 ERR("Cannot get a handle number for the stateblock\n");
6161 LeaveCriticalSection(&ddraw_cs);
6162 return DDERR_OUTOFMEMORY;
6164 This->Handles[*BlockHandle - 1].type = DDrawHandle_StateBlock;
6166 /* The D3DSTATEBLOCKTYPE enum is fine here */
6167 hr = IWineD3DDevice_CreateStateBlock(This->wineD3DDevice,
6168 Type,
6169 (IWineD3DStateBlock **) &This->Handles[*BlockHandle - 1].ptr,
6170 NULL /* Parent, hope that works */);
6171 LeaveCriticalSection(&ddraw_cs);
6172 return hr_ddraw_from_wined3d(hr);
6175 static HRESULT WINAPI
6176 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
6177 D3DSTATEBLOCKTYPE Type,
6178 DWORD *BlockHandle)
6180 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6183 static HRESULT WINAPI
6184 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
6185 D3DSTATEBLOCKTYPE Type,
6186 DWORD *BlockHandle)
6188 HRESULT hr;
6189 WORD old_fpucw;
6191 old_fpucw = d3d_fpu_setup();
6192 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6193 set_fpu_control_word(old_fpucw);
6195 return hr;
6198 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6199 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
6200 IDirectDrawSurfaceImpl *src)
6202 IDirectDrawSurfaceImpl *src_level, *dest_level;
6203 IDirectDrawSurface7 *temp;
6204 DDSURFACEDESC2 ddsd;
6205 BOOL levelFound; /* at least one suitable sublevel in dest found */
6207 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
6208 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
6209 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
6211 levelFound = FALSE;
6213 src_level = src;
6214 dest_level = dest;
6216 for (;src_level && dest_level;)
6218 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6219 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6221 levelFound = TRUE;
6223 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6224 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6225 IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(dest_level, IDirectDrawSurface7), &ddsd.ddsCaps, &temp);
6227 if (dest_level != dest) IDirectDrawSurface7_Release(ICOM_INTERFACE(dest_level, IDirectDrawSurface7));
6229 dest_level = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, temp);
6232 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6233 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6234 IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(src_level, IDirectDrawSurface7), &ddsd.ddsCaps, &temp);
6236 if (src_level != src) IDirectDrawSurface7_Release(ICOM_INTERFACE(src_level, IDirectDrawSurface7));
6238 src_level = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, temp);
6241 if (src_level && src_level != src) IDirectDrawSurface7_Release(ICOM_INTERFACE(src_level, IDirectDrawSurface7));
6242 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(ICOM_INTERFACE(dest_level, IDirectDrawSurface7));
6244 return !dest_level && levelFound;
6247 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6248 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
6249 IDirectDrawSurfaceImpl *dest,
6250 IDirectDrawSurfaceImpl *src,
6251 POINT *DestPoint,
6252 RECT *SrcRect)
6254 IDirectDrawSurfaceImpl *src_level, *dest_level;
6255 IDirectDrawSurface7 *temp;
6256 DDSURFACEDESC2 ddsd;
6257 POINT point;
6258 RECT rect;
6259 HRESULT hr;
6260 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
6261 DWORD ckeyflag;
6262 DDCOLORKEY ddckey;
6263 BOOL palette_missing = FALSE;
6265 /* Copy palette, if possible. */
6266 IDirectDrawSurface7_GetPalette(ICOM_INTERFACE(src, IDirectDrawSurface7), &pal_src);
6267 IDirectDrawSurface7_GetPalette(ICOM_INTERFACE(dest, IDirectDrawSurface7), &pal);
6269 if (pal_src != NULL && pal != NULL)
6271 PALETTEENTRY palent[256];
6273 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
6274 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
6277 if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
6278 DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
6280 palette_missing = TRUE;
6283 if (pal) IDirectDrawPalette_Release(pal);
6284 if (pal_src) IDirectDrawPalette_Release(pal_src);
6286 /* Copy colorkeys, if present. */
6287 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6289 hr = IDirectDrawSurface7_GetColorKey(ICOM_INTERFACE(src, IDirectDrawSurface7), ckeyflag, &ddckey);
6291 if (SUCCEEDED(hr))
6293 IDirectDrawSurface7_SetColorKey(ICOM_INTERFACE(dest, IDirectDrawSurface7), ckeyflag, &ddckey);
6297 src_level = src;
6298 dest_level = dest;
6300 point = *DestPoint;
6301 rect = *SrcRect;
6303 for (;src_level && dest_level;)
6305 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6306 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6308 /* Try UpdateSurface that may perform a more direct opengl loading. But skip this if destination is paletted texture and has no palette.
6309 * Some games like Sacrifice set palette after Load, and it is a waste of effort to try to load texture without palette and generates
6310 * warnings in wined3d. */
6311 if (!palette_missing)
6312 hr = IWineD3DDevice_UpdateSurface(device->wineD3DDevice, src_level->WineD3DSurface, &rect, dest_level->WineD3DSurface,
6313 &point);
6315 if (palette_missing || FAILED(hr))
6317 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
6318 IWineD3DSurface_BltFast(dest_level->WineD3DSurface,
6319 point.x, point.y,
6320 src_level->WineD3DSurface, &rect, 0);
6323 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6324 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6325 IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(dest_level, IDirectDrawSurface7), &ddsd.ddsCaps, &temp);
6327 if (dest_level != dest) IDirectDrawSurface7_Release(ICOM_INTERFACE(dest_level, IDirectDrawSurface7));
6329 dest_level = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, temp);
6332 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6333 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6334 IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(src_level, IDirectDrawSurface7), &ddsd.ddsCaps, &temp);
6336 if (src_level != src) IDirectDrawSurface7_Release(ICOM_INTERFACE(src_level, IDirectDrawSurface7));
6338 src_level = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, temp);
6340 point.x /= 2;
6341 point.y /= 2;
6343 rect.top /= 2;
6344 rect.left /= 2;
6345 rect.right = (rect.right + 1) / 2;
6346 rect.bottom = (rect.bottom + 1) / 2;
6349 if (src_level && src_level != src) IDirectDrawSurface7_Release(ICOM_INTERFACE(src_level, IDirectDrawSurface7));
6350 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(ICOM_INTERFACE(dest_level, IDirectDrawSurface7));
6353 /*****************************************************************************
6354 * IDirect3DDevice7::Load
6356 * Loads a rectangular area from the source into the destination texture.
6357 * It can also copy the source to the faces of a cubic environment map
6359 * Version 7
6361 * Params:
6362 * DestTex: Destination texture
6363 * DestPoint: Point in the destination where the source image should be
6364 * written to
6365 * SrcTex: Source texture
6366 * SrcRect: Source rectangle
6367 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6368 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6369 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6371 * Returns:
6372 * D3D_OK on success
6373 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6376 *****************************************************************************/
6378 static HRESULT
6379 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6380 IDirectDrawSurface7 *DestTex,
6381 POINT *DestPoint,
6382 IDirectDrawSurface7 *SrcTex,
6383 RECT *SrcRect,
6384 DWORD Flags)
6386 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6387 IDirectDrawSurfaceImpl *dest = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, DestTex);
6388 IDirectDrawSurfaceImpl *src = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, SrcTex);
6389 POINT destpoint;
6390 RECT srcrect;
6391 TRACE("(%p)->(%p,%p,%p,%p,%08x)\n", This, dest, DestPoint, src, SrcRect, Flags);
6393 if( (!src) || (!dest) )
6394 return DDERR_INVALIDPARAMS;
6396 EnterCriticalSection(&ddraw_cs);
6398 if (SrcRect) srcrect = *SrcRect;
6399 else
6401 srcrect.left = srcrect.top = 0;
6402 srcrect.right = src->surface_desc.dwWidth;
6403 srcrect.bottom = src->surface_desc.dwHeight;
6406 if (DestPoint) destpoint = *DestPoint;
6407 else
6409 destpoint.x = destpoint.y = 0;
6411 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6412 * destination can be a subset of mip levels, in which case actual coordinates used
6413 * for it may be divided. If any dimension of dest is larger than source, it can't be
6414 * mip level subset, so an error can be returned early.
6416 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6417 srcrect.right > src->surface_desc.dwWidth ||
6418 srcrect.bottom > src->surface_desc.dwHeight ||
6419 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6420 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6421 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6422 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6424 LeaveCriticalSection(&ddraw_cs);
6425 return DDERR_INVALIDPARAMS;
6428 /* Must be top level surfaces. */
6429 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6430 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6432 LeaveCriticalSection(&ddraw_cs);
6433 return DDERR_INVALIDPARAMS;
6436 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6438 DWORD src_face_flag, dest_face_flag;
6439 IDirectDrawSurfaceImpl *src_face, *dest_face;
6440 IDirectDrawSurface7 *temp;
6441 DDSURFACEDESC2 ddsd;
6442 int i;
6444 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6446 LeaveCriticalSection(&ddraw_cs);
6447 return DDERR_INVALIDPARAMS;
6450 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6451 * time it's actual surface loading. */
6452 for (i = 0; i < 2; i++)
6454 dest_face = dest;
6455 src_face = src;
6457 for (;dest_face && src_face;)
6459 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6460 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6462 if (src_face_flag == dest_face_flag)
6464 if (i == 0)
6466 /* Destination mip levels must be subset of source mip levels. */
6467 if (!is_mip_level_subset(dest_face, src_face))
6469 LeaveCriticalSection(&ddraw_cs);
6470 return DDERR_INVALIDPARAMS;
6473 else if (Flags & dest_face_flag)
6475 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6478 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6480 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6481 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6482 IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(src, IDirectDrawSurface7), &ddsd.ddsCaps, &temp);
6484 if (src_face != src) IDirectDrawSurface7_Release(ICOM_INTERFACE(src_face, IDirectDrawSurface7));
6486 src_face = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, temp);
6488 else
6490 if (src_face != src) IDirectDrawSurface7_Release(ICOM_INTERFACE(src_face, IDirectDrawSurface7));
6492 src_face = NULL;
6496 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6498 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6499 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6500 IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(dest, IDirectDrawSurface7), &ddsd.ddsCaps, &temp);
6502 if (dest_face != dest) IDirectDrawSurface7_Release(ICOM_INTERFACE(dest_face, IDirectDrawSurface7));
6504 dest_face = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, temp);
6506 else
6508 if (dest_face != dest) IDirectDrawSurface7_Release(ICOM_INTERFACE(dest_face, IDirectDrawSurface7));
6510 dest_face = NULL;
6514 if (i == 0)
6516 /* Native returns error if src faces are not subset of dest faces. */
6517 if (src_face)
6519 LeaveCriticalSection(&ddraw_cs);
6520 return DDERR_INVALIDPARAMS;
6525 LeaveCriticalSection(&ddraw_cs);
6526 return D3D_OK;
6528 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6530 LeaveCriticalSection(&ddraw_cs);
6531 return DDERR_INVALIDPARAMS;
6534 /* Handle non cube map textures. */
6536 /* Destination mip levels must be subset of source mip levels. */
6537 if (!is_mip_level_subset(dest, src))
6539 LeaveCriticalSection(&ddraw_cs);
6540 return DDERR_INVALIDPARAMS;
6543 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6545 LeaveCriticalSection(&ddraw_cs);
6546 return D3D_OK;
6549 static HRESULT WINAPI
6550 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6551 IDirectDrawSurface7 *DestTex,
6552 POINT *DestPoint,
6553 IDirectDrawSurface7 *SrcTex,
6554 RECT *SrcRect,
6555 DWORD Flags)
6557 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6560 static HRESULT WINAPI
6561 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6562 IDirectDrawSurface7 *DestTex,
6563 POINT *DestPoint,
6564 IDirectDrawSurface7 *SrcTex,
6565 RECT *SrcRect,
6566 DWORD Flags)
6568 HRESULT hr;
6569 WORD old_fpucw;
6571 old_fpucw = d3d_fpu_setup();
6572 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6573 set_fpu_control_word(old_fpucw);
6575 return hr;
6578 /*****************************************************************************
6579 * IDirect3DDevice7::LightEnable
6581 * Enables or disables a light
6583 * Version 7, IDirect3DLight uses this method too.
6585 * Params:
6586 * LightIndex: The index of the light to enable / disable
6587 * Enable: Enable or disable the light
6589 * Returns:
6590 * D3D_OK on success
6591 * For more details, see IWineD3DDevice::SetLightEnable
6593 *****************************************************************************/
6594 static HRESULT
6595 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6596 DWORD LightIndex,
6597 BOOL Enable)
6599 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6600 HRESULT hr;
6601 TRACE("(%p)->(%08x,%d): Relay!\n", This, LightIndex, Enable);
6603 EnterCriticalSection(&ddraw_cs);
6604 hr = IWineD3DDevice_SetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6605 LeaveCriticalSection(&ddraw_cs);
6606 return hr_ddraw_from_wined3d(hr);
6609 static HRESULT WINAPI
6610 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6611 DWORD LightIndex,
6612 BOOL Enable)
6614 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6617 static HRESULT WINAPI
6618 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6619 DWORD LightIndex,
6620 BOOL Enable)
6622 HRESULT hr;
6623 WORD old_fpucw;
6625 old_fpucw = d3d_fpu_setup();
6626 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6627 set_fpu_control_word(old_fpucw);
6629 return hr;
6632 /*****************************************************************************
6633 * IDirect3DDevice7::GetLightEnable
6635 * Retrieves if the light with the given index is enabled or not
6637 * Version 7
6639 * Params:
6640 * LightIndex: Index of desired light
6641 * Enable: Pointer to a BOOL which contains the result
6643 * Returns:
6644 * D3D_OK on success
6645 * DDERR_INVALIDPARAMS if Enable is NULL
6646 * See IWineD3DDevice::GetLightEnable for more details
6648 *****************************************************************************/
6649 static HRESULT
6650 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6651 DWORD LightIndex,
6652 BOOL* Enable)
6654 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6655 HRESULT hr;
6656 TRACE("(%p)->(%08x,%p): Relay\n", This, LightIndex, Enable);
6658 if(!Enable)
6659 return DDERR_INVALIDPARAMS;
6661 EnterCriticalSection(&ddraw_cs);
6662 hr = IWineD3DDevice_GetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6663 LeaveCriticalSection(&ddraw_cs);
6664 return hr_ddraw_from_wined3d(hr);
6667 static HRESULT WINAPI
6668 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6669 DWORD LightIndex,
6670 BOOL* Enable)
6672 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6675 static HRESULT WINAPI
6676 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6677 DWORD LightIndex,
6678 BOOL* Enable)
6680 HRESULT hr;
6681 WORD old_fpucw;
6683 old_fpucw = d3d_fpu_setup();
6684 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6685 set_fpu_control_word(old_fpucw);
6687 return hr;
6690 /*****************************************************************************
6691 * IDirect3DDevice7::SetClipPlane
6693 * Sets custom clipping plane
6695 * Version 7
6697 * Params:
6698 * Index: The index of the clipping plane
6699 * PlaneEquation: An equation defining the clipping plane
6701 * Returns:
6702 * D3D_OK on success
6703 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6704 * See IWineD3DDevice::SetClipPlane for more details
6706 *****************************************************************************/
6707 static HRESULT
6708 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6709 DWORD Index,
6710 D3DVALUE* PlaneEquation)
6712 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6713 HRESULT hr;
6714 TRACE("(%p)->(%08x,%p): Relay!\n", This, Index, PlaneEquation);
6716 if(!PlaneEquation)
6717 return DDERR_INVALIDPARAMS;
6719 EnterCriticalSection(&ddraw_cs);
6720 hr = IWineD3DDevice_SetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6721 LeaveCriticalSection(&ddraw_cs);
6722 return hr;
6725 static HRESULT WINAPI
6726 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6727 DWORD Index,
6728 D3DVALUE* PlaneEquation)
6730 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6733 static HRESULT WINAPI
6734 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6735 DWORD Index,
6736 D3DVALUE* PlaneEquation)
6738 HRESULT hr;
6739 WORD old_fpucw;
6741 old_fpucw = d3d_fpu_setup();
6742 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6743 set_fpu_control_word(old_fpucw);
6745 return hr;
6748 /*****************************************************************************
6749 * IDirect3DDevice7::GetClipPlane
6751 * Returns the clipping plane with a specific index
6753 * Params:
6754 * Index: The index of the desired plane
6755 * PlaneEquation: Address to store the plane equation to
6757 * Returns:
6758 * D3D_OK on success
6759 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6760 * See IWineD3DDevice::GetClipPlane for more details
6762 *****************************************************************************/
6763 static HRESULT
6764 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6765 DWORD Index,
6766 D3DVALUE* PlaneEquation)
6768 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6769 HRESULT hr;
6770 TRACE("(%p)->(%d,%p): Relay!\n", This, Index, PlaneEquation);
6772 if(!PlaneEquation)
6773 return DDERR_INVALIDPARAMS;
6775 EnterCriticalSection(&ddraw_cs);
6776 hr = IWineD3DDevice_GetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6777 LeaveCriticalSection(&ddraw_cs);
6778 return hr;
6781 static HRESULT WINAPI
6782 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6783 DWORD Index,
6784 D3DVALUE* PlaneEquation)
6786 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6789 static HRESULT WINAPI
6790 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6791 DWORD Index,
6792 D3DVALUE* PlaneEquation)
6794 HRESULT hr;
6795 WORD old_fpucw;
6797 old_fpucw = d3d_fpu_setup();
6798 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6799 set_fpu_control_word(old_fpucw);
6801 return hr;
6804 /*****************************************************************************
6805 * IDirect3DDevice7::GetInfo
6807 * Retrieves some information about the device. The DirectX sdk says that
6808 * this version returns S_FALSE for all retail builds of DirectX, that's what
6809 * this implementation does.
6811 * Params:
6812 * DevInfoID: Information type requested
6813 * DevInfoStruct: Pointer to a structure to store the info to
6814 * Size: Size of the structure
6816 * Returns:
6817 * S_FALSE, because it's a non-debug driver
6819 *****************************************************************************/
6820 static HRESULT WINAPI
6821 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6822 DWORD DevInfoID,
6823 void *DevInfoStruct,
6824 DWORD Size)
6826 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
6827 TRACE("(%p)->(%08x,%p,%08x)\n", This, DevInfoID, DevInfoStruct, Size);
6829 if (TRACE_ON(d3d7))
6831 TRACE(" info requested : ");
6832 switch (DevInfoID)
6834 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6835 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6836 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6837 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6841 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6844 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6845 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6846 * are not duplicated.
6848 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6849 * has already been setup for optimal d3d operation.
6851 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6852 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6853 * by Sacrifice (game). */
6854 const IDirect3DDevice7Vtbl IDirect3DDevice7_FPUSetup_Vtbl =
6856 /*** IUnknown Methods ***/
6857 IDirect3DDeviceImpl_7_QueryInterface,
6858 IDirect3DDeviceImpl_7_AddRef,
6859 IDirect3DDeviceImpl_7_Release,
6860 /*** IDirect3DDevice7 ***/
6861 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6862 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6863 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6864 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6865 IDirect3DDeviceImpl_7_GetDirect3D,
6866 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6867 IDirect3DDeviceImpl_7_GetRenderTarget,
6868 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6869 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6870 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6871 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6872 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6873 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6874 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6875 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6876 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6877 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6878 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6879 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6880 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6881 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6882 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6883 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6884 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6885 IDirect3DDeviceImpl_7_SetClipStatus,
6886 IDirect3DDeviceImpl_7_GetClipStatus,
6887 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6888 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6889 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6890 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6891 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6892 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6893 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6894 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6895 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6896 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6897 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6898 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6899 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6900 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6901 IDirect3DDeviceImpl_7_Load_FPUSetup,
6902 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6903 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6904 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6905 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6906 IDirect3DDeviceImpl_7_GetInfo
6909 const IDirect3DDevice7Vtbl IDirect3DDevice7_FPUPreserve_Vtbl =
6911 /*** IUnknown Methods ***/
6912 IDirect3DDeviceImpl_7_QueryInterface,
6913 IDirect3DDeviceImpl_7_AddRef,
6914 IDirect3DDeviceImpl_7_Release,
6915 /*** IDirect3DDevice7 ***/
6916 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6917 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6918 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6919 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6920 IDirect3DDeviceImpl_7_GetDirect3D,
6921 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6922 IDirect3DDeviceImpl_7_GetRenderTarget,
6923 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6924 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6925 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6926 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6927 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6928 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6929 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6930 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6931 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6932 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6933 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6934 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6935 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6936 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6937 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6938 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6939 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6940 IDirect3DDeviceImpl_7_SetClipStatus,
6941 IDirect3DDeviceImpl_7_GetClipStatus,
6942 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6943 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6944 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6945 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6946 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6947 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6948 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6949 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6950 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6951 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6952 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6953 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6954 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6955 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6956 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6957 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6958 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6959 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6960 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6961 IDirect3DDeviceImpl_7_GetInfo
6964 const IDirect3DDevice3Vtbl IDirect3DDevice3_Vtbl =
6966 /*** IUnknown Methods ***/
6967 Thunk_IDirect3DDeviceImpl_3_QueryInterface,
6968 Thunk_IDirect3DDeviceImpl_3_AddRef,
6969 Thunk_IDirect3DDeviceImpl_3_Release,
6970 /*** IDirect3DDevice3 ***/
6971 IDirect3DDeviceImpl_3_GetCaps,
6972 IDirect3DDeviceImpl_3_GetStats,
6973 IDirect3DDeviceImpl_3_AddViewport,
6974 IDirect3DDeviceImpl_3_DeleteViewport,
6975 IDirect3DDeviceImpl_3_NextViewport,
6976 Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
6977 Thunk_IDirect3DDeviceImpl_3_BeginScene,
6978 Thunk_IDirect3DDeviceImpl_3_EndScene,
6979 Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
6980 IDirect3DDeviceImpl_3_SetCurrentViewport,
6981 IDirect3DDeviceImpl_3_GetCurrentViewport,
6982 Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
6983 Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
6984 IDirect3DDeviceImpl_3_Begin,
6985 IDirect3DDeviceImpl_3_BeginIndexed,
6986 IDirect3DDeviceImpl_3_Vertex,
6987 IDirect3DDeviceImpl_3_Index,
6988 IDirect3DDeviceImpl_3_End,
6989 IDirect3DDeviceImpl_3_GetRenderState,
6990 IDirect3DDeviceImpl_3_SetRenderState,
6991 IDirect3DDeviceImpl_3_GetLightState,
6992 IDirect3DDeviceImpl_3_SetLightState,
6993 Thunk_IDirect3DDeviceImpl_3_SetTransform,
6994 Thunk_IDirect3DDeviceImpl_3_GetTransform,
6995 Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
6996 Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
6997 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6998 Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
6999 Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
7000 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
7001 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
7002 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
7003 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
7004 Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
7005 Thunk_IDirect3DDeviceImpl_3_GetTexture,
7006 IDirect3DDeviceImpl_3_SetTexture,
7007 Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
7008 Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
7009 Thunk_IDirect3DDeviceImpl_3_ValidateDevice
7012 const IDirect3DDevice2Vtbl IDirect3DDevice2_Vtbl =
7014 /*** IUnknown Methods ***/
7015 Thunk_IDirect3DDeviceImpl_2_QueryInterface,
7016 Thunk_IDirect3DDeviceImpl_2_AddRef,
7017 Thunk_IDirect3DDeviceImpl_2_Release,
7018 /*** IDirect3DDevice2 ***/
7019 Thunk_IDirect3DDeviceImpl_2_GetCaps,
7020 IDirect3DDeviceImpl_2_SwapTextureHandles,
7021 Thunk_IDirect3DDeviceImpl_2_GetStats,
7022 Thunk_IDirect3DDeviceImpl_2_AddViewport,
7023 Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
7024 Thunk_IDirect3DDeviceImpl_2_NextViewport,
7025 IDirect3DDeviceImpl_2_EnumTextureFormats,
7026 Thunk_IDirect3DDeviceImpl_2_BeginScene,
7027 Thunk_IDirect3DDeviceImpl_2_EndScene,
7028 Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
7029 Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
7030 Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
7031 Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
7032 Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
7033 Thunk_IDirect3DDeviceImpl_2_Begin,
7034 Thunk_IDirect3DDeviceImpl_2_BeginIndexed,
7035 Thunk_IDirect3DDeviceImpl_2_Vertex,
7036 Thunk_IDirect3DDeviceImpl_2_Index,
7037 Thunk_IDirect3DDeviceImpl_2_End,
7038 Thunk_IDirect3DDeviceImpl_2_GetRenderState,
7039 Thunk_IDirect3DDeviceImpl_2_SetRenderState,
7040 Thunk_IDirect3DDeviceImpl_2_GetLightState,
7041 Thunk_IDirect3DDeviceImpl_2_SetLightState,
7042 Thunk_IDirect3DDeviceImpl_2_SetTransform,
7043 Thunk_IDirect3DDeviceImpl_2_GetTransform,
7044 Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
7045 Thunk_IDirect3DDeviceImpl_2_DrawPrimitive,
7046 Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
7047 Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
7048 Thunk_IDirect3DDeviceImpl_2_GetClipStatus
7051 const IDirect3DDeviceVtbl IDirect3DDevice1_Vtbl =
7053 /*** IUnknown Methods ***/
7054 Thunk_IDirect3DDeviceImpl_1_QueryInterface,
7055 Thunk_IDirect3DDeviceImpl_1_AddRef,
7056 Thunk_IDirect3DDeviceImpl_1_Release,
7057 /*** IDirect3DDevice1 ***/
7058 IDirect3DDeviceImpl_1_Initialize,
7059 Thunk_IDirect3DDeviceImpl_1_GetCaps,
7060 Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
7061 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
7062 Thunk_IDirect3DDeviceImpl_1_GetStats,
7063 IDirect3DDeviceImpl_1_Execute,
7064 Thunk_IDirect3DDeviceImpl_1_AddViewport,
7065 Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
7066 Thunk_IDirect3DDeviceImpl_1_NextViewport,
7067 IDirect3DDeviceImpl_1_Pick,
7068 IDirect3DDeviceImpl_1_GetPickRecords,
7069 Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
7070 IDirect3DDeviceImpl_1_CreateMatrix,
7071 IDirect3DDeviceImpl_1_SetMatrix,
7072 IDirect3DDeviceImpl_1_GetMatrix,
7073 IDirect3DDeviceImpl_1_DeleteMatrix,
7074 Thunk_IDirect3DDeviceImpl_1_BeginScene,
7075 Thunk_IDirect3DDeviceImpl_1_EndScene,
7076 Thunk_IDirect3DDeviceImpl_1_GetDirect3D
7079 /*****************************************************************************
7080 * IDirect3DDeviceImpl_CreateHandle
7082 * Not called from the VTable
7084 * Some older interface versions operate with handles, which are basically
7085 * DWORDs which identify an interface, for example
7086 * IDirect3DDevice::SetRenderState with DIRECT3DRENDERSTATE_TEXTUREHANDLE
7088 * Those handle could be just casts to the interface pointers or vice versa,
7089 * but that is not 64 bit safe and would mean blindly derefering a DWORD
7090 * passed by the app. Instead there is a dynamic array in the device which
7091 * keeps a DWORD to pointer information and a type for the handle.
7093 * Basically this array only grows, when a handle is freed its pointer is
7094 * just set to NULL. There will be much more reads from the array than
7095 * insertion operations, so a dynamic array is fine.
7097 * Params:
7098 * This: D3DDevice implementation for which this handle should be created
7100 * Returns:
7101 * A free handle on success
7102 * 0 on failure
7104 *****************************************************************************/
7105 DWORD
7106 IDirect3DDeviceImpl_CreateHandle(IDirect3DDeviceImpl *This)
7108 DWORD i;
7109 struct HandleEntry *oldHandles = This->Handles;
7111 TRACE("(%p)\n", This);
7113 for(i = 0; i < This->numHandles; i++)
7115 if(This->Handles[i].ptr == NULL &&
7116 This->Handles[i].type == DDrawHandle_Unknown)
7118 TRACE("Reusing freed handle %d\n", i + 1);
7119 return i + 1;
7123 TRACE("Growing the handle array\n");
7125 This->numHandles++;
7126 This->Handles = HeapAlloc(GetProcessHeap(), 0, sizeof(struct HandleEntry) * This->numHandles);
7127 if(!This->Handles)
7129 ERR("Out of memory\n");
7130 This->Handles = oldHandles;
7131 This->numHandles--;
7132 return 0;
7134 if(oldHandles)
7136 memcpy(This->Handles, oldHandles, (This->numHandles - 1) * sizeof(struct HandleEntry));
7137 HeapFree(GetProcessHeap(), 0, oldHandles);
7140 TRACE("Returning %d\n", This->numHandles);
7141 return This->numHandles;
7144 /*****************************************************************************
7145 * IDirect3DDeviceImpl_UpdateDepthStencil
7147 * Checks the current render target for attached depth stencils and sets the
7148 * WineD3D depth stencil accordingly.
7150 * Returns:
7151 * The depth stencil state to set if creating the device
7153 *****************************************************************************/
7154 WINED3DZBUFFERTYPE
7155 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
7157 IDirectDrawSurface7 *depthStencil = NULL;
7158 IDirectDrawSurfaceImpl *dsi;
7159 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
7161 IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(This->target, IDirectDrawSurface7),
7162 &depthcaps,
7163 &depthStencil);
7164 if(!depthStencil)
7166 TRACE("Setting wined3d depth stencil to NULL\n");
7167 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
7168 NULL);
7169 return WINED3DZB_FALSE;
7172 dsi = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, depthStencil);
7173 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->WineD3DSurface);
7174 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
7175 dsi->WineD3DSurface);
7177 IDirectDrawSurface7_Release(depthStencil);
7178 return WINED3DZB_TRUE;