wined3d: Get rid of the WINED3DLIGHT typedef.
[wine/multimedia.git] / dlls / ddraw / device.c
blob06fa7c453dacbbe9e740382750f0b7db8ecc7f20
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 "ddraw_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
37 /* The device ID */
38 const GUID IID_D3DDEVICE_WineD3D = {
39 0xaef72d43,
40 0xb09a,
41 0x4b7b,
42 { 0xb7,0x98,0xc6,0x8a,0x77,0x2d,0x72,0x2a }
45 static inline void set_fpu_control_word(WORD fpucw)
47 #if defined(__i386__) && defined(__GNUC__)
48 __asm__ volatile ("fldcw %0" : : "m" (fpucw));
49 #elif defined(__i386__) && defined(_MSC_VER)
50 __asm fldcw fpucw;
51 #endif
54 static inline WORD d3d_fpu_setup(void)
56 WORD oldcw;
58 #if defined(__i386__) && defined(__GNUC__)
59 __asm__ volatile ("fnstcw %0" : "=m" (oldcw));
60 #elif defined(__i386__) && defined(_MSC_VER)
61 __asm fnstcw oldcw;
62 #else
63 static BOOL warned = FALSE;
64 if(!warned)
66 FIXME("FPUPRESERVE not implemented for this platform / compiler\n");
67 warned = TRUE;
69 return 0;
70 #endif
72 set_fpu_control_word(0x37f);
74 return oldcw;
77 /*****************************************************************************
78 * IUnknown Methods. Common for Version 1, 2, 3 and 7
79 *****************************************************************************/
81 /*****************************************************************************
82 * IDirect3DDevice7::QueryInterface
84 * Used to query other interfaces from a Direct3DDevice interface.
85 * It can return interface pointers to all Direct3DDevice versions as well
86 * as IDirectDraw and IDirect3D. For a link to QueryInterface
87 * rules see ddraw.c, IDirectDraw7::QueryInterface
89 * Exists in Version 1, 2, 3 and 7
91 * Params:
92 * refiid: Interface ID queried for
93 * obj: Used to return the interface pointer
95 * Returns:
96 * D3D_OK or E_NOINTERFACE
98 *****************************************************************************/
99 static HRESULT WINAPI
100 IDirect3DDeviceImpl_7_QueryInterface(IDirect3DDevice7 *iface,
101 REFIID refiid,
102 void **obj)
104 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
106 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(refiid), obj);
108 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
109 *obj = NULL;
111 if(!refiid)
112 return DDERR_INVALIDPARAMS;
114 if ( IsEqualGUID( &IID_IUnknown, refiid ) )
116 *obj = iface;
119 /* Check DirectDraw Interfaces. */
120 else if( IsEqualGUID( &IID_IDirectDraw7, refiid ) )
122 *obj = &This->ddraw->IDirectDraw7_iface;
123 TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
125 else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
127 *obj = &This->ddraw->IDirectDraw4_iface;
128 TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
130 else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
132 *obj = &This->ddraw->IDirectDraw2_iface;
133 TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
135 else if( IsEqualGUID( &IID_IDirectDraw, refiid ) )
137 *obj = &This->ddraw->IDirectDraw_iface;
138 TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
141 /* Direct3D */
142 else if ( IsEqualGUID( &IID_IDirect3D , refiid ) )
144 *obj = &This->ddraw->IDirect3D_iface;
145 TRACE("(%p) Returning IDirect3D interface at %p\n", This, *obj);
147 else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) )
149 *obj = &This->ddraw->IDirect3D2_iface;
150 TRACE("(%p) Returning IDirect3D2 interface at %p\n", This, *obj);
152 else if ( IsEqualGUID( &IID_IDirect3D3 , refiid ) )
154 *obj = &This->ddraw->IDirect3D3_iface;
155 TRACE("(%p) Returning IDirect3D3 interface at %p\n", This, *obj);
157 else if ( IsEqualGUID( &IID_IDirect3D7 , refiid ) )
159 *obj = &This->ddraw->IDirect3D7_iface;
160 TRACE("(%p) Returning IDirect3D7 interface at %p\n", This, *obj);
163 /* Direct3DDevice */
164 else if ( IsEqualGUID( &IID_IDirect3DDevice , refiid ) )
166 *obj = &This->IDirect3DDevice_iface;
167 TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
169 else if ( IsEqualGUID( &IID_IDirect3DDevice2 , refiid ) ) {
170 *obj = &This->IDirect3DDevice2_iface;
171 TRACE("(%p) Returning IDirect3DDevice2 interface at %p\n", This, *obj);
173 else if ( IsEqualGUID( &IID_IDirect3DDevice3 , refiid ) ) {
174 *obj = &This->IDirect3DDevice3_iface;
175 TRACE("(%p) Returning IDirect3DDevice3 interface at %p\n", This, *obj);
177 else if ( IsEqualGUID( &IID_IDirect3DDevice7 , refiid ) ) {
178 *obj = This;
179 TRACE("(%p) Returning IDirect3DDevice7 interface at %p\n", This, *obj);
182 /* Unknown interface */
183 else
185 ERR("(%p)->(%s, %p): No interface found\n", This, debugstr_guid(refiid), obj);
186 return E_NOINTERFACE;
189 /* AddRef the returned interface */
190 IUnknown_AddRef( (IUnknown *) *obj);
191 return D3D_OK;
194 static HRESULT WINAPI IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface, REFIID riid,
195 void **obj)
197 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
198 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
200 return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obj);
203 static HRESULT WINAPI IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface, REFIID riid,
204 void **obj)
206 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
207 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
209 return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obj);
212 static HRESULT WINAPI IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface, REFIID riid,
213 void **obp)
215 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
216 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
218 return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obp);
221 /*****************************************************************************
222 * IDirect3DDevice7::AddRef
224 * Increases the refcount....
225 * The most exciting Method, definitely
227 * Exists in Version 1, 2, 3 and 7
229 * Returns:
230 * The new refcount
232 *****************************************************************************/
233 static ULONG WINAPI
234 IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
236 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
237 ULONG ref = InterlockedIncrement(&This->ref);
239 TRACE("%p increasing refcount to %u.\n", This, ref);
241 return ref;
244 static ULONG WINAPI IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
246 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
247 TRACE("iface %p.\n", iface);
249 return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
252 static ULONG WINAPI IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
254 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
255 TRACE("iface %p.\n", iface);
257 return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
260 static ULONG WINAPI IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
262 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
263 TRACE("iface %p.\n", iface);
265 return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
268 /*****************************************************************************
269 * IDirect3DDevice7::Release
271 * Decreases the refcount of the interface
272 * When the refcount is reduced to 0, the object is destroyed.
274 * Exists in Version 1, 2, 3 and 7
276 * Returns:d
277 * The new refcount
279 *****************************************************************************/
280 static ULONG WINAPI
281 IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
283 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
284 ULONG ref = InterlockedDecrement(&This->ref);
286 TRACE("%p decreasing refcount to %u.\n", This, ref);
288 /* This method doesn't destroy the WineD3DDevice, because it's still in use for
289 * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
290 * when the render target is released
292 if (ref == 0)
294 DWORD i;
296 wined3d_mutex_lock();
298 /* There is no need to unset any resources here, wined3d will take
299 * care of that on Uninit3D(). */
301 /* Free the index buffer. */
302 wined3d_buffer_decref(This->indexbuffer);
304 /* Set the device up to render to the front buffer since the back
305 * buffer will vanish soon. */
306 wined3d_device_set_render_target(This->wined3d_device, 0,
307 This->ddraw->d3d_target->wined3d_surface, TRUE);
309 /* Release the WineD3DDevice. This won't destroy it. */
310 if (!wined3d_device_decref(This->wined3d_device))
311 ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This->wined3d_device);
313 /* The texture handles should be unset by now, but there might be some bits
314 * missing in our reference counting(needs test). Do a sanity check. */
315 for (i = 0; i < This->handle_table.entry_count; ++i)
317 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
319 switch (entry->type)
321 case DDRAW_HANDLE_FREE:
322 break;
324 case DDRAW_HANDLE_MATERIAL:
326 IDirect3DMaterialImpl *m = entry->object;
327 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
328 m->Handle = 0;
329 break;
332 case DDRAW_HANDLE_MATRIX:
334 /* No FIXME here because this might happen because of sloppy applications. */
335 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
336 IDirect3DDevice_DeleteMatrix(&This->IDirect3DDevice_iface, i + 1);
337 break;
340 case DDRAW_HANDLE_STATEBLOCK:
342 /* No FIXME here because this might happen because of sloppy applications. */
343 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
344 IDirect3DDevice7_DeleteStateBlock(iface, i + 1);
345 break;
348 case DDRAW_HANDLE_SURFACE:
350 IDirectDrawSurfaceImpl *surf = entry->object;
351 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
352 surf->Handle = 0;
353 break;
356 default:
357 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
358 break;
362 ddraw_handle_table_destroy(&This->handle_table);
364 TRACE("Releasing target %p %p\n", This->target, This->ddraw->d3d_target);
365 /* Release the render target and the WineD3D render target
366 * (See IDirect3D7::CreateDevice for more comments on this)
368 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
369 IDirectDrawSurface7_Release(&This->ddraw->d3d_target->IDirectDrawSurface7_iface);
370 TRACE("Target release done\n");
372 This->ddraw->d3ddevice = NULL;
374 /* Now free the structure */
375 HeapFree(GetProcessHeap(), 0, This);
376 wined3d_mutex_unlock();
379 TRACE("Done\n");
380 return ref;
383 static ULONG WINAPI IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
385 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
386 TRACE("iface %p.\n", iface);
388 return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
391 static ULONG WINAPI IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
393 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
394 TRACE("iface %p.\n", iface);
396 return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
399 static ULONG WINAPI IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
401 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
402 TRACE("iface %p.\n", iface);
404 return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
407 /*****************************************************************************
408 * IDirect3DDevice Methods
409 *****************************************************************************/
411 /*****************************************************************************
412 * IDirect3DDevice::Initialize
414 * Initializes a Direct3DDevice. This implementation is a no-op, as all
415 * initialization is done at create time.
417 * Exists in Version 1
419 * Parameters:
420 * No idea what they mean, as the MSDN page is gone
422 * Returns: DD_OK
424 *****************************************************************************/
425 static HRESULT WINAPI
426 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
427 IDirect3D *Direct3D, GUID *guid,
428 D3DDEVICEDESC *Desc)
430 /* It shouldn't be crucial, but print a FIXME, I'm interested if
431 * any game calls it and when. */
432 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
433 iface, Direct3D, debugstr_guid(guid), Desc);
435 return D3D_OK;
438 /*****************************************************************************
439 * IDirect3DDevice7::GetCaps
441 * Retrieves the device's capabilities
443 * This implementation is used for Version 7 only, the older versions have
444 * their own implementation.
446 * Parameters:
447 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
449 * Returns:
450 * D3D_OK on success
451 * D3DERR_* if a problem occurs. See WineD3D
453 *****************************************************************************/
454 static HRESULT
455 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
456 D3DDEVICEDESC7 *Desc)
458 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
459 D3DDEVICEDESC OldDesc;
461 TRACE("iface %p, device_desc %p.\n", iface, Desc);
463 /* Call the same function used by IDirect3D, this saves code */
464 return IDirect3DImpl_GetCaps(This->ddraw->wineD3D, &OldDesc, Desc);
467 static HRESULT WINAPI
468 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
469 D3DDEVICEDESC7 *Desc)
471 return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
474 static HRESULT WINAPI
475 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
476 D3DDEVICEDESC7 *Desc)
478 HRESULT hr;
479 WORD old_fpucw;
481 old_fpucw = d3d_fpu_setup();
482 hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
483 set_fpu_control_word(old_fpucw);
485 return hr;
487 /*****************************************************************************
488 * IDirect3DDevice3::GetCaps
490 * Retrieves the capabilities of the hardware device and the emulation
491 * device. For Wine, hardware and emulation are the same (it's all HW).
493 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
495 * Parameters:
496 * HWDesc: Structure to fill with the HW caps
497 * HelDesc: Structure to fill with the hardware emulation caps
499 * Returns:
500 * D3D_OK on success
501 * D3DERR_* if a problem occurs. See WineD3D
503 *****************************************************************************/
504 static HRESULT WINAPI
505 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
506 D3DDEVICEDESC *HWDesc,
507 D3DDEVICEDESC *HelDesc)
509 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
510 D3DDEVICEDESC7 newDesc;
511 HRESULT hr;
513 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
515 hr = IDirect3DImpl_GetCaps(This->ddraw->wineD3D, HWDesc, &newDesc);
516 if(hr != D3D_OK) return hr;
518 *HelDesc = *HWDesc;
519 return D3D_OK;
522 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
523 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
525 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
526 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
527 return IDirect3DDevice3_GetCaps(&This->IDirect3DDevice3_iface, D3DHWDevDesc, D3DHELDevDesc);
530 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
531 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
533 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
534 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
535 return IDirect3DDevice3_GetCaps(&This->IDirect3DDevice3_iface, D3DHWDevDesc, D3DHELDevDesc);
538 /*****************************************************************************
539 * IDirect3DDevice2::SwapTextureHandles
541 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
543 * Parameters:
544 * Tex1, Tex2: The 2 Textures to swap
546 * Returns:
547 * D3D_OK
549 *****************************************************************************/
550 static HRESULT WINAPI
551 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
552 IDirect3DTexture2 *Tex1,
553 IDirect3DTexture2 *Tex2)
555 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
556 IDirectDrawSurfaceImpl *surf1 = unsafe_impl_from_IDirect3DTexture2(Tex1);
557 IDirectDrawSurfaceImpl *surf2 = unsafe_impl_from_IDirect3DTexture2(Tex2);
558 DWORD h1, h2;
560 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, Tex1, Tex2);
562 wined3d_mutex_lock();
564 h1 = surf1->Handle - 1;
565 h2 = surf2->Handle - 1;
566 This->handle_table.entries[h1].object = surf2;
567 This->handle_table.entries[h2].object = surf1;
568 surf2->Handle = h1 + 1;
569 surf1->Handle = h2 + 1;
571 wined3d_mutex_unlock();
573 return D3D_OK;
576 static HRESULT WINAPI IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
577 IDirect3DTexture *D3DTex1, IDirect3DTexture *D3DTex2)
579 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
580 IDirectDrawSurfaceImpl *surf1 = unsafe_impl_from_IDirect3DTexture(D3DTex1);
581 IDirectDrawSurfaceImpl *surf2 = unsafe_impl_from_IDirect3DTexture(D3DTex2);
582 IDirect3DTexture2 *t1 = surf1 ? &surf1->IDirect3DTexture2_iface : NULL;
583 IDirect3DTexture2 *t2 = surf2 ? &surf2->IDirect3DTexture2_iface : NULL;
585 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, D3DTex1, D3DTex2);
587 return IDirect3DDevice2_SwapTextureHandles(&This->IDirect3DDevice2_iface, t1, t2);
590 /*****************************************************************************
591 * IDirect3DDevice3::GetStats
593 * This method seems to retrieve some stats from the device.
594 * The MSDN documentation doesn't exist any more, but the D3DSTATS
595 * structure suggests that the amount of drawn primitives and processed
596 * vertices is returned.
598 * Exists in Version 1, 2 and 3
600 * Parameters:
601 * Stats: Pointer to a D3DSTATS structure to be filled
603 * Returns:
604 * D3D_OK on success
605 * DDERR_INVALIDPARAMS if Stats == NULL
607 *****************************************************************************/
608 static HRESULT WINAPI
609 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
610 D3DSTATS *Stats)
612 FIXME("iface %p, stats %p stub!\n", iface, Stats);
614 if(!Stats)
615 return DDERR_INVALIDPARAMS;
617 /* Fill the Stats with 0 */
618 Stats->dwTrianglesDrawn = 0;
619 Stats->dwLinesDrawn = 0;
620 Stats->dwPointsDrawn = 0;
621 Stats->dwSpansDrawn = 0;
622 Stats->dwVerticesProcessed = 0;
624 return D3D_OK;
627 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *Stats)
629 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
631 TRACE("iface %p, stats %p.\n", iface, Stats);
633 return IDirect3DDevice3_GetStats(&This->IDirect3DDevice3_iface, Stats);
636 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface, D3DSTATS *Stats)
638 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
640 TRACE("iface %p, stats %p.\n", iface, Stats);
642 return IDirect3DDevice3_GetStats(&This->IDirect3DDevice3_iface, Stats);
645 /*****************************************************************************
646 * IDirect3DDevice::CreateExecuteBuffer
648 * Creates an IDirect3DExecuteBuffer, used for rendering with a
649 * Direct3DDevice.
651 * Version 1 only.
653 * Params:
654 * Desc: Buffer description
655 * ExecuteBuffer: Address to return the Interface pointer at
656 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
657 * support
659 * Returns:
660 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
661 * DDERR_OUTOFMEMORY if we ran out of memory
662 * D3D_OK on success
664 *****************************************************************************/
665 static HRESULT WINAPI
666 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
667 D3DEXECUTEBUFFERDESC *Desc,
668 IDirect3DExecuteBuffer **ExecuteBuffer,
669 IUnknown *UnkOuter)
671 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
672 IDirect3DExecuteBufferImpl* object;
673 HRESULT hr;
675 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
676 iface, Desc, ExecuteBuffer, UnkOuter);
678 if(UnkOuter)
679 return CLASS_E_NOAGGREGATION;
681 /* Allocate the new Execute Buffer */
682 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
683 if(!object)
685 ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
686 return DDERR_OUTOFMEMORY;
689 hr = d3d_execute_buffer_init(object, This, Desc);
690 if (FAILED(hr))
692 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
693 HeapFree(GetProcessHeap(), 0, object);
694 return hr;
697 *ExecuteBuffer = &object->IDirect3DExecuteBuffer_iface;
699 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
701 return D3D_OK;
704 /*****************************************************************************
705 * IDirect3DDevice::Execute
707 * Executes all the stuff in an execute buffer.
709 * Params:
710 * ExecuteBuffer: The buffer to execute
711 * Viewport: The viewport used for rendering
712 * Flags: Some flags
714 * Returns:
715 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
716 * D3D_OK on success
718 *****************************************************************************/
719 static HRESULT WINAPI IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
720 IDirect3DExecuteBuffer *ExecuteBuffer, IDirect3DViewport *Viewport, DWORD Flags)
722 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
723 IDirect3DExecuteBufferImpl *buffer = unsafe_impl_from_IDirect3DExecuteBuffer(ExecuteBuffer);
724 IDirect3DViewportImpl *Direct3DViewportImpl = unsafe_impl_from_IDirect3DViewport(Viewport);
725 HRESULT hr;
727 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, Viewport, Flags);
729 if(!buffer)
730 return DDERR_INVALIDPARAMS;
732 /* Execute... */
733 wined3d_mutex_lock();
734 hr = d3d_execute_buffer_execute(buffer, This, Direct3DViewportImpl);
735 wined3d_mutex_unlock();
737 return hr;
740 /*****************************************************************************
741 * IDirect3DDevice3::AddViewport
743 * Add a Direct3DViewport to the device's viewport list. These viewports
744 * are wrapped to IDirect3DDevice7 viewports in viewport.c
746 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
747 * are the same interfaces.
749 * Params:
750 * Viewport: The viewport to add
752 * Returns:
753 * DDERR_INVALIDPARAMS if Viewport == NULL
754 * D3D_OK on success
756 *****************************************************************************/
757 static HRESULT WINAPI
758 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
759 IDirect3DViewport3 *Viewport)
761 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
762 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(Viewport);
764 TRACE("iface %p, viewport %p.\n", iface, Viewport);
766 /* Sanity check */
767 if(!vp)
768 return DDERR_INVALIDPARAMS;
770 wined3d_mutex_lock();
771 list_add_head(&This->viewport_list, &vp->entry);
772 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
773 so set active_device here. */
774 wined3d_mutex_unlock();
776 return D3D_OK;
779 static HRESULT WINAPI IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
780 IDirect3DViewport2 *Direct3DViewport2)
782 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
783 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
785 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
787 return IDirect3DDevice3_AddViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
790 static HRESULT WINAPI IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
791 IDirect3DViewport *Direct3DViewport)
793 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
794 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport(Direct3DViewport);
796 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
798 return IDirect3DDevice3_AddViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
801 /*****************************************************************************
802 * IDirect3DDevice3::DeleteViewport
804 * Deletes a Direct3DViewport from the device's viewport list.
806 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
807 * are equal.
809 * Params:
810 * Viewport: The viewport to delete
812 * Returns:
813 * D3D_OK on success
814 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
816 *****************************************************************************/
817 static HRESULT WINAPI IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
819 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
820 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
822 TRACE("iface %p, viewport %p.\n", iface, viewport);
824 wined3d_mutex_lock();
826 if (vp->active_device != This)
828 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
829 wined3d_mutex_unlock();
830 return DDERR_INVALIDPARAMS;
833 vp->active_device = NULL;
834 list_remove(&vp->entry);
836 wined3d_mutex_unlock();
838 return D3D_OK;
841 static HRESULT WINAPI IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
842 IDirect3DViewport2 *Direct3DViewport2)
844 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
845 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
847 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
849 return IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
852 static HRESULT WINAPI IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
853 IDirect3DViewport *Direct3DViewport)
855 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
856 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport(Direct3DViewport);
858 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
860 return IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
863 /*****************************************************************************
864 * IDirect3DDevice3::NextViewport
866 * Returns a viewport from the viewport list, depending on the
867 * passed viewport and the flags.
869 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
870 * are equal.
872 * Params:
873 * Viewport: Viewport to use for beginning the search
874 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
876 * Returns:
877 * D3D_OK on success
878 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
880 *****************************************************************************/
881 static HRESULT WINAPI
882 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
883 IDirect3DViewport3 *Viewport3,
884 IDirect3DViewport3 **lplpDirect3DViewport3,
885 DWORD Flags)
887 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
888 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(Viewport3);
889 IDirect3DViewportImpl *next;
890 struct list *entry;
892 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
893 iface, Viewport3, lplpDirect3DViewport3, Flags);
895 if(!vp)
897 *lplpDirect3DViewport3 = NULL;
898 return DDERR_INVALIDPARAMS;
902 wined3d_mutex_lock();
903 switch (Flags)
905 case D3DNEXT_NEXT:
906 entry = list_next(&This->viewport_list, &vp->entry);
907 break;
909 case D3DNEXT_HEAD:
910 entry = list_head(&This->viewport_list);
911 break;
913 case D3DNEXT_TAIL:
914 entry = list_tail(&This->viewport_list);
915 break;
917 default:
918 WARN("Invalid flags %#x.\n", Flags);
919 *lplpDirect3DViewport3 = NULL;
920 wined3d_mutex_unlock();
921 return DDERR_INVALIDPARAMS;
924 if (entry)
926 next = LIST_ENTRY(entry, IDirect3DViewportImpl, entry);
927 *lplpDirect3DViewport3 = &next->IDirect3DViewport3_iface;
929 else
930 *lplpDirect3DViewport3 = NULL;
932 wined3d_mutex_unlock();
934 return D3D_OK;
937 static HRESULT WINAPI IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
938 IDirect3DViewport2 *Viewport2, IDirect3DViewport2 **lplpDirect3DViewport2, DWORD Flags)
940 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
941 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Viewport2);
942 IDirect3DViewport3 *res;
943 HRESULT hr;
945 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
946 iface, Viewport2, lplpDirect3DViewport2, Flags);
948 hr = IDirect3DDevice3_NextViewport(&This->IDirect3DDevice3_iface,
949 &vp->IDirect3DViewport3_iface, &res, Flags);
950 *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
951 return hr;
954 static HRESULT WINAPI IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
955 IDirect3DViewport *Viewport, IDirect3DViewport **lplpDirect3DViewport, DWORD Flags)
957 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
958 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport(Viewport);
959 IDirect3DViewport3 *res;
960 HRESULT hr;
962 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
963 iface, Viewport, lplpDirect3DViewport, Flags);
965 hr = IDirect3DDevice3_NextViewport(&This->IDirect3DDevice3_iface,
966 &vp->IDirect3DViewport3_iface, &res, Flags);
967 *lplpDirect3DViewport = (IDirect3DViewport *)res;
968 return hr;
971 /*****************************************************************************
972 * IDirect3DDevice::Pick
974 * Executes an execute buffer without performing rendering. Instead, a
975 * list of primitives that intersect with (x1,y1) of the passed rectangle
976 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
977 * this list.
979 * Version 1 only
981 * Params:
982 * ExecuteBuffer: Buffer to execute
983 * Viewport: Viewport to use for execution
984 * Flags: None are defined, according to the SDK
985 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
986 * x2 and y2 are ignored.
988 * Returns:
989 * D3D_OK because it's a stub
991 *****************************************************************************/
992 static HRESULT WINAPI
993 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
994 IDirect3DExecuteBuffer *ExecuteBuffer,
995 IDirect3DViewport *Viewport,
996 DWORD Flags,
997 D3DRECT *Rect)
999 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
1000 iface, ExecuteBuffer, Viewport, Flags, wine_dbgstr_rect((RECT *)Rect));
1002 return D3D_OK;
1005 /*****************************************************************************
1006 * IDirect3DDevice::GetPickRecords
1008 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1010 * Version 1 only
1012 * Params:
1013 * Count: Pointer to a DWORD containing the numbers of pick records to
1014 * retrieve
1015 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1017 * Returns:
1018 * D3D_OK, because it's a stub
1020 *****************************************************************************/
1021 static HRESULT WINAPI
1022 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1023 DWORD *Count,
1024 D3DPICKRECORD *D3DPickRec)
1026 FIXME("iface %p, count %p, records %p stub!\n", iface, Count, D3DPickRec);
1028 return D3D_OK;
1031 /*****************************************************************************
1032 * IDirect3DDevice7::EnumTextureformats
1034 * Enumerates the supported texture formats. It has a list of all possible
1035 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1036 * WineD3D supports it. If so, then it is passed to the app.
1038 * This is for Version 7 and 3, older versions have a different
1039 * callback function and their own implementation
1041 * Params:
1042 * Callback: Callback to call for each enumerated format
1043 * Arg: Argument to pass to the callback
1045 * Returns:
1046 * D3D_OK on success
1047 * DDERR_INVALIDPARAMS if Callback == NULL
1049 *****************************************************************************/
1050 static HRESULT
1051 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1052 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1053 void *Arg)
1055 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1056 struct wined3d_display_mode mode;
1057 HRESULT hr;
1058 unsigned int i;
1060 static const enum wined3d_format_id FormatList[] =
1062 /* 32 bit */
1063 WINED3DFMT_B8G8R8A8_UNORM,
1064 WINED3DFMT_B8G8R8X8_UNORM,
1065 /* 24 bit */
1066 WINED3DFMT_B8G8R8_UNORM,
1067 /* 16 Bit */
1068 WINED3DFMT_B5G5R5A1_UNORM,
1069 WINED3DFMT_B4G4R4A4_UNORM,
1070 WINED3DFMT_B5G6R5_UNORM,
1071 WINED3DFMT_B5G5R5X1_UNORM,
1072 /* 8 Bit */
1073 WINED3DFMT_B2G3R3_UNORM,
1074 WINED3DFMT_P8_UINT,
1075 /* FOURCC codes */
1076 WINED3DFMT_DXT1,
1077 WINED3DFMT_DXT3,
1078 WINED3DFMT_DXT5,
1081 static const enum wined3d_format_id BumpFormatList[] =
1083 WINED3DFMT_R8G8_SNORM,
1084 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1085 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1086 WINED3DFMT_R16G16_SNORM,
1087 WINED3DFMT_R10G11B11_SNORM,
1088 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1091 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1093 if(!Callback)
1094 return DDERR_INVALIDPARAMS;
1096 wined3d_mutex_lock();
1098 memset(&mode, 0, sizeof(mode));
1099 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1100 if (FAILED(hr))
1102 wined3d_mutex_unlock();
1103 WARN("Cannot get the current adapter format\n");
1104 return hr;
1107 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1109 hr = wined3d_check_device_format(This->ddraw->wineD3D, WINED3DADAPTER_DEFAULT, WINED3DDEVTYPE_HAL,
1110 mode.format_id, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1111 if (hr == D3D_OK)
1113 DDPIXELFORMAT pformat;
1115 memset(&pformat, 0, sizeof(pformat));
1116 pformat.dwSize = sizeof(pformat);
1117 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1119 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1120 hr = Callback(&pformat, Arg);
1121 if(hr != DDENUMRET_OK)
1123 TRACE("Format enumeration cancelled by application\n");
1124 wined3d_mutex_unlock();
1125 return D3D_OK;
1130 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1132 hr = wined3d_check_device_format(This->ddraw->wineD3D, WINED3DADAPTER_DEFAULT,
1133 WINED3DDEVTYPE_HAL, mode.format_id, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1134 WINED3DRTYPE_TEXTURE, BumpFormatList[i], SURFACE_OPENGL);
1135 if (hr == D3D_OK)
1137 DDPIXELFORMAT pformat;
1139 memset(&pformat, 0, sizeof(pformat));
1140 pformat.dwSize = sizeof(pformat);
1141 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1143 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1144 hr = Callback(&pformat, Arg);
1145 if(hr != DDENUMRET_OK)
1147 TRACE("Format enumeration cancelled by application\n");
1148 wined3d_mutex_unlock();
1149 return D3D_OK;
1153 TRACE("End of enumeration\n");
1154 wined3d_mutex_unlock();
1156 return D3D_OK;
1159 static HRESULT WINAPI
1160 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1161 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1162 void *Arg)
1164 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1167 static HRESULT WINAPI
1168 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1169 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1170 void *Arg)
1172 HRESULT hr;
1173 WORD old_fpucw;
1175 old_fpucw = d3d_fpu_setup();
1176 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1177 set_fpu_control_word(old_fpucw);
1179 return hr;
1182 static HRESULT WINAPI IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1183 LPD3DENUMPIXELFORMATSCALLBACK Callback, void *Arg)
1185 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1187 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1189 return IDirect3DDevice7_EnumTextureFormats(&This->IDirect3DDevice7_iface, Callback, Arg);
1192 /*****************************************************************************
1193 * IDirect3DDevice2::EnumTextureformats
1195 * EnumTextureFormats for Version 1 and 2, see
1196 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1198 * This version has a different callback and does not enumerate FourCC
1199 * formats
1201 *****************************************************************************/
1202 static HRESULT WINAPI
1203 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1204 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1205 void *Arg)
1207 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1208 struct wined3d_display_mode mode;
1209 HRESULT hr;
1210 unsigned int i;
1212 static const enum wined3d_format_id FormatList[] =
1214 /* 32 bit */
1215 WINED3DFMT_B8G8R8A8_UNORM,
1216 WINED3DFMT_B8G8R8X8_UNORM,
1217 /* 24 bit */
1218 WINED3DFMT_B8G8R8_UNORM,
1219 /* 16 Bit */
1220 WINED3DFMT_B5G5R5A1_UNORM,
1221 WINED3DFMT_B4G4R4A4_UNORM,
1222 WINED3DFMT_B5G6R5_UNORM,
1223 WINED3DFMT_B5G5R5X1_UNORM,
1224 /* 8 Bit */
1225 WINED3DFMT_B2G3R3_UNORM,
1226 WINED3DFMT_P8_UINT,
1227 /* FOURCC codes - Not in this version*/
1230 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1232 if(!Callback)
1233 return DDERR_INVALIDPARAMS;
1235 wined3d_mutex_lock();
1237 memset(&mode, 0, sizeof(mode));
1238 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1239 if (FAILED(hr))
1241 wined3d_mutex_unlock();
1242 WARN("Cannot get the current adapter format\n");
1243 return hr;
1246 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1248 hr = wined3d_check_device_format(This->ddraw->wineD3D, 0, WINED3DDEVTYPE_HAL,
1249 mode.format_id, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1250 if (hr == D3D_OK)
1252 DDSURFACEDESC sdesc;
1254 memset(&sdesc, 0, sizeof(sdesc));
1255 sdesc.dwSize = sizeof(sdesc);
1256 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1257 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1258 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1259 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1261 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1262 hr = Callback(&sdesc, Arg);
1263 if(hr != DDENUMRET_OK)
1265 TRACE("Format enumeration cancelled by application\n");
1266 wined3d_mutex_unlock();
1267 return D3D_OK;
1271 TRACE("End of enumeration\n");
1272 wined3d_mutex_unlock();
1274 return D3D_OK;
1277 static HRESULT WINAPI IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1278 LPD3DENUMTEXTUREFORMATSCALLBACK Callback, void *Arg)
1280 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1282 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1284 return IDirect3DDevice2_EnumTextureFormats(&This->IDirect3DDevice2_iface, Callback, Arg);
1287 /*****************************************************************************
1288 * IDirect3DDevice::CreateMatrix
1290 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1291 * allocated for the handle.
1293 * Version 1 only
1295 * Params
1296 * D3DMatHandle: Address to return the handle at
1298 * Returns:
1299 * D3D_OK on success
1300 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1302 *****************************************************************************/
1303 static HRESULT WINAPI
1304 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1306 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1307 D3DMATRIX *Matrix;
1308 DWORD h;
1310 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1312 if(!D3DMatHandle)
1313 return DDERR_INVALIDPARAMS;
1315 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1316 if(!Matrix)
1318 ERR("Out of memory when allocating a D3DMATRIX\n");
1319 return DDERR_OUTOFMEMORY;
1322 wined3d_mutex_lock();
1324 h = ddraw_allocate_handle(&This->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1325 if (h == DDRAW_INVALID_HANDLE)
1327 ERR("Failed to allocate a matrix handle.\n");
1328 HeapFree(GetProcessHeap(), 0, Matrix);
1329 wined3d_mutex_unlock();
1330 return DDERR_OUTOFMEMORY;
1333 *D3DMatHandle = h + 1;
1335 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1337 wined3d_mutex_unlock();
1339 return D3D_OK;
1342 /*****************************************************************************
1343 * IDirect3DDevice::SetMatrix
1345 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1346 * allocated for the handle
1348 * Version 1 only
1350 * Params:
1351 * D3DMatHandle: Handle to set the matrix to
1352 * D3DMatrix: Matrix to set
1354 * Returns:
1355 * D3D_OK on success
1356 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1357 * to set is NULL
1359 *****************************************************************************/
1360 static HRESULT WINAPI
1361 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1362 D3DMATRIXHANDLE D3DMatHandle,
1363 D3DMATRIX *D3DMatrix)
1365 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1366 D3DMATRIX *m;
1368 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1370 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1372 wined3d_mutex_lock();
1374 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1375 if (!m)
1377 WARN("Invalid matrix handle.\n");
1378 wined3d_mutex_unlock();
1379 return DDERR_INVALIDPARAMS;
1382 if (TRACE_ON(ddraw))
1383 dump_D3DMATRIX(D3DMatrix);
1385 *m = *D3DMatrix;
1387 if (D3DMatHandle == This->world)
1388 wined3d_device_set_transform(This->wined3d_device,
1389 WINED3DTS_WORLDMATRIX(0), (struct wined3d_matrix *)D3DMatrix);
1391 if (D3DMatHandle == This->view)
1392 wined3d_device_set_transform(This->wined3d_device,
1393 WINED3DTS_VIEW, (struct wined3d_matrix *)D3DMatrix);
1395 if (D3DMatHandle == This->proj)
1396 wined3d_device_set_transform(This->wined3d_device,
1397 WINED3DTS_PROJECTION, (struct wined3d_matrix *)D3DMatrix);
1399 wined3d_mutex_unlock();
1401 return D3D_OK;
1404 /*****************************************************************************
1405 * IDirect3DDevice::GetMatrix
1407 * Returns the content of a D3DMATRIX handle
1409 * Version 1 only
1411 * Params:
1412 * D3DMatHandle: Matrix handle to read the content from
1413 * D3DMatrix: Address to store the content at
1415 * Returns:
1416 * D3D_OK on success
1417 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1419 *****************************************************************************/
1420 static HRESULT WINAPI
1421 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1422 D3DMATRIXHANDLE D3DMatHandle,
1423 D3DMATRIX *D3DMatrix)
1425 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1426 D3DMATRIX *m;
1428 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1430 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1432 wined3d_mutex_lock();
1434 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1435 if (!m)
1437 WARN("Invalid matrix handle.\n");
1438 wined3d_mutex_unlock();
1439 return DDERR_INVALIDPARAMS;
1442 *D3DMatrix = *m;
1444 wined3d_mutex_unlock();
1446 return D3D_OK;
1449 /*****************************************************************************
1450 * IDirect3DDevice::DeleteMatrix
1452 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1454 * Version 1 only
1456 * Params:
1457 * D3DMatHandle: Handle to destroy
1459 * Returns:
1460 * D3D_OK on success
1461 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1463 *****************************************************************************/
1464 static HRESULT WINAPI
1465 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1466 D3DMATRIXHANDLE D3DMatHandle)
1468 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1469 D3DMATRIX *m;
1471 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1473 wined3d_mutex_lock();
1475 m = ddraw_free_handle(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1476 if (!m)
1478 WARN("Invalid matrix handle.\n");
1479 wined3d_mutex_unlock();
1480 return DDERR_INVALIDPARAMS;
1483 wined3d_mutex_unlock();
1485 HeapFree(GetProcessHeap(), 0, m);
1487 return D3D_OK;
1490 /*****************************************************************************
1491 * IDirect3DDevice7::BeginScene
1493 * This method must be called before any rendering is performed.
1494 * IDirect3DDevice::EndScene has to be called after the scene is complete
1496 * Version 1, 2, 3 and 7
1498 * Returns:
1499 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1500 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1501 * started scene).
1503 *****************************************************************************/
1504 static HRESULT
1505 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1507 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1508 HRESULT hr;
1510 TRACE("iface %p.\n", iface);
1512 wined3d_mutex_lock();
1513 hr = wined3d_device_begin_scene(This->wined3d_device);
1514 wined3d_mutex_unlock();
1516 if(hr == WINED3D_OK) return D3D_OK;
1517 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1520 static HRESULT WINAPI
1521 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1523 return IDirect3DDeviceImpl_7_BeginScene(iface);
1526 static HRESULT WINAPI
1527 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1529 HRESULT hr;
1530 WORD old_fpucw;
1532 old_fpucw = d3d_fpu_setup();
1533 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1534 set_fpu_control_word(old_fpucw);
1536 return hr;
1539 static HRESULT WINAPI IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1541 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1542 TRACE("iface %p.\n", iface);
1544 return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
1547 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1549 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1550 TRACE("iface %p.\n", iface);
1552 return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
1555 static HRESULT WINAPI IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1557 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1558 TRACE("iface %p.\n", iface);
1560 return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
1563 /*****************************************************************************
1564 * IDirect3DDevice7::EndScene
1566 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1567 * This method must be called after rendering is finished.
1569 * Version 1, 2, 3 and 7
1571 * Returns:
1572 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1573 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1574 * that only if the scene was already ended.
1576 *****************************************************************************/
1577 static HRESULT
1578 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1580 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1581 HRESULT hr;
1583 TRACE("iface %p.\n", iface);
1585 wined3d_mutex_lock();
1586 hr = wined3d_device_end_scene(This->wined3d_device);
1587 wined3d_mutex_unlock();
1589 if(hr == WINED3D_OK) return D3D_OK;
1590 else return D3DERR_SCENE_NOT_IN_SCENE;
1593 static HRESULT WINAPI DECLSPEC_HOTPATCH
1594 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1596 return IDirect3DDeviceImpl_7_EndScene(iface);
1599 static HRESULT WINAPI DECLSPEC_HOTPATCH
1600 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1602 HRESULT hr;
1603 WORD old_fpucw;
1605 old_fpucw = d3d_fpu_setup();
1606 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1607 set_fpu_control_word(old_fpucw);
1609 return hr;
1612 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1614 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1615 TRACE("iface %p.\n", iface);
1617 return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
1620 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1622 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1623 TRACE("iface %p.\n", iface);
1625 return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
1628 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1630 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1631 TRACE("iface %p.\n", iface);
1633 return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
1636 /*****************************************************************************
1637 * IDirect3DDevice7::GetDirect3D
1639 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1640 * this device.
1642 * Params:
1643 * Direct3D7: Address to store the interface pointer at
1645 * Returns:
1646 * D3D_OK on success
1647 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1649 *****************************************************************************/
1650 static HRESULT WINAPI
1651 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1652 IDirect3D7 **Direct3D7)
1654 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1656 TRACE("iface %p, d3d %p.\n", iface, Direct3D7);
1658 if(!Direct3D7)
1659 return DDERR_INVALIDPARAMS;
1661 *Direct3D7 = &This->ddraw->IDirect3D7_iface;
1662 IDirect3D7_AddRef(*Direct3D7);
1664 TRACE(" returning interface %p\n", *Direct3D7);
1665 return D3D_OK;
1668 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1669 IDirect3D3 **Direct3D3)
1671 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1673 TRACE("iface %p, d3d %p.\n", iface, Direct3D3);
1675 if(!Direct3D3)
1676 return DDERR_INVALIDPARAMS;
1678 IDirect3D3_AddRef(&This->ddraw->IDirect3D3_iface);
1679 *Direct3D3 = &This->ddraw->IDirect3D3_iface;
1680 TRACE(" returning interface %p\n", *Direct3D3);
1681 return D3D_OK;
1684 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1685 IDirect3D2 **Direct3D2)
1687 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1689 TRACE("iface %p, d3d %p.\n", iface, Direct3D2);
1691 if(!Direct3D2)
1692 return DDERR_INVALIDPARAMS;
1694 IDirect3D2_AddRef(&This->ddraw->IDirect3D2_iface);
1695 *Direct3D2 = &This->ddraw->IDirect3D2_iface;
1696 TRACE(" returning interface %p\n", *Direct3D2);
1697 return D3D_OK;
1700 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1701 IDirect3D **Direct3D)
1703 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1705 TRACE("iface %p, d3d %p.\n", iface, Direct3D);
1707 if(!Direct3D)
1708 return DDERR_INVALIDPARAMS;
1710 IDirect3D_AddRef(&This->ddraw->IDirect3D_iface);
1711 *Direct3D = &This->ddraw->IDirect3D_iface;
1712 TRACE(" returning interface %p\n", *Direct3D);
1713 return D3D_OK;
1716 /*****************************************************************************
1717 * IDirect3DDevice3::SetCurrentViewport
1719 * Sets a Direct3DViewport as the current viewport.
1720 * For the thunks note that all viewport interface versions are equal
1722 * Params:
1723 * Direct3DViewport3: The viewport to set
1725 * Version 2 and 3
1727 * Returns:
1728 * D3D_OK on success
1729 * (Is a NULL viewport valid?)
1731 *****************************************************************************/
1732 static HRESULT WINAPI
1733 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1734 IDirect3DViewport3 *Direct3DViewport3)
1736 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1737 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(Direct3DViewport3);
1739 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1741 wined3d_mutex_lock();
1742 /* Do nothing if the specified viewport is the same as the current one */
1743 if (This->current_viewport == vp )
1745 wined3d_mutex_unlock();
1746 return D3D_OK;
1749 if (vp->active_device != This)
1751 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1752 wined3d_mutex_unlock();
1753 return DDERR_INVALIDPARAMS;
1756 /* Release previous viewport and AddRef the new one */
1757 if (This->current_viewport)
1759 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1760 &This->current_viewport->IDirect3DViewport3_iface);
1761 IDirect3DViewport3_Release(&This->current_viewport->IDirect3DViewport3_iface);
1763 IDirect3DViewport3_AddRef(Direct3DViewport3);
1765 /* Set this viewport as the current viewport */
1766 This->current_viewport = vp;
1768 /* Activate this viewport */
1769 viewport_activate(This->current_viewport, FALSE);
1771 wined3d_mutex_unlock();
1773 return D3D_OK;
1776 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1777 IDirect3DViewport2 *Direct3DViewport2)
1779 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1780 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
1782 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1784 return IDirect3DDevice3_SetCurrentViewport(&This->IDirect3DDevice3_iface,
1785 &vp->IDirect3DViewport3_iface);
1788 /*****************************************************************************
1789 * IDirect3DDevice3::GetCurrentViewport
1791 * Returns the currently active viewport.
1793 * Version 2 and 3
1795 * Params:
1796 * Direct3DViewport3: Address to return the interface pointer at
1798 * Returns:
1799 * D3D_OK on success
1800 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1802 *****************************************************************************/
1803 static HRESULT WINAPI
1804 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1805 IDirect3DViewport3 **Direct3DViewport3)
1807 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1809 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1811 if(!Direct3DViewport3)
1812 return DDERR_INVALIDPARAMS;
1814 wined3d_mutex_lock();
1815 *Direct3DViewport3 = &This->current_viewport->IDirect3DViewport3_iface;
1817 /* AddRef the returned viewport */
1818 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1820 TRACE(" returning interface %p\n", *Direct3DViewport3);
1822 wined3d_mutex_unlock();
1824 return D3D_OK;
1827 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1828 IDirect3DViewport2 **Direct3DViewport2)
1830 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1831 HRESULT hr;
1833 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1835 hr = IDirect3DDevice3_GetCurrentViewport(&This->IDirect3DDevice3_iface,
1836 (IDirect3DViewport3 **)Direct3DViewport2);
1837 if(hr != D3D_OK) return hr;
1838 return D3D_OK;
1841 /*****************************************************************************
1842 * IDirect3DDevice7::SetRenderTarget
1844 * Sets the render target for the Direct3DDevice.
1845 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1846 * IDirectDrawSurface3 == IDirectDrawSurface
1848 * Version 2, 3 and 7
1850 * Params:
1851 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1852 * render target
1853 * Flags: Some flags
1855 * Returns:
1856 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1858 *****************************************************************************/
1859 static HRESULT d3d_device_set_render_target(IDirect3DDeviceImpl *This, IDirectDrawSurfaceImpl *Target)
1861 HRESULT hr;
1863 wined3d_mutex_lock();
1865 if(This->target == Target)
1867 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1868 wined3d_mutex_unlock();
1869 return D3D_OK;
1871 This->target = Target;
1872 hr = wined3d_device_set_render_target(This->wined3d_device, 0,
1873 Target ? Target->wined3d_surface : NULL, FALSE);
1874 if(hr != D3D_OK)
1876 wined3d_mutex_unlock();
1877 return hr;
1879 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1881 wined3d_mutex_unlock();
1883 return D3D_OK;
1886 static HRESULT
1887 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1888 IDirectDrawSurface7 *NewTarget,
1889 DWORD Flags)
1891 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1892 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface7(NewTarget);
1894 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, Flags);
1895 /* Flags: Not used */
1897 IDirectDrawSurface7_AddRef(NewTarget);
1898 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
1899 return d3d_device_set_render_target(This, Target);
1902 static HRESULT WINAPI
1903 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1904 IDirectDrawSurface7 *NewTarget,
1905 DWORD Flags)
1907 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1910 static HRESULT WINAPI
1911 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1912 IDirectDrawSurface7 *NewTarget,
1913 DWORD Flags)
1915 HRESULT hr;
1916 WORD old_fpucw;
1918 old_fpucw = d3d_fpu_setup();
1919 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1920 set_fpu_control_word(old_fpucw);
1922 return hr;
1925 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
1926 IDirectDrawSurface4 *NewRenderTarget, DWORD Flags)
1928 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1929 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface4(NewRenderTarget);
1931 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1933 IDirectDrawSurface4_AddRef(NewRenderTarget);
1934 IDirectDrawSurface4_Release(&This->target->IDirectDrawSurface4_iface);
1935 return d3d_device_set_render_target(This, Target);
1938 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
1939 IDirectDrawSurface *NewRenderTarget, DWORD Flags)
1941 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1942 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface(NewRenderTarget);
1944 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1946 IDirectDrawSurface_AddRef(NewRenderTarget);
1947 IDirectDrawSurface_Release(&This->target->IDirectDrawSurface_iface);
1948 return d3d_device_set_render_target(This, Target);
1951 /*****************************************************************************
1952 * IDirect3DDevice7::GetRenderTarget
1954 * Returns the current render target.
1955 * This is handled locally, because the WineD3D render target's parent
1956 * is an IParent
1958 * Version 2, 3 and 7
1960 * Params:
1961 * RenderTarget: Address to store the surface interface pointer
1963 * Returns:
1964 * D3D_OK on success
1965 * DDERR_INVALIDPARAMS if RenderTarget == NULL
1967 *****************************************************************************/
1968 static HRESULT WINAPI
1969 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
1970 IDirectDrawSurface7 **RenderTarget)
1972 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1974 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1976 if(!RenderTarget)
1977 return DDERR_INVALIDPARAMS;
1979 wined3d_mutex_lock();
1980 *RenderTarget = &This->target->IDirectDrawSurface7_iface;
1981 IDirectDrawSurface7_AddRef(*RenderTarget);
1982 wined3d_mutex_unlock();
1984 return D3D_OK;
1987 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
1988 IDirectDrawSurface4 **RenderTarget)
1990 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1991 IDirectDrawSurface7 *RenderTarget7;
1992 IDirectDrawSurfaceImpl *RenderTargetImpl;
1993 HRESULT hr;
1995 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1997 if(!RenderTarget)
1998 return DDERR_INVALIDPARAMS;
2000 hr = IDirect3DDevice7_GetRenderTarget(&This->IDirect3DDevice7_iface, &RenderTarget7);
2001 if(hr != D3D_OK) return hr;
2002 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2003 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface;
2004 IDirectDrawSurface4_AddRef(*RenderTarget);
2005 IDirectDrawSurface7_Release(RenderTarget7);
2006 return D3D_OK;
2009 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
2010 IDirectDrawSurface **RenderTarget)
2012 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2013 IDirectDrawSurface7 *RenderTarget7;
2014 IDirectDrawSurfaceImpl *RenderTargetImpl;
2015 HRESULT hr;
2017 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2019 if(!RenderTarget)
2020 return DDERR_INVALIDPARAMS;
2022 hr = IDirect3DDevice7_GetRenderTarget(&This->IDirect3DDevice7_iface, &RenderTarget7);
2023 if(hr != D3D_OK) return hr;
2024 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2025 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
2026 IDirectDrawSurface_AddRef(*RenderTarget);
2027 IDirectDrawSurface7_Release(RenderTarget7);
2028 return D3D_OK;
2031 /*****************************************************************************
2032 * IDirect3DDevice3::Begin
2034 * Begins a description block of vertices. This is similar to glBegin()
2035 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2036 * described with IDirect3DDevice::Vertex are drawn.
2038 * Version 2 and 3
2040 * Params:
2041 * PrimitiveType: The type of primitives to draw
2042 * VertexTypeDesc: A flexible vertex format description of the vertices
2043 * Flags: Some flags..
2045 * Returns:
2046 * D3D_OK on success
2048 *****************************************************************************/
2049 static HRESULT WINAPI
2050 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2051 D3DPRIMITIVETYPE PrimitiveType,
2052 DWORD VertexTypeDesc,
2053 DWORD Flags)
2055 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2057 TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
2058 iface, PrimitiveType, VertexTypeDesc, Flags);
2060 wined3d_mutex_lock();
2061 This->primitive_type = PrimitiveType;
2062 This->vertex_type = VertexTypeDesc;
2063 This->render_flags = Flags;
2064 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2065 This->nb_vertices = 0;
2066 wined3d_mutex_unlock();
2068 return D3D_OK;
2071 static HRESULT WINAPI IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface, D3DPRIMITIVETYPE d3dpt,
2072 D3DVERTEXTYPE dwVertexTypeDesc, DWORD dwFlags)
2074 DWORD FVF;
2075 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2077 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2078 iface, d3dpt, dwVertexTypeDesc, dwFlags);
2080 switch(dwVertexTypeDesc)
2082 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2083 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2084 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2085 default:
2086 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2087 return DDERR_INVALIDPARAMS; /* Should never happen */
2090 return IDirect3DDevice3_Begin(&This->IDirect3DDevice3_iface, d3dpt, FVF, dwFlags);
2093 /*****************************************************************************
2094 * IDirect3DDevice3::BeginIndexed
2096 * Draws primitives based on vertices in a vertex array which are specified
2097 * by indices.
2099 * Version 2 and 3
2101 * Params:
2102 * PrimitiveType: Primitive type to draw
2103 * VertexType: A FVF description of the vertex format
2104 * Vertices: pointer to an array containing the vertices
2105 * NumVertices: The number of vertices in the vertex array
2106 * Flags: Some flags ...
2108 * Returns:
2109 * D3D_OK, because it's a stub
2111 *****************************************************************************/
2112 static HRESULT WINAPI
2113 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2114 D3DPRIMITIVETYPE PrimitiveType,
2115 DWORD VertexType,
2116 void *Vertices,
2117 DWORD NumVertices,
2118 DWORD Flags)
2120 FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2121 iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2123 return D3D_OK;
2127 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2128 D3DPRIMITIVETYPE d3dptPrimitiveType, D3DVERTEXTYPE d3dvtVertexType,
2129 void *lpvVertices, DWORD dwNumVertices, DWORD dwFlags)
2131 DWORD FVF;
2132 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2134 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2135 iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2137 switch(d3dvtVertexType)
2139 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2140 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2141 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2142 default:
2143 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2144 return DDERR_INVALIDPARAMS; /* Should never happen */
2147 return IDirect3DDevice3_BeginIndexed(&This->IDirect3DDevice3_iface,
2148 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2151 /*****************************************************************************
2152 * IDirect3DDevice3::Vertex
2154 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2155 * drawn vertices in a vertex buffer. If the buffer is too small, its
2156 * size is increased.
2158 * Version 2 and 3
2160 * Params:
2161 * Vertex: Pointer to the vertex
2163 * Returns:
2164 * D3D_OK, on success
2165 * DDERR_INVALIDPARAMS if Vertex is NULL
2167 *****************************************************************************/
2168 static HRESULT WINAPI
2169 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2170 void *Vertex)
2172 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2174 TRACE("iface %p, vertex %p.\n", iface, Vertex);
2176 if(!Vertex)
2177 return DDERR_INVALIDPARAMS;
2179 wined3d_mutex_lock();
2180 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2182 BYTE *old_buffer;
2183 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2184 old_buffer = This->vertex_buffer;
2185 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2186 if (old_buffer)
2188 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2189 HeapFree(GetProcessHeap(), 0, old_buffer);
2193 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2194 wined3d_mutex_unlock();
2196 return D3D_OK;
2199 static HRESULT WINAPI IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface, void *lpVertexType)
2201 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2203 TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
2205 return IDirect3DDevice3_Vertex(&This->IDirect3DDevice3_iface, lpVertexType);
2208 /*****************************************************************************
2209 * IDirect3DDevice3::Index
2211 * Specifies an index to a vertex to be drawn. The vertex array has to
2212 * be specified with BeginIndexed first.
2214 * Parameters:
2215 * VertexIndex: The index of the vertex to draw
2217 * Returns:
2218 * D3D_OK because it's a stub
2220 *****************************************************************************/
2221 static HRESULT WINAPI
2222 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2223 WORD VertexIndex)
2225 FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
2227 return D3D_OK;
2230 static HRESULT WINAPI IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface, WORD wVertexIndex)
2232 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2234 TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
2236 return IDirect3DDevice3_Index(&This->IDirect3DDevice3_iface, wVertexIndex);
2239 /*****************************************************************************
2240 * IDirect3DDevice3::End
2242 * Ends a draw begun with IDirect3DDevice3::Begin or
2243 * IDirect3DDevice::BeginIndexed. The vertices specified with
2244 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2245 * the IDirect3DDevice7::DrawPrimitive method. So far only
2246 * non-indexed mode is supported
2248 * Version 2 and 3
2250 * Params:
2251 * Flags: Some flags, as usual. Don't know which are defined
2253 * Returns:
2254 * The return value of IDirect3DDevice7::DrawPrimitive
2256 *****************************************************************************/
2257 static HRESULT WINAPI
2258 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2259 DWORD Flags)
2261 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2263 TRACE("iface %p, flags %#x.\n", iface, Flags);
2265 return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface, This->primitive_type,
2266 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2269 static HRESULT WINAPI IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface, DWORD dwFlags)
2271 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2273 TRACE("iface %p, flags %#x.\n", iface, dwFlags);
2275 return IDirect3DDevice3_End(&This->IDirect3DDevice3_iface, dwFlags);
2278 /*****************************************************************************
2279 * IDirect3DDevice7::GetRenderState
2281 * Returns the value of a render state. The possible render states are
2282 * defined in include/d3dtypes.h
2284 * Version 2, 3 and 7
2286 * Params:
2287 * RenderStateType: Render state to return the current setting of
2288 * Value: Address to store the value at
2290 * Returns:
2291 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2292 * DDERR_INVALIDPARAMS if Value == NULL
2294 *****************************************************************************/
2295 static HRESULT IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2296 D3DRENDERSTATETYPE RenderStateType, DWORD *Value)
2298 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
2299 HRESULT hr;
2301 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2303 if(!Value)
2304 return DDERR_INVALIDPARAMS;
2306 wined3d_mutex_lock();
2307 switch(RenderStateType)
2309 case D3DRENDERSTATE_TEXTUREMAG:
2311 WINED3DTEXTUREFILTERTYPE tex_mag;
2313 hr = wined3d_device_get_sampler_state(This->wined3d_device, 0, WINED3DSAMP_MAGFILTER, &tex_mag);
2315 switch (tex_mag)
2317 case WINED3DTEXF_POINT:
2318 *Value = D3DFILTER_NEAREST;
2319 break;
2320 case WINED3DTEXF_LINEAR:
2321 *Value = D3DFILTER_LINEAR;
2322 break;
2323 default:
2324 ERR("Unhandled texture mag %d !\n",tex_mag);
2325 *Value = 0;
2327 break;
2330 case D3DRENDERSTATE_TEXTUREMIN:
2332 WINED3DTEXTUREFILTERTYPE tex_min;
2333 WINED3DTEXTUREFILTERTYPE tex_mip;
2335 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2336 0, WINED3DSAMP_MINFILTER, &tex_min);
2337 if (FAILED(hr))
2339 wined3d_mutex_unlock();
2340 return hr;
2342 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2343 0, WINED3DSAMP_MIPFILTER, &tex_mip);
2345 switch (tex_min)
2347 case WINED3DTEXF_POINT:
2348 switch (tex_mip)
2350 case WINED3DTEXF_NONE:
2351 *Value = D3DFILTER_NEAREST;
2352 break;
2353 case WINED3DTEXF_POINT:
2354 *Value = D3DFILTER_MIPNEAREST;
2355 break;
2356 case WINED3DTEXF_LINEAR:
2357 *Value = D3DFILTER_LINEARMIPNEAREST;
2358 break;
2359 default:
2360 ERR("Unhandled mip filter %#x.\n", tex_mip);
2361 *Value = D3DFILTER_NEAREST;
2362 break;
2364 break;
2365 case WINED3DTEXF_LINEAR:
2366 switch (tex_mip)
2368 case WINED3DTEXF_NONE:
2369 *Value = D3DFILTER_LINEAR;
2370 break;
2371 case WINED3DTEXF_POINT:
2372 *Value = D3DFILTER_MIPLINEAR;
2373 break;
2374 case WINED3DTEXF_LINEAR:
2375 *Value = D3DFILTER_LINEARMIPLINEAR;
2376 break;
2377 default:
2378 ERR("Unhandled mip filter %#x.\n", tex_mip);
2379 *Value = D3DFILTER_LINEAR;
2380 break;
2382 break;
2383 default:
2384 ERR("Unhandled texture min filter %#x.\n",tex_min);
2385 *Value = D3DFILTER_NEAREST;
2386 break;
2388 break;
2391 case D3DRENDERSTATE_TEXTUREADDRESS:
2392 case D3DRENDERSTATE_TEXTUREADDRESSU:
2393 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2394 0, WINED3DSAMP_ADDRESSU, Value);
2395 break;
2396 case D3DRENDERSTATE_TEXTUREADDRESSV:
2397 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2398 0, WINED3DSAMP_ADDRESSV, Value);
2399 break;
2401 case D3DRENDERSTATE_BORDERCOLOR:
2402 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2403 hr = E_NOTIMPL;
2404 break;
2406 case D3DRENDERSTATE_TEXTUREHANDLE:
2407 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2408 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2409 hr = DDERR_INVALIDPARAMS;
2410 break;
2412 case D3DRENDERSTATE_ZBIAS:
2413 hr = wined3d_device_get_render_state(This->wined3d_device, WINED3DRS_DEPTHBIAS, Value);
2414 break;
2416 default:
2417 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2418 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2420 FIXME("Unhandled stipple pattern render state (%#x).\n",
2421 RenderStateType);
2422 hr = E_NOTIMPL;
2423 break;
2425 hr = wined3d_device_get_render_state(This->wined3d_device, RenderStateType, Value);
2427 wined3d_mutex_unlock();
2429 return hr;
2432 static HRESULT WINAPI
2433 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2434 D3DRENDERSTATETYPE RenderStateType,
2435 DWORD *Value)
2437 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2440 static HRESULT WINAPI
2441 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2442 D3DRENDERSTATETYPE RenderStateType,
2443 DWORD *Value)
2445 HRESULT hr;
2446 WORD old_fpucw;
2448 old_fpucw = d3d_fpu_setup();
2449 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2450 set_fpu_control_word(old_fpucw);
2452 return hr;
2455 static HRESULT WINAPI
2456 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2457 D3DRENDERSTATETYPE dwRenderStateType,
2458 DWORD *lpdwRenderState)
2460 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2461 HRESULT hr;
2463 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2465 switch(dwRenderStateType)
2467 case D3DRENDERSTATE_TEXTUREHANDLE:
2469 /* This state is wrapped to SetTexture in SetRenderState, so
2470 * it has to be wrapped to GetTexture here. */
2471 struct wined3d_texture *tex = NULL;
2472 *lpdwRenderState = 0;
2474 wined3d_mutex_lock();
2475 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2476 if (SUCCEEDED(hr) && tex)
2478 /* The parent of the texture is the IDirectDrawSurface7
2479 * interface of the ddraw surface. */
2480 IDirectDrawSurfaceImpl *parent = wined3d_texture_get_parent(tex);
2481 if (parent) *lpdwRenderState = parent->Handle;
2482 wined3d_texture_decref(tex);
2484 wined3d_mutex_unlock();
2486 return hr;
2489 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2491 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2492 the mapping to get the value. */
2493 DWORD colorop, colorarg1, colorarg2;
2494 DWORD alphaop, alphaarg1, alphaarg2;
2496 wined3d_mutex_lock();
2498 This->legacyTextureBlending = TRUE;
2500 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLOROP, &colorop);
2501 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLORARG1, &colorarg1);
2502 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLORARG2, &colorarg2);
2503 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, &alphaop);
2504 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2505 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2507 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2508 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2510 *lpdwRenderState = D3DTBLEND_DECAL;
2512 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2513 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2515 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2517 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2518 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2520 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2522 else
2524 struct wined3d_texture *tex = NULL;
2525 HRESULT hr;
2526 BOOL tex_alpha = FALSE;
2527 DDPIXELFORMAT ddfmt;
2529 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2531 if(hr == WINED3D_OK && tex)
2533 struct wined3d_resource *sub_resource;
2535 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2537 struct wined3d_resource_desc desc;
2539 wined3d_resource_get_desc(sub_resource, &desc);
2540 ddfmt.dwSize = sizeof(ddfmt);
2541 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2542 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2545 wined3d_texture_decref(tex);
2548 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2549 alphaop == (tex_alpha ? WINED3DTOP_SELECTARG1 : WINED3DTOP_SELECTARG2) &&
2550 alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2552 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2555 *lpdwRenderState = D3DTBLEND_MODULATE;
2558 wined3d_mutex_unlock();
2560 return D3D_OK;
2563 default:
2564 return IDirect3DDevice7_GetRenderState(&This->IDirect3DDevice7_iface, dwRenderStateType, lpdwRenderState);
2568 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2569 D3DRENDERSTATETYPE dwRenderStateType, DWORD *lpdwRenderState)
2571 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2573 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2575 return IDirect3DDevice3_GetRenderState(&This->IDirect3DDevice3_iface,
2576 dwRenderStateType, lpdwRenderState);
2579 /*****************************************************************************
2580 * IDirect3DDevice7::SetRenderState
2582 * Sets a render state. The possible render states are defined in
2583 * include/d3dtypes.h
2585 * Version 2, 3 and 7
2587 * Params:
2588 * RenderStateType: State to set
2589 * Value: Value to assign to that state
2591 * Returns:
2592 * D3D_OK on success,
2593 * for details see IWineD3DDevice::SetRenderState
2595 *****************************************************************************/
2596 static HRESULT
2597 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2598 D3DRENDERSTATETYPE RenderStateType,
2599 DWORD Value)
2601 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
2602 HRESULT hr;
2604 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2606 wined3d_mutex_lock();
2607 /* Some render states need special care */
2608 switch(RenderStateType)
2611 * The ddraw texture filter mapping works like this:
2612 * D3DFILTER_NEAREST Point min/mag, no mip
2613 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2614 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2616 * D3DFILTER_LINEAR Linear min/mag, no mip
2617 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2618 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2620 * This is the opposite of the GL naming convention,
2621 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2623 case D3DRENDERSTATE_TEXTUREMAG:
2625 WINED3DTEXTUREFILTERTYPE tex_mag;
2627 switch (Value)
2629 case D3DFILTER_NEAREST:
2630 case D3DFILTER_MIPNEAREST:
2631 case D3DFILTER_LINEARMIPNEAREST:
2632 tex_mag = WINED3DTEXF_POINT;
2633 break;
2634 case D3DFILTER_LINEAR:
2635 case D3DFILTER_MIPLINEAR:
2636 case D3DFILTER_LINEARMIPLINEAR:
2637 tex_mag = WINED3DTEXF_LINEAR;
2638 break;
2639 default:
2640 tex_mag = WINED3DTEXF_POINT;
2641 ERR("Unhandled texture mag %d !\n",Value);
2642 break;
2645 hr = wined3d_device_set_sampler_state(This->wined3d_device, 0, WINED3DSAMP_MAGFILTER, tex_mag);
2646 break;
2649 case D3DRENDERSTATE_TEXTUREMIN:
2651 WINED3DTEXTUREFILTERTYPE tex_min;
2652 WINED3DTEXTUREFILTERTYPE tex_mip;
2654 switch ((D3DTEXTUREFILTER) Value)
2656 case D3DFILTER_NEAREST:
2657 tex_min = WINED3DTEXF_POINT;
2658 tex_mip = WINED3DTEXF_NONE;
2659 break;
2660 case D3DFILTER_LINEAR:
2661 tex_min = WINED3DTEXF_LINEAR;
2662 tex_mip = WINED3DTEXF_NONE;
2663 break;
2664 case D3DFILTER_MIPNEAREST:
2665 tex_min = WINED3DTEXF_POINT;
2666 tex_mip = WINED3DTEXF_POINT;
2667 break;
2668 case D3DFILTER_MIPLINEAR:
2669 tex_min = WINED3DTEXF_LINEAR;
2670 tex_mip = WINED3DTEXF_POINT;
2671 break;
2672 case D3DFILTER_LINEARMIPNEAREST:
2673 tex_min = WINED3DTEXF_POINT;
2674 tex_mip = WINED3DTEXF_LINEAR;
2675 break;
2676 case D3DFILTER_LINEARMIPLINEAR:
2677 tex_min = WINED3DTEXF_LINEAR;
2678 tex_mip = WINED3DTEXF_LINEAR;
2679 break;
2681 default:
2682 ERR("Unhandled texture min %d !\n",Value);
2683 tex_min = WINED3DTEXF_POINT;
2684 tex_mip = WINED3DTEXF_NONE;
2685 break;
2688 wined3d_device_set_sampler_state(This->wined3d_device,
2689 0, WINED3DSAMP_MIPFILTER, tex_mip);
2690 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2691 0, WINED3DSAMP_MINFILTER, tex_min);
2692 break;
2695 case D3DRENDERSTATE_TEXTUREADDRESS:
2696 wined3d_device_set_sampler_state(This->wined3d_device,
2697 0, WINED3DSAMP_ADDRESSV, Value);
2698 /* Drop through */
2699 case D3DRENDERSTATE_TEXTUREADDRESSU:
2700 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2701 0, WINED3DSAMP_ADDRESSU, Value);
2702 break;
2703 case D3DRENDERSTATE_TEXTUREADDRESSV:
2704 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2705 0, WINED3DSAMP_ADDRESSV, Value);
2706 break;
2708 case D3DRENDERSTATE_BORDERCOLOR:
2709 /* This should probably just forward to the corresponding sampler
2710 * state. Needs tests. */
2711 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2712 hr = E_NOTIMPL;
2713 break;
2715 case D3DRENDERSTATE_TEXTUREHANDLE:
2716 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2717 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2718 hr = DDERR_INVALIDPARAMS;
2719 break;
2721 case D3DRENDERSTATE_ZBIAS:
2722 hr = wined3d_device_set_render_state(This->wined3d_device, WINED3DRS_DEPTHBIAS, Value);
2723 break;
2725 default:
2726 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2727 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2729 FIXME("Unhandled stipple pattern render state (%#x).\n",
2730 RenderStateType);
2731 hr = E_NOTIMPL;
2732 break;
2735 hr = wined3d_device_set_render_state(This->wined3d_device, RenderStateType, Value);
2736 break;
2738 wined3d_mutex_unlock();
2740 return hr;
2743 static HRESULT WINAPI
2744 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2745 D3DRENDERSTATETYPE RenderStateType,
2746 DWORD Value)
2748 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2751 static HRESULT WINAPI
2752 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2753 D3DRENDERSTATETYPE RenderStateType,
2754 DWORD Value)
2756 HRESULT hr;
2757 WORD old_fpucw;
2759 old_fpucw = d3d_fpu_setup();
2760 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2761 set_fpu_control_word(old_fpucw);
2763 return hr;
2766 static HRESULT WINAPI
2767 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2768 D3DRENDERSTATETYPE RenderStateType,
2769 DWORD Value)
2771 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2772 for this state can be directly mapped to texture stage colorop and alphaop, but
2773 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2774 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2775 alphaarg when needed.
2777 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2779 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2780 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2781 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2782 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2783 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2784 in device - TRUE if the app is using TEXTUREMAPBLEND.
2786 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2787 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2788 unless some broken game will be found that cares. */
2790 HRESULT hr;
2791 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2793 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2795 wined3d_mutex_lock();
2797 switch(RenderStateType)
2799 case D3DRENDERSTATE_TEXTUREHANDLE:
2801 IDirectDrawSurfaceImpl *surf;
2803 if(Value == 0)
2805 hr = wined3d_device_set_texture(This->wined3d_device, 0, NULL);
2806 break;
2809 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2810 if (!surf)
2812 WARN("Invalid texture handle.\n");
2813 hr = DDERR_INVALIDPARAMS;
2814 break;
2817 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2818 break;
2821 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2823 This->legacyTextureBlending = TRUE;
2825 switch ( (D3DTEXTUREBLEND) Value)
2827 case D3DTBLEND_MODULATE:
2829 struct wined3d_texture *tex = NULL;
2830 BOOL tex_alpha = FALSE;
2831 DDPIXELFORMAT ddfmt;
2833 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2835 if(hr == WINED3D_OK && tex)
2837 struct wined3d_resource *sub_resource;
2839 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2841 struct wined3d_resource_desc desc;
2843 wined3d_resource_get_desc(sub_resource, &desc);
2844 ddfmt.dwSize = sizeof(ddfmt);
2845 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2846 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2849 wined3d_texture_decref(tex);
2852 if (tex_alpha)
2853 wined3d_device_set_texture_stage_state(This->wined3d_device,
2854 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2855 else
2856 wined3d_device_set_texture_stage_state(This->wined3d_device,
2857 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2858 wined3d_device_set_texture_stage_state(This->wined3d_device,
2859 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2860 wined3d_device_set_texture_stage_state(This->wined3d_device,
2861 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2862 wined3d_device_set_texture_stage_state(This->wined3d_device,
2863 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2864 wined3d_device_set_texture_stage_state(This->wined3d_device,
2865 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2866 wined3d_device_set_texture_stage_state(This->wined3d_device,
2867 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2868 break;
2871 case D3DTBLEND_ADD:
2872 wined3d_device_set_texture_stage_state(This->wined3d_device,
2873 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2874 wined3d_device_set_texture_stage_state(This->wined3d_device,
2875 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2876 wined3d_device_set_texture_stage_state(This->wined3d_device,
2877 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2878 wined3d_device_set_texture_stage_state(This->wined3d_device,
2879 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2880 wined3d_device_set_texture_stage_state(This->wined3d_device,
2881 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2882 break;
2884 case D3DTBLEND_MODULATEALPHA:
2885 wined3d_device_set_texture_stage_state(This->wined3d_device,
2886 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2887 wined3d_device_set_texture_stage_state(This->wined3d_device,
2888 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2889 wined3d_device_set_texture_stage_state(This->wined3d_device,
2890 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2891 wined3d_device_set_texture_stage_state(This->wined3d_device,
2892 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2893 wined3d_device_set_texture_stage_state(This->wined3d_device,
2894 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2895 wined3d_device_set_texture_stage_state(This->wined3d_device,
2896 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2897 break;
2899 case D3DTBLEND_COPY:
2900 case D3DTBLEND_DECAL:
2901 wined3d_device_set_texture_stage_state(This->wined3d_device,
2902 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2903 wined3d_device_set_texture_stage_state(This->wined3d_device,
2904 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2905 wined3d_device_set_texture_stage_state(This->wined3d_device,
2906 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2907 wined3d_device_set_texture_stage_state(This->wined3d_device,
2908 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2909 break;
2911 case D3DTBLEND_DECALALPHA:
2912 wined3d_device_set_texture_stage_state(This->wined3d_device,
2913 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2914 wined3d_device_set_texture_stage_state(This->wined3d_device,
2915 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2916 wined3d_device_set_texture_stage_state(This->wined3d_device,
2917 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2918 wined3d_device_set_texture_stage_state(This->wined3d_device,
2919 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2920 wined3d_device_set_texture_stage_state(This->wined3d_device,
2921 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2922 break;
2924 default:
2925 ERR("Unhandled texture environment %d !\n",Value);
2928 hr = D3D_OK;
2929 break;
2932 default:
2933 hr = IDirect3DDevice7_SetRenderState(&This->IDirect3DDevice7_iface, RenderStateType, Value);
2934 break;
2936 wined3d_mutex_unlock();
2938 return hr;
2941 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2942 D3DRENDERSTATETYPE RenderStateType, DWORD Value)
2944 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2946 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2948 return IDirect3DDevice3_SetRenderState(&This->IDirect3DDevice3_iface, RenderStateType, Value);
2951 /*****************************************************************************
2952 * Direct3DDevice3::SetLightState
2954 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2955 * light states are forwarded to Direct3DDevice7 render states
2957 * Version 2 and 3
2959 * Params:
2960 * LightStateType: The light state to change
2961 * Value: The value to assign to that light state
2963 * Returns:
2964 * D3D_OK on success
2965 * DDERR_INVALIDPARAMS if the parameters were incorrect
2966 * Also check IDirect3DDevice7::SetRenderState
2968 *****************************************************************************/
2969 static HRESULT WINAPI
2970 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
2971 D3DLIGHTSTATETYPE LightStateType,
2972 DWORD Value)
2974 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2975 HRESULT hr;
2977 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
2979 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2981 TRACE("Unexpected Light State Type\n");
2982 return DDERR_INVALIDPARAMS;
2985 wined3d_mutex_lock();
2986 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
2988 IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
2989 if (!m)
2991 WARN("Invalid material handle.\n");
2992 wined3d_mutex_unlock();
2993 return DDERR_INVALIDPARAMS;
2996 TRACE(" activating material %p.\n", m);
2997 material_activate(m);
2999 This->material = Value;
3001 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3003 switch (Value)
3005 case D3DCOLOR_MONO:
3006 ERR("DDCOLOR_MONO should not happen!\n");
3007 break;
3008 case D3DCOLOR_RGB:
3009 /* We are already in this mode */
3010 TRACE("Setting color model to RGB (no-op).\n");
3011 break;
3012 default:
3013 ERR("Unknown color model!\n");
3014 wined3d_mutex_unlock();
3015 return DDERR_INVALIDPARAMS;
3018 else
3020 D3DRENDERSTATETYPE rs;
3021 switch (LightStateType)
3023 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3024 rs = D3DRENDERSTATE_AMBIENT;
3025 break;
3026 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3027 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3028 break;
3029 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3030 rs = D3DRENDERSTATE_FOGSTART;
3031 break;
3032 case D3DLIGHTSTATE_FOGEND: /* 6 */
3033 rs = D3DRENDERSTATE_FOGEND;
3034 break;
3035 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3036 rs = D3DRENDERSTATE_FOGDENSITY;
3037 break;
3038 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3039 rs = D3DRENDERSTATE_COLORVERTEX;
3040 break;
3041 default:
3042 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3043 wined3d_mutex_unlock();
3044 return DDERR_INVALIDPARAMS;
3047 hr = IDirect3DDevice7_SetRenderState(&This->IDirect3DDevice7_iface, rs, Value);
3048 wined3d_mutex_unlock();
3049 return hr;
3051 wined3d_mutex_unlock();
3053 return D3D_OK;
3056 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3057 D3DLIGHTSTATETYPE LightStateType, DWORD Value)
3059 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3061 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3063 return IDirect3DDevice3_SetLightState(&This->IDirect3DDevice3_iface, LightStateType, Value);
3066 /*****************************************************************************
3067 * IDirect3DDevice3::GetLightState
3069 * Returns the current setting of a light state. The state is read from
3070 * the Direct3DDevice7 render state.
3072 * Version 2 and 3
3074 * Params:
3075 * LightStateType: The light state to return
3076 * Value: The address to store the light state setting at
3078 * Returns:
3079 * D3D_OK on success
3080 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3081 * Also see IDirect3DDevice7::GetRenderState
3083 *****************************************************************************/
3084 static HRESULT WINAPI
3085 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3086 D3DLIGHTSTATETYPE LightStateType,
3087 DWORD *Value)
3089 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3090 HRESULT hr;
3092 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3094 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3096 TRACE("Unexpected Light State Type\n");
3097 return DDERR_INVALIDPARAMS;
3100 if(!Value)
3101 return DDERR_INVALIDPARAMS;
3103 wined3d_mutex_lock();
3104 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3106 *Value = This->material;
3108 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3110 *Value = D3DCOLOR_RGB;
3112 else
3114 D3DRENDERSTATETYPE rs;
3115 switch (LightStateType)
3117 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3118 rs = D3DRENDERSTATE_AMBIENT;
3119 break;
3120 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3121 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3122 break;
3123 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3124 rs = D3DRENDERSTATE_FOGSTART;
3125 break;
3126 case D3DLIGHTSTATE_FOGEND: /* 6 */
3127 rs = D3DRENDERSTATE_FOGEND;
3128 break;
3129 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3130 rs = D3DRENDERSTATE_FOGDENSITY;
3131 break;
3132 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3133 rs = D3DRENDERSTATE_COLORVERTEX;
3134 break;
3135 default:
3136 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3137 wined3d_mutex_unlock();
3138 return DDERR_INVALIDPARAMS;
3141 hr = IDirect3DDevice7_GetRenderState(&This->IDirect3DDevice7_iface, rs, Value);
3142 wined3d_mutex_unlock();
3143 return hr;
3145 wined3d_mutex_unlock();
3147 return D3D_OK;
3150 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3151 D3DLIGHTSTATETYPE LightStateType, DWORD *Value)
3153 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3155 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3157 return IDirect3DDevice3_GetLightState(&This->IDirect3DDevice3_iface, LightStateType, Value);
3160 /*****************************************************************************
3161 * IDirect3DDevice7::SetTransform
3163 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3164 * in include/d3dtypes.h.
3165 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3166 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3167 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3169 * Version 2, 3 and 7
3171 * Params:
3172 * TransformStateType: transform state to set
3173 * Matrix: Matrix to assign to the state
3175 * Returns:
3176 * D3D_OK on success
3177 * DDERR_INVALIDPARAMS if Matrix == NULL
3178 * For details see IWineD3DDevice::SetTransform
3180 *****************************************************************************/
3181 static HRESULT
3182 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3183 D3DTRANSFORMSTATETYPE TransformStateType,
3184 D3DMATRIX *Matrix)
3186 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3187 D3DTRANSFORMSTATETYPE type;
3188 HRESULT hr;
3190 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3192 switch(TransformStateType)
3194 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3195 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3196 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3197 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3198 default: type = TransformStateType;
3201 if (!Matrix)
3202 return DDERR_INVALIDPARAMS;
3204 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3205 wined3d_mutex_lock();
3206 hr = wined3d_device_set_transform(This->wined3d_device, type, (struct wined3d_matrix *)Matrix);
3207 wined3d_mutex_unlock();
3209 return hr;
3212 static HRESULT WINAPI
3213 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3214 D3DTRANSFORMSTATETYPE TransformStateType,
3215 D3DMATRIX *Matrix)
3217 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3220 static HRESULT WINAPI
3221 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3222 D3DTRANSFORMSTATETYPE TransformStateType,
3223 D3DMATRIX *Matrix)
3225 HRESULT hr;
3226 WORD old_fpucw;
3228 old_fpucw = d3d_fpu_setup();
3229 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3230 set_fpu_control_word(old_fpucw);
3232 return hr;
3235 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3236 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3238 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3240 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3242 return IDirect3DDevice7_SetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3245 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3246 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3248 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3250 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3252 return IDirect3DDevice7_SetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3255 /*****************************************************************************
3256 * IDirect3DDevice7::GetTransform
3258 * Returns the matrix assigned to a transform state
3259 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3260 * SetTransform
3262 * Params:
3263 * TransformStateType: State to read the matrix from
3264 * Matrix: Address to store the matrix at
3266 * Returns:
3267 * D3D_OK on success
3268 * DDERR_INVALIDPARAMS if Matrix == NULL
3269 * For details, see IWineD3DDevice::GetTransform
3271 *****************************************************************************/
3272 static HRESULT
3273 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3274 D3DTRANSFORMSTATETYPE TransformStateType,
3275 D3DMATRIX *Matrix)
3277 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3278 D3DTRANSFORMSTATETYPE type;
3279 HRESULT hr;
3281 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3283 switch(TransformStateType)
3285 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3286 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3287 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3288 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3289 default: type = TransformStateType;
3292 if(!Matrix)
3293 return DDERR_INVALIDPARAMS;
3295 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3296 wined3d_mutex_lock();
3297 hr = wined3d_device_get_transform(This->wined3d_device, type, (struct wined3d_matrix *)Matrix);
3298 wined3d_mutex_unlock();
3300 return hr;
3303 static HRESULT WINAPI
3304 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3305 D3DTRANSFORMSTATETYPE TransformStateType,
3306 D3DMATRIX *Matrix)
3308 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3311 static HRESULT WINAPI
3312 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3313 D3DTRANSFORMSTATETYPE TransformStateType,
3314 D3DMATRIX *Matrix)
3316 HRESULT hr;
3317 WORD old_fpucw;
3319 old_fpucw = d3d_fpu_setup();
3320 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3321 set_fpu_control_word(old_fpucw);
3323 return hr;
3326 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3327 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3329 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3331 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3333 return IDirect3DDevice7_GetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3336 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3337 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3339 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3341 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3343 return IDirect3DDevice7_GetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3346 /*****************************************************************************
3347 * IDirect3DDevice7::MultiplyTransform
3349 * Multiplies the already-set transform matrix of a transform state
3350 * with another matrix. For the world matrix, see SetTransform
3352 * Version 2, 3 and 7
3354 * Params:
3355 * TransformStateType: Transform state to multiply
3356 * D3DMatrix Matrix to multiply with.
3358 * Returns
3359 * D3D_OK on success
3360 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3361 * For details, see IWineD3DDevice::MultiplyTransform
3363 *****************************************************************************/
3364 static HRESULT
3365 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3366 D3DTRANSFORMSTATETYPE TransformStateType,
3367 D3DMATRIX *D3DMatrix)
3369 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3370 HRESULT hr;
3371 D3DTRANSFORMSTATETYPE type;
3373 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3375 switch(TransformStateType)
3377 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3378 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3379 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3380 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3381 default: type = TransformStateType;
3384 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3385 wined3d_mutex_lock();
3386 hr = wined3d_device_multiply_transform(This->wined3d_device,
3387 type, (struct wined3d_matrix *)D3DMatrix);
3388 wined3d_mutex_unlock();
3390 return hr;
3393 static HRESULT WINAPI
3394 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3395 D3DTRANSFORMSTATETYPE TransformStateType,
3396 D3DMATRIX *D3DMatrix)
3398 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3401 static HRESULT WINAPI
3402 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3403 D3DTRANSFORMSTATETYPE TransformStateType,
3404 D3DMATRIX *D3DMatrix)
3406 HRESULT hr;
3407 WORD old_fpucw;
3409 old_fpucw = d3d_fpu_setup();
3410 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3411 set_fpu_control_word(old_fpucw);
3413 return hr;
3416 static HRESULT WINAPI IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3417 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3419 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3421 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3423 return IDirect3DDevice7_MultiplyTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3426 static HRESULT WINAPI IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3427 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3429 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3431 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3433 return IDirect3DDevice7_MultiplyTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3436 /*****************************************************************************
3437 * IDirect3DDevice7::DrawPrimitive
3439 * Draws primitives based on vertices in an application-provided pointer
3441 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3442 * an FVF format for D3D7
3444 * Params:
3445 * PrimitiveType: The type of the primitives to draw
3446 * Vertex type: Flexible vertex format vertex description
3447 * Vertices: Pointer to the vertex array
3448 * VertexCount: The number of vertices to draw
3449 * Flags: As usual a few flags
3451 * Returns:
3452 * D3D_OK on success
3453 * DDERR_INVALIDPARAMS if Vertices is NULL
3454 * For details, see IWineD3DDevice::DrawPrimitiveUP
3456 *****************************************************************************/
3457 static HRESULT
3458 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3459 D3DPRIMITIVETYPE PrimitiveType,
3460 DWORD VertexType,
3461 void *Vertices,
3462 DWORD VertexCount,
3463 DWORD Flags)
3465 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3466 UINT stride;
3467 HRESULT hr;
3469 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3470 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3472 if(!Vertices)
3473 return DDERR_INVALIDPARAMS;
3475 /* Get the stride */
3476 stride = get_flexible_vertex_size(VertexType);
3478 /* Set the FVF */
3479 wined3d_mutex_lock();
3480 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3481 if(hr != D3D_OK)
3483 wined3d_mutex_unlock();
3484 return hr;
3487 /* This method translates to the user pointer draw of WineD3D */
3488 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3489 hr = wined3d_device_draw_primitive_up(This->wined3d_device, VertexCount, Vertices, stride);
3490 wined3d_mutex_unlock();
3492 return hr;
3495 static HRESULT WINAPI
3496 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3497 D3DPRIMITIVETYPE PrimitiveType,
3498 DWORD VertexType,
3499 void *Vertices,
3500 DWORD VertexCount,
3501 DWORD Flags)
3503 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3506 static HRESULT WINAPI
3507 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3508 D3DPRIMITIVETYPE PrimitiveType,
3509 DWORD VertexType,
3510 void *Vertices,
3511 DWORD VertexCount,
3512 DWORD Flags)
3514 HRESULT hr;
3515 WORD old_fpucw;
3517 old_fpucw = d3d_fpu_setup();
3518 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3519 set_fpu_control_word(old_fpucw);
3521 return hr;
3524 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3525 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3526 DWORD Flags)
3528 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3529 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3530 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3532 return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface,
3533 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3536 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3537 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3538 DWORD VertexCount, DWORD Flags)
3540 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3541 DWORD FVF;
3543 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3544 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3546 switch(VertexType)
3548 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3549 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3550 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3551 default:
3552 ERR("Unexpected vertex type %d\n", VertexType);
3553 return DDERR_INVALIDPARAMS; /* Should never happen */
3556 return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface,
3557 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3560 /*****************************************************************************
3561 * IDirect3DDevice7::DrawIndexedPrimitive
3563 * Draws vertices from an application-provided pointer, based on the index
3564 * numbers in a WORD array.
3566 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3567 * an FVF format for D3D7
3569 * Params:
3570 * PrimitiveType: The primitive type to draw
3571 * VertexType: The FVF vertex description
3572 * Vertices: Pointer to the vertex array
3573 * VertexCount: ?
3574 * Indices: Pointer to the index array
3575 * IndexCount: Number of indices = Number of vertices to draw
3576 * Flags: As usual, some flags
3578 * Returns:
3579 * D3D_OK on success
3580 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3581 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3583 *****************************************************************************/
3584 static HRESULT
3585 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3586 D3DPRIMITIVETYPE PrimitiveType,
3587 DWORD VertexType,
3588 void *Vertices,
3589 DWORD VertexCount,
3590 WORD *Indices,
3591 DWORD IndexCount,
3592 DWORD Flags)
3594 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3595 HRESULT hr;
3597 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3598 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3600 /* Set the D3DDevice's FVF */
3601 wined3d_mutex_lock();
3602 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3603 if(FAILED(hr))
3605 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3606 wined3d_mutex_unlock();
3607 return hr;
3610 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3611 hr = wined3d_device_draw_indexed_primitive_up(This->wined3d_device, IndexCount, Indices,
3612 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3613 wined3d_mutex_unlock();
3615 return hr;
3618 static HRESULT WINAPI
3619 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3620 D3DPRIMITIVETYPE PrimitiveType,
3621 DWORD VertexType,
3622 void *Vertices,
3623 DWORD VertexCount,
3624 WORD *Indices,
3625 DWORD IndexCount,
3626 DWORD Flags)
3628 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3631 static HRESULT WINAPI
3632 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3633 D3DPRIMITIVETYPE PrimitiveType,
3634 DWORD VertexType,
3635 void *Vertices,
3636 DWORD VertexCount,
3637 WORD *Indices,
3638 DWORD IndexCount,
3639 DWORD Flags)
3641 HRESULT hr;
3642 WORD old_fpucw;
3644 old_fpucw = d3d_fpu_setup();
3645 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3646 set_fpu_control_word(old_fpucw);
3648 return hr;
3651 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3652 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3653 WORD *Indices, DWORD IndexCount, DWORD Flags)
3655 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3656 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3657 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3659 return IDirect3DDevice7_DrawIndexedPrimitive(&This->IDirect3DDevice7_iface,
3660 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3663 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3664 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3665 DWORD VertexCount, WORD *Indices, DWORD IndexCount, DWORD Flags)
3667 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3668 DWORD FVF;
3670 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3671 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3673 switch(VertexType)
3675 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3676 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3677 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3678 default:
3679 ERR("Unexpected vertex type %d\n", VertexType);
3680 return DDERR_INVALIDPARAMS; /* Should never happen */
3683 return IDirect3DDevice7_DrawIndexedPrimitive(&This->IDirect3DDevice7_iface,
3684 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3687 /*****************************************************************************
3688 * IDirect3DDevice7::SetClipStatus
3690 * Sets the clip status. This defines things as clipping conditions and
3691 * the extents of the clipping region.
3693 * Version 2, 3 and 7
3695 * Params:
3696 * ClipStatus:
3698 * Returns:
3699 * D3D_OK because it's a stub
3700 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3702 *****************************************************************************/
3703 static HRESULT WINAPI
3704 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3705 D3DCLIPSTATUS *ClipStatus)
3707 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3709 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3710 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3712 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3713 return D3D_OK;
3716 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3717 D3DCLIPSTATUS *ClipStatus)
3719 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3720 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3722 return IDirect3DDevice7_SetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3725 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3726 D3DCLIPSTATUS *ClipStatus)
3728 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3729 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3731 return IDirect3DDevice7_SetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3734 /*****************************************************************************
3735 * IDirect3DDevice7::GetClipStatus
3737 * Returns the clip status
3739 * Params:
3740 * ClipStatus: Address to write the clip status to
3742 * Returns:
3743 * D3D_OK because it's a stub
3745 *****************************************************************************/
3746 static HRESULT WINAPI
3747 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3748 D3DCLIPSTATUS *ClipStatus)
3750 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3752 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3753 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3754 return D3D_OK;
3757 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3758 D3DCLIPSTATUS *ClipStatus)
3760 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3761 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3763 return IDirect3DDevice7_GetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3766 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3767 D3DCLIPSTATUS *ClipStatus)
3769 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3770 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3772 return IDirect3DDevice7_GetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3775 /*****************************************************************************
3776 * IDirect3DDevice::DrawPrimitiveStrided
3778 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3780 * Version 3 and 7
3782 * Params:
3783 * PrimitiveType: The primitive type to draw
3784 * VertexType: The FVF description of the vertices to draw (for the stride??)
3785 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3786 * the vertex data locations
3787 * VertexCount: The number of vertices to draw
3788 * Flags: Some flags
3790 * Returns:
3791 * D3D_OK, because it's a stub
3792 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3793 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3795 *****************************************************************************/
3796 static HRESULT
3797 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3798 D3DPRIMITIVETYPE PrimitiveType,
3799 DWORD VertexType,
3800 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3801 DWORD VertexCount,
3802 DWORD Flags)
3804 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3805 WineDirect3DVertexStridedData WineD3DStrided;
3806 DWORD i;
3807 HRESULT hr;
3809 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3810 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3812 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3813 /* Get the strided data right. the wined3d structure is a bit bigger
3814 * Watch out: The contents of the strided data are determined by the fvf,
3815 * not by the members set in D3DDrawPrimStrideData. So it's valid
3816 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3817 * not set in the fvf.
3819 if(VertexType & D3DFVF_POSITION_MASK)
3821 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3822 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3823 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3824 if (VertexType & D3DFVF_XYZRHW)
3826 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3827 WineD3DStrided.position_transformed = TRUE;
3828 } else
3829 WineD3DStrided.position_transformed = FALSE;
3832 if(VertexType & D3DFVF_NORMAL)
3834 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3835 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3836 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3839 if(VertexType & D3DFVF_DIFFUSE)
3841 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3842 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3843 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3846 if(VertexType & D3DFVF_SPECULAR)
3848 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3849 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3850 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3853 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3855 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3857 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3858 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3859 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3860 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3861 default: ERR("Unexpected texture coordinate size %d\n",
3862 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3864 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3865 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3868 /* WineD3D doesn't need the FVF here */
3869 wined3d_mutex_lock();
3870 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3871 hr = wined3d_device_draw_primitive_strided(This->wined3d_device, VertexCount, &WineD3DStrided);
3872 wined3d_mutex_unlock();
3874 return hr;
3877 static HRESULT WINAPI
3878 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3879 D3DPRIMITIVETYPE PrimitiveType,
3880 DWORD VertexType,
3881 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3882 DWORD VertexCount,
3883 DWORD Flags)
3885 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3888 static HRESULT WINAPI
3889 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3890 D3DPRIMITIVETYPE PrimitiveType,
3891 DWORD VertexType,
3892 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3893 DWORD VertexCount,
3894 DWORD Flags)
3896 HRESULT hr;
3897 WORD old_fpucw;
3899 old_fpucw = d3d_fpu_setup();
3900 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3901 set_fpu_control_word(old_fpucw);
3903 return hr;
3906 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3907 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3908 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3910 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3912 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3913 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3915 return IDirect3DDevice7_DrawPrimitiveStrided(&This->IDirect3DDevice7_iface,
3916 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3919 /*****************************************************************************
3920 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3922 * Draws primitives specified by strided data locations based on indices
3924 * Version 3 and 7
3926 * Params:
3927 * PrimitiveType:
3929 * Returns:
3930 * D3D_OK, because it's a stub
3931 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3932 * (DDERR_INVALIDPARAMS if Indices is NULL)
3933 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3935 *****************************************************************************/
3936 static HRESULT
3937 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3938 D3DPRIMITIVETYPE PrimitiveType,
3939 DWORD VertexType,
3940 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3941 DWORD VertexCount,
3942 WORD *Indices,
3943 DWORD IndexCount,
3944 DWORD Flags)
3946 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3947 WineDirect3DVertexStridedData WineD3DStrided;
3948 DWORD i;
3949 HRESULT hr;
3951 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3952 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3954 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3955 /* Get the strided data right. the wined3d structure is a bit bigger
3956 * Watch out: The contents of the strided data are determined by the fvf,
3957 * not by the members set in D3DDrawPrimStrideData. So it's valid
3958 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3959 * not set in the fvf.
3961 if(VertexType & D3DFVF_POSITION_MASK)
3963 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3964 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3965 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3966 if (VertexType & D3DFVF_XYZRHW)
3968 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3969 WineD3DStrided.position_transformed = TRUE;
3970 } else
3971 WineD3DStrided.position_transformed = FALSE;
3974 if(VertexType & D3DFVF_NORMAL)
3976 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3977 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3978 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3981 if(VertexType & D3DFVF_DIFFUSE)
3983 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3984 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3985 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3988 if(VertexType & D3DFVF_SPECULAR)
3990 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3991 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3992 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3995 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3997 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3999 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
4000 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
4001 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
4002 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
4003 default: ERR("Unexpected texture coordinate size %d\n",
4004 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4006 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4007 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4010 /* WineD3D doesn't need the FVF here */
4011 wined3d_mutex_lock();
4012 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4013 hr = wined3d_device_draw_indexed_primitive_strided(This->wined3d_device,
4014 IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
4015 wined3d_mutex_unlock();
4017 return hr;
4020 static HRESULT WINAPI
4021 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4022 D3DPRIMITIVETYPE PrimitiveType,
4023 DWORD VertexType,
4024 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4025 DWORD VertexCount,
4026 WORD *Indices,
4027 DWORD IndexCount,
4028 DWORD Flags)
4030 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4033 static HRESULT WINAPI
4034 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4035 D3DPRIMITIVETYPE PrimitiveType,
4036 DWORD VertexType,
4037 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4038 DWORD VertexCount,
4039 WORD *Indices,
4040 DWORD IndexCount,
4041 DWORD Flags)
4043 HRESULT hr;
4044 WORD old_fpucw;
4046 old_fpucw = d3d_fpu_setup();
4047 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4048 set_fpu_control_word(old_fpucw);
4050 return hr;
4053 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4054 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4055 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4056 DWORD IndexCount, DWORD Flags)
4058 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4060 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4061 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4063 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&This->IDirect3DDevice7_iface,
4064 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4067 /*****************************************************************************
4068 * IDirect3DDevice7::DrawPrimitiveVB
4070 * Draws primitives from a vertex buffer to the screen.
4072 * Version 3 and 7
4074 * Params:
4075 * PrimitiveType: Type of primitive to be rendered.
4076 * D3DVertexBuf: Source Vertex Buffer
4077 * StartVertex: Index of the first vertex from the buffer to be rendered
4078 * NumVertices: Number of vertices to be rendered
4079 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4081 * Return values
4082 * D3D_OK on success
4083 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4085 *****************************************************************************/
4086 static HRESULT
4087 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4088 D3DPRIMITIVETYPE PrimitiveType,
4089 IDirect3DVertexBuffer7 *D3DVertexBuf,
4090 DWORD StartVertex,
4091 DWORD NumVertices,
4092 DWORD Flags)
4094 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4095 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4096 HRESULT hr;
4097 DWORD stride;
4099 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4100 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4102 /* Sanity checks */
4103 if(!vb)
4105 ERR("(%p) No Vertex buffer specified\n", This);
4106 return DDERR_INVALIDPARAMS;
4108 stride = get_flexible_vertex_size(vb->fvf);
4110 wined3d_mutex_lock();
4111 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4112 if (FAILED(hr))
4114 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4115 wined3d_mutex_unlock();
4116 return hr;
4119 /* Set the vertex stream source */
4120 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4121 if(hr != D3D_OK)
4123 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4124 wined3d_mutex_unlock();
4125 return hr;
4128 /* Now draw the primitives */
4129 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4130 hr = wined3d_device_draw_primitive(This->wined3d_device, StartVertex, NumVertices);
4131 wined3d_mutex_unlock();
4133 return hr;
4136 static HRESULT WINAPI
4137 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4138 D3DPRIMITIVETYPE PrimitiveType,
4139 IDirect3DVertexBuffer7 *D3DVertexBuf,
4140 DWORD StartVertex,
4141 DWORD NumVertices,
4142 DWORD Flags)
4144 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4147 static HRESULT WINAPI
4148 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4149 D3DPRIMITIVETYPE PrimitiveType,
4150 IDirect3DVertexBuffer7 *D3DVertexBuf,
4151 DWORD StartVertex,
4152 DWORD NumVertices,
4153 DWORD Flags)
4155 HRESULT hr;
4156 WORD old_fpucw;
4158 old_fpucw = d3d_fpu_setup();
4159 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4160 set_fpu_control_word(old_fpucw);
4162 return hr;
4165 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4166 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex,
4167 DWORD NumVertices, DWORD Flags)
4169 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4170 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4172 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4173 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4175 return IDirect3DDevice7_DrawPrimitiveVB(&This->IDirect3DDevice7_iface,
4176 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4180 /*****************************************************************************
4181 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4183 * Draws primitives from a vertex buffer to the screen
4185 * Params:
4186 * PrimitiveType: Type of primitive to be rendered.
4187 * D3DVertexBuf: Source Vertex Buffer
4188 * StartVertex: Index of the first vertex from the buffer to be rendered
4189 * NumVertices: Number of vertices to be rendered
4190 * Indices: Array of DWORDs used to index into the Vertices
4191 * IndexCount: Number of indices in Indices
4192 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4194 * Return values
4196 *****************************************************************************/
4197 static HRESULT
4198 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4199 D3DPRIMITIVETYPE PrimitiveType,
4200 IDirect3DVertexBuffer7 *D3DVertexBuf,
4201 DWORD StartVertex,
4202 DWORD NumVertices,
4203 WORD *Indices,
4204 DWORD IndexCount,
4205 DWORD Flags)
4207 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4208 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4209 DWORD stride = get_flexible_vertex_size(vb->fvf);
4210 struct wined3d_resource *wined3d_resource;
4211 struct wined3d_resource_desc desc;
4212 WORD *LockedIndices;
4213 HRESULT hr;
4215 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4216 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4218 /* Steps:
4219 * 1) Upload the Indices to the index buffer
4220 * 2) Set the index source
4221 * 3) Set the Vertex Buffer as the Stream source
4222 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4225 wined3d_mutex_lock();
4227 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4228 if (FAILED(hr))
4230 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4231 wined3d_mutex_unlock();
4232 return hr;
4235 /* check that the buffer is large enough to hold the indices,
4236 * reallocate if necessary. */
4237 wined3d_resource = wined3d_buffer_get_resource(This->indexbuffer);
4238 wined3d_resource_get_desc(wined3d_resource, &desc);
4239 if (desc.size < IndexCount * sizeof(WORD))
4241 UINT size = max(desc.size * 2, IndexCount * sizeof(WORD));
4242 struct wined3d_buffer *buffer;
4244 TRACE("Growing index buffer to %u bytes\n", size);
4246 hr = wined3d_buffer_create_ib(This->wined3d_device, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4247 WINED3DPOOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
4248 if (FAILED(hr))
4250 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4251 wined3d_mutex_unlock();
4252 return hr;
4255 wined3d_buffer_decref(This->indexbuffer);
4256 This->indexbuffer = buffer;
4259 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4260 * method could be created which takes an user pointer containing the
4261 * indices or a SetData-Method for the index buffer, which overrides the
4262 * index buffer data with our pointer. */
4263 hr = wined3d_buffer_map(This->indexbuffer, 0, IndexCount * sizeof(WORD),
4264 (BYTE **)&LockedIndices, 0);
4265 if (FAILED(hr))
4267 ERR("Failed to map buffer, hr %#x.\n", hr);
4268 wined3d_mutex_unlock();
4269 return hr;
4271 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4272 wined3d_buffer_unmap(This->indexbuffer);
4274 /* Set the index stream */
4275 wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4276 hr = wined3d_device_set_index_buffer(This->wined3d_device, This->indexbuffer, WINED3DFMT_R16_UINT);
4278 /* Set the vertex stream source */
4279 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4280 if (FAILED(hr))
4282 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4283 wined3d_mutex_unlock();
4284 return hr;
4288 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4289 hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, 0, IndexCount);
4291 wined3d_mutex_unlock();
4293 return hr;
4296 static HRESULT WINAPI
4297 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4298 D3DPRIMITIVETYPE PrimitiveType,
4299 IDirect3DVertexBuffer7 *D3DVertexBuf,
4300 DWORD StartVertex,
4301 DWORD NumVertices,
4302 WORD *Indices,
4303 DWORD IndexCount,
4304 DWORD Flags)
4306 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4309 static HRESULT WINAPI
4310 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4311 D3DPRIMITIVETYPE PrimitiveType,
4312 IDirect3DVertexBuffer7 *D3DVertexBuf,
4313 DWORD StartVertex,
4314 DWORD NumVertices,
4315 WORD *Indices,
4316 DWORD IndexCount,
4317 DWORD Flags)
4319 HRESULT hr;
4320 WORD old_fpucw;
4322 old_fpucw = d3d_fpu_setup();
4323 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4324 set_fpu_control_word(old_fpucw);
4326 return hr;
4329 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4330 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4331 DWORD IndexCount, DWORD Flags)
4333 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4334 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4336 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4337 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4339 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&This->IDirect3DDevice7_iface,
4340 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount,
4341 Flags);
4344 /*****************************************************************************
4345 * IDirect3DDevice7::ComputeSphereVisibility
4347 * Calculates the visibility of spheres in the current viewport. The spheres
4348 * are passed in the Centers and Radii arrays, the results are passed back
4349 * in the ReturnValues array. Return values are either completely visible,
4350 * partially visible or completely invisible.
4351 * The return value consist of a combination of D3DCLIP_* flags, or it's
4352 * 0 if the sphere is completely visible(according to the SDK, not checked)
4354 * Version 3 and 7
4356 * Params:
4357 * Centers: Array containing the sphere centers
4358 * Radii: Array containing the sphere radii
4359 * NumSpheres: The number of centers and radii in the arrays
4360 * Flags: Some flags
4361 * ReturnValues: Array to write the results to
4363 * Returns:
4364 * D3D_OK
4365 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4366 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4367 * is singular)
4369 *****************************************************************************/
4371 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4373 float distance, norm;
4375 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4376 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4378 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4379 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4380 return 0;
4383 static HRESULT WINAPI
4384 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4385 D3DVECTOR *Centers,
4386 D3DVALUE *Radii,
4387 DWORD NumSpheres,
4388 DWORD Flags,
4389 DWORD *ReturnValues)
4391 D3DMATRIX m, temp;
4392 D3DVALUE origin_plane[6];
4393 D3DVECTOR vec[6];
4394 HRESULT hr;
4395 UINT i, j;
4397 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4398 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4400 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4401 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4402 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4403 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4404 multiply_matrix(&m, &temp, &m);
4406 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4407 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4408 multiply_matrix(&m, &temp, &m);
4410 /* Left plane */
4411 vec[0].u1.x = m._14 + m._11;
4412 vec[0].u2.y = m._24 + m._21;
4413 vec[0].u3.z = m._34 + m._31;
4414 origin_plane[0] = m._44 + m._41;
4416 /* Right plane */
4417 vec[1].u1.x = m._14 - m._11;
4418 vec[1].u2.y = m._24 - m._21;
4419 vec[1].u3.z = m._34 - m._31;
4420 origin_plane[1] = m._44 - m._41;
4422 /* Top plane */
4423 vec[2].u1.x = m._14 - m._12;
4424 vec[2].u2.y = m._24 - m._22;
4425 vec[2].u3.z = m._34 - m._32;
4426 origin_plane[2] = m._44 - m._42;
4428 /* Bottom plane */
4429 vec[3].u1.x = m._14 + m._12;
4430 vec[3].u2.y = m._24 + m._22;
4431 vec[3].u3.z = m._34 + m._32;
4432 origin_plane[3] = m._44 + m._42;
4434 /* Front plane */
4435 vec[4].u1.x = m._13;
4436 vec[4].u2.y = m._23;
4437 vec[4].u3.z = m._33;
4438 origin_plane[4] = m._43;
4440 /* Back plane*/
4441 vec[5].u1.x = m._14 - m._13;
4442 vec[5].u2.y = m._24 - m._23;
4443 vec[5].u3.z = m._34 - m._33;
4444 origin_plane[5] = m._44 - m._43;
4446 for(i=0; i<NumSpheres; i++)
4448 ReturnValues[i] = 0;
4449 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4452 return D3D_OK;
4455 static HRESULT WINAPI IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4456 D3DVECTOR *Centers, D3DVALUE *Radii, DWORD NumSpheres, DWORD Flags, DWORD *ReturnValues)
4458 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4460 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4461 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4463 return IDirect3DDevice7_ComputeSphereVisibility(&This->IDirect3DDevice7_iface,
4464 Centers, Radii, NumSpheres, Flags, ReturnValues);
4467 /*****************************************************************************
4468 * IDirect3DDevice7::GetTexture
4470 * Returns the texture interface handle assigned to a texture stage.
4471 * The returned texture is AddRefed. This is taken from old ddraw,
4472 * not checked in Windows.
4474 * Version 3 and 7
4476 * Params:
4477 * Stage: Texture stage to read the texture from
4478 * Texture: Address to store the interface pointer at
4480 * Returns:
4481 * D3D_OK on success
4482 * DDERR_INVALIDPARAMS if Texture is NULL
4483 * For details, see IWineD3DDevice::GetTexture
4485 *****************************************************************************/
4486 static HRESULT
4487 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4488 DWORD Stage,
4489 IDirectDrawSurface7 **Texture)
4491 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4492 struct wined3d_texture *wined3d_texture;
4493 HRESULT hr;
4495 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4497 if(!Texture)
4499 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4500 return DDERR_INVALIDPARAMS;
4503 wined3d_mutex_lock();
4504 hr = wined3d_device_get_texture(This->wined3d_device, Stage, &wined3d_texture);
4505 if (FAILED(hr) || !wined3d_texture)
4507 *Texture = NULL;
4508 wined3d_mutex_unlock();
4509 return hr;
4512 *Texture = wined3d_texture_get_parent(wined3d_texture);
4513 IDirectDrawSurface7_AddRef(*Texture);
4514 wined3d_texture_decref(wined3d_texture);
4515 wined3d_mutex_unlock();
4517 return hr;
4520 static HRESULT WINAPI
4521 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4522 DWORD Stage,
4523 IDirectDrawSurface7 **Texture)
4525 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4528 static HRESULT WINAPI
4529 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4530 DWORD Stage,
4531 IDirectDrawSurface7 **Texture)
4533 HRESULT hr;
4534 WORD old_fpucw;
4536 old_fpucw = d3d_fpu_setup();
4537 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4538 set_fpu_control_word(old_fpucw);
4540 return hr;
4543 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface, DWORD Stage,
4544 IDirect3DTexture2 **Texture2)
4546 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4547 HRESULT ret;
4548 IDirectDrawSurface7 *ret_val;
4549 IDirectDrawSurfaceImpl *ret_val_impl;
4551 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4553 ret = IDirect3DDevice7_GetTexture(&This->IDirect3DDevice7_iface, Stage, &ret_val);
4555 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4556 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4558 TRACE("Returning texture %p.\n", *Texture2);
4560 return ret;
4563 /*****************************************************************************
4564 * IDirect3DDevice7::SetTexture
4566 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4568 * Version 3 and 7
4570 * Params:
4571 * Stage: The stage to assign the texture to
4572 * Texture: Interface pointer to the texture surface
4574 * Returns
4575 * D3D_OK on success
4576 * For details, see IWineD3DDevice::SetTexture
4578 *****************************************************************************/
4579 static HRESULT
4580 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4581 DWORD Stage,
4582 IDirectDrawSurface7 *Texture)
4584 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4585 IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
4586 HRESULT hr;
4588 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4590 /* Texture may be NULL here */
4591 wined3d_mutex_lock();
4592 hr = wined3d_device_set_texture(This->wined3d_device,
4593 Stage, surf ? surf->wined3d_texture : NULL);
4594 wined3d_mutex_unlock();
4596 return hr;
4599 static HRESULT WINAPI
4600 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4601 DWORD Stage,
4602 IDirectDrawSurface7 *Texture)
4604 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4607 static HRESULT WINAPI
4608 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4609 DWORD Stage,
4610 IDirectDrawSurface7 *Texture)
4612 HRESULT hr;
4613 WORD old_fpucw;
4615 old_fpucw = d3d_fpu_setup();
4616 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4617 set_fpu_control_word(old_fpucw);
4619 return hr;
4622 static HRESULT WINAPI
4623 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4624 DWORD Stage,
4625 IDirect3DTexture2 *Texture2)
4627 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4628 IDirectDrawSurfaceImpl *tex = unsafe_impl_from_IDirect3DTexture2(Texture2);
4629 DWORD texmapblend;
4630 HRESULT hr;
4632 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4634 wined3d_mutex_lock();
4636 if (This->legacyTextureBlending)
4637 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4639 hr = IDirect3DDevice7_SetTexture(&This->IDirect3DDevice7_iface, Stage, &tex->IDirectDrawSurface7_iface);
4641 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4643 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4644 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4645 struct wined3d_texture *tex = NULL;
4646 BOOL tex_alpha = FALSE;
4647 DDPIXELFORMAT ddfmt;
4648 HRESULT result;
4650 result = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
4651 if (result == WINED3D_OK && tex)
4653 struct wined3d_resource *sub_resource;
4655 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4657 struct wined3d_resource_desc desc;
4659 wined3d_resource_get_desc(sub_resource, &desc);
4660 ddfmt.dwSize = sizeof(ddfmt);
4661 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4662 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4665 wined3d_texture_decref(tex);
4668 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4669 if (tex_alpha)
4670 wined3d_device_set_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4671 else
4672 wined3d_device_set_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4675 wined3d_mutex_unlock();
4677 return hr;
4680 static const struct tss_lookup
4682 BOOL sampler_state;
4683 DWORD state;
4685 tss_lookup[] =
4687 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
4688 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
4689 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
4690 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
4691 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
4692 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
4693 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
4694 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4695 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4696 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4697 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4698 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4699 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
4700 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
4701 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
4702 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
4703 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
4704 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
4705 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
4706 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4707 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4708 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4709 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4710 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4711 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4714 /*****************************************************************************
4715 * IDirect3DDevice7::GetTextureStageState
4717 * Retrieves a state from a texture stage.
4719 * Version 3 and 7
4721 * Params:
4722 * Stage: The stage to retrieve the state from
4723 * TexStageStateType: The state type to retrieve
4724 * State: Address to store the state's value at
4726 * Returns:
4727 * D3D_OK on success
4728 * DDERR_INVALIDPARAMS if State is NULL
4729 * For details, see IWineD3DDevice::GetTextureStageState
4731 *****************************************************************************/
4732 static HRESULT
4733 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4734 DWORD Stage,
4735 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4736 DWORD *State)
4738 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4739 HRESULT hr;
4740 const struct tss_lookup *l;
4742 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4743 iface, Stage, TexStageStateType, State);
4745 if(!State)
4746 return DDERR_INVALIDPARAMS;
4748 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4750 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4751 return DD_OK;
4754 l = &tss_lookup[TexStageStateType];
4756 wined3d_mutex_lock();
4758 if (l->sampler_state)
4760 hr = wined3d_device_get_sampler_state(This->wined3d_device, Stage, l->state, State);
4762 switch(TexStageStateType)
4764 /* Mipfilter is a sampler state with different values */
4765 case D3DTSS_MIPFILTER:
4767 switch(*State)
4769 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4770 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4771 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4772 default:
4773 ERR("Unexpected mipfilter value %#x\n", *State);
4774 *State = D3DTFP_NONE;
4775 break;
4777 break;
4780 /* Magfilter has slightly different values */
4781 case D3DTSS_MAGFILTER:
4783 switch(*State)
4785 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4786 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4787 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4788 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4789 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4790 default:
4791 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4792 *State = D3DTFG_POINT;
4793 break;
4795 break;
4798 default:
4799 break;
4802 else
4804 hr = wined3d_device_get_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4807 wined3d_mutex_unlock();
4809 return hr;
4812 static HRESULT WINAPI
4813 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4814 DWORD Stage,
4815 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4816 DWORD *State)
4818 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4821 static HRESULT WINAPI
4822 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4823 DWORD Stage,
4824 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4825 DWORD *State)
4827 HRESULT hr;
4828 WORD old_fpucw;
4830 old_fpucw = d3d_fpu_setup();
4831 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4832 set_fpu_control_word(old_fpucw);
4834 return hr;
4837 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4838 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD *State)
4840 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4842 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4843 iface, Stage, TexStageStateType, State);
4845 return IDirect3DDevice7_GetTextureStageState(&This->IDirect3DDevice7_iface,
4846 Stage, TexStageStateType, State);
4849 /*****************************************************************************
4850 * IDirect3DDevice7::SetTextureStageState
4852 * Sets a texture stage state. Some stage types need to be handled specially,
4853 * because they do not exist in WineD3D and were moved to another place
4855 * Version 3 and 7
4857 * Params:
4858 * Stage: The stage to modify
4859 * TexStageStateType: The state to change
4860 * State: The new value for the state
4862 * Returns:
4863 * D3D_OK on success
4864 * For details, see IWineD3DDevice::SetTextureStageState
4866 *****************************************************************************/
4867 static HRESULT
4868 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4869 DWORD Stage,
4870 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4871 DWORD State)
4873 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4874 const struct tss_lookup *l;
4875 HRESULT hr;
4877 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4878 iface, Stage, TexStageStateType, State);
4880 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4882 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4883 return DD_OK;
4886 l = &tss_lookup[TexStageStateType];
4888 wined3d_mutex_lock();
4890 if (l->sampler_state)
4892 switch(TexStageStateType)
4894 /* Mipfilter is a sampler state with different values */
4895 case D3DTSS_MIPFILTER:
4897 switch(State)
4899 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
4900 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
4901 case 0: /* Unchecked */
4902 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
4903 default:
4904 ERR("Unexpected mipfilter value %d\n", State);
4905 State = WINED3DTEXF_NONE;
4906 break;
4908 break;
4911 /* Magfilter has slightly different values */
4912 case D3DTSS_MAGFILTER:
4914 switch(State)
4916 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
4917 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
4918 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
4919 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
4920 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
4921 default:
4922 ERR("Unexpected d3d7 mag filter type %d\n", State);
4923 State = WINED3DTEXF_POINT;
4924 break;
4926 break;
4929 case D3DTSS_ADDRESS:
4930 wined3d_device_set_sampler_state(This->wined3d_device, Stage, WINED3DSAMP_ADDRESSV, State);
4931 break;
4933 default:
4934 break;
4937 hr = wined3d_device_set_sampler_state(This->wined3d_device, Stage, l->state, State);
4939 else
4941 hr = wined3d_device_set_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4944 wined3d_mutex_unlock();
4946 return hr;
4949 static HRESULT WINAPI
4950 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4951 DWORD Stage,
4952 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4953 DWORD State)
4955 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4958 static HRESULT WINAPI
4959 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4960 DWORD Stage,
4961 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4962 DWORD State)
4964 HRESULT hr;
4965 WORD old_fpucw;
4967 old_fpucw = d3d_fpu_setup();
4968 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4969 set_fpu_control_word(old_fpucw);
4971 return hr;
4974 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
4975 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD State)
4977 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4979 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4980 iface, Stage, TexStageStateType, State);
4982 return IDirect3DDevice7_SetTextureStageState(&This->IDirect3DDevice7_iface,
4983 Stage, TexStageStateType, State);
4986 /*****************************************************************************
4987 * IDirect3DDevice7::ValidateDevice
4989 * SDK: "Reports the device's ability to render the currently set
4990 * texture-blending operations in a single pass". Whatever that means
4991 * exactly...
4993 * Version 3 and 7
4995 * Params:
4996 * NumPasses: Address to write the number of necessary passes for the
4997 * desired effect to.
4999 * Returns:
5000 * D3D_OK on success
5001 * See IWineD3DDevice::ValidateDevice for more details
5003 *****************************************************************************/
5004 static HRESULT
5005 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
5006 DWORD *NumPasses)
5008 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5009 HRESULT hr;
5011 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
5013 wined3d_mutex_lock();
5014 hr = wined3d_device_validate_device(This->wined3d_device, NumPasses);
5015 wined3d_mutex_unlock();
5017 return hr;
5020 static HRESULT WINAPI
5021 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
5022 DWORD *NumPasses)
5024 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5027 static HRESULT WINAPI
5028 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
5029 DWORD *NumPasses)
5031 HRESULT hr;
5032 WORD old_fpucw;
5034 old_fpucw = d3d_fpu_setup();
5035 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5036 set_fpu_control_word(old_fpucw);
5038 return hr;
5041 static HRESULT WINAPI IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *Passes)
5043 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
5045 TRACE("iface %p, pass_count %p.\n", iface, Passes);
5047 return IDirect3DDevice7_ValidateDevice(&This->IDirect3DDevice7_iface, Passes);
5050 /*****************************************************************************
5051 * IDirect3DDevice7::Clear
5053 * Fills the render target, the z buffer and the stencil buffer with a
5054 * clear color / value
5056 * Version 7 only
5058 * Params:
5059 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5060 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5061 * Flags: Some flags, as usual
5062 * Color: Clear color for the render target
5063 * Z: Clear value for the Z buffer
5064 * Stencil: Clear value to store in each stencil buffer entry
5066 * Returns:
5067 * D3D_OK on success
5068 * For details, see IWineD3DDevice::Clear
5070 *****************************************************************************/
5071 static HRESULT IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface, DWORD count,
5072 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5074 const struct wined3d_color c =
5076 ((color >> 16) & 0xff) / 255.0f,
5077 ((color >> 8) & 0xff) / 255.0f,
5078 (color & 0xff) / 255.0f,
5079 ((color >> 24) & 0xff) / 255.0f,
5081 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5082 HRESULT hr;
5084 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5085 iface, count, rects, flags, color, z, stencil);
5087 wined3d_mutex_lock();
5088 hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
5089 wined3d_mutex_unlock();
5091 return hr;
5094 static HRESULT WINAPI
5095 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5096 DWORD Count,
5097 D3DRECT *Rects,
5098 DWORD Flags,
5099 D3DCOLOR Color,
5100 D3DVALUE Z,
5101 DWORD Stencil)
5103 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5106 static HRESULT WINAPI
5107 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5108 DWORD Count,
5109 D3DRECT *Rects,
5110 DWORD Flags,
5111 D3DCOLOR Color,
5112 D3DVALUE Z,
5113 DWORD Stencil)
5115 HRESULT hr;
5116 WORD old_fpucw;
5118 old_fpucw = d3d_fpu_setup();
5119 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5120 set_fpu_control_word(old_fpucw);
5122 return hr;
5125 /*****************************************************************************
5126 * IDirect3DDevice7::SetViewport
5128 * Sets the current viewport.
5130 * Version 7 only, but IDirect3DViewport uses this call for older
5131 * versions
5133 * Params:
5134 * Data: The new viewport to set
5136 * Returns:
5137 * D3D_OK on success
5138 * DDERR_INVALIDPARAMS if Data is NULL
5139 * For more details, see IWineDDDevice::SetViewport
5141 *****************************************************************************/
5142 static HRESULT
5143 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5144 D3DVIEWPORT7 *Data)
5146 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5147 HRESULT hr;
5149 TRACE("iface %p, viewport %p.\n", iface, Data);
5151 if(!Data)
5152 return DDERR_INVALIDPARAMS;
5154 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5155 wined3d_mutex_lock();
5156 hr = wined3d_device_set_viewport(This->wined3d_device, (WINED3DVIEWPORT *)Data);
5157 wined3d_mutex_unlock();
5159 return hr;
5162 static HRESULT WINAPI
5163 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5164 D3DVIEWPORT7 *Data)
5166 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5169 static HRESULT WINAPI
5170 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5171 D3DVIEWPORT7 *Data)
5173 HRESULT hr;
5174 WORD old_fpucw;
5176 old_fpucw = d3d_fpu_setup();
5177 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5178 set_fpu_control_word(old_fpucw);
5180 return hr;
5183 /*****************************************************************************
5184 * IDirect3DDevice::GetViewport
5186 * Returns the current viewport
5188 * Version 7
5190 * Params:
5191 * Data: D3D7Viewport structure to write the viewport information to
5193 * Returns:
5194 * D3D_OK on success
5195 * DDERR_INVALIDPARAMS if Data is NULL
5196 * For more details, see IWineD3DDevice::GetViewport
5198 *****************************************************************************/
5199 static HRESULT
5200 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5201 D3DVIEWPORT7 *Data)
5203 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5204 HRESULT hr;
5206 TRACE("iface %p, viewport %p.\n", iface, Data);
5208 if(!Data)
5209 return DDERR_INVALIDPARAMS;
5211 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5212 wined3d_mutex_lock();
5213 hr = wined3d_device_get_viewport(This->wined3d_device, (WINED3DVIEWPORT *)Data);
5214 wined3d_mutex_unlock();
5216 return hr_ddraw_from_wined3d(hr);
5219 static HRESULT WINAPI
5220 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5221 D3DVIEWPORT7 *Data)
5223 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5226 static HRESULT WINAPI
5227 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5228 D3DVIEWPORT7 *Data)
5230 HRESULT hr;
5231 WORD old_fpucw;
5233 old_fpucw = d3d_fpu_setup();
5234 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5235 set_fpu_control_word(old_fpucw);
5237 return hr;
5240 /*****************************************************************************
5241 * IDirect3DDevice7::SetMaterial
5243 * Sets the Material
5245 * Version 7
5247 * Params:
5248 * Mat: The material to set
5250 * Returns:
5251 * D3D_OK on success
5252 * DDERR_INVALIDPARAMS if Mat is NULL.
5253 * For more details, see IWineD3DDevice::SetMaterial
5255 *****************************************************************************/
5256 static HRESULT
5257 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5258 D3DMATERIAL7 *Mat)
5260 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5261 HRESULT hr;
5263 TRACE("iface %p, material %p.\n", iface, Mat);
5265 if (!Mat) return DDERR_INVALIDPARAMS;
5267 wined3d_mutex_lock();
5268 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5269 hr = wined3d_device_set_material(This->wined3d_device, (WINED3DMATERIAL *)Mat);
5270 wined3d_mutex_unlock();
5272 return hr_ddraw_from_wined3d(hr);
5275 static HRESULT WINAPI
5276 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5277 D3DMATERIAL7 *Mat)
5279 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5282 static HRESULT WINAPI
5283 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5284 D3DMATERIAL7 *Mat)
5286 HRESULT hr;
5287 WORD old_fpucw;
5289 old_fpucw = d3d_fpu_setup();
5290 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5291 set_fpu_control_word(old_fpucw);
5293 return hr;
5296 /*****************************************************************************
5297 * IDirect3DDevice7::GetMaterial
5299 * Returns the current material
5301 * Version 7
5303 * Params:
5304 * Mat: D3DMATERIAL7 structure to write the material parameters to
5306 * Returns:
5307 * D3D_OK on success
5308 * DDERR_INVALIDPARAMS if Mat is NULL
5309 * For more details, see IWineD3DDevice::GetMaterial
5311 *****************************************************************************/
5312 static HRESULT
5313 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5314 D3DMATERIAL7 *Mat)
5316 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5317 HRESULT hr;
5319 TRACE("iface %p, material %p.\n", iface, Mat);
5321 wined3d_mutex_lock();
5322 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5323 hr = wined3d_device_get_material(This->wined3d_device, (WINED3DMATERIAL *)Mat);
5324 wined3d_mutex_unlock();
5326 return hr_ddraw_from_wined3d(hr);
5329 static HRESULT WINAPI
5330 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5331 D3DMATERIAL7 *Mat)
5333 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5336 static HRESULT WINAPI
5337 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5338 D3DMATERIAL7 *Mat)
5340 HRESULT hr;
5341 WORD old_fpucw;
5343 old_fpucw = d3d_fpu_setup();
5344 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5345 set_fpu_control_word(old_fpucw);
5347 return hr;
5350 /*****************************************************************************
5351 * IDirect3DDevice7::SetLight
5353 * Assigns a light to a light index, but doesn't activate it yet.
5355 * Version 7, IDirect3DLight uses this method for older versions
5357 * Params:
5358 * LightIndex: The index of the new light
5359 * Light: A D3DLIGHT7 structure describing the light
5361 * Returns:
5362 * D3D_OK on success
5363 * For more details, see IWineD3DDevice::SetLight
5365 *****************************************************************************/
5366 static HRESULT
5367 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5368 DWORD LightIndex,
5369 D3DLIGHT7 *Light)
5371 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5372 HRESULT hr;
5374 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5376 wined3d_mutex_lock();
5377 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5378 hr = wined3d_device_set_light(This->wined3d_device, LightIndex, (struct wined3d_light *)Light);
5379 wined3d_mutex_unlock();
5381 return hr_ddraw_from_wined3d(hr);
5384 static HRESULT WINAPI
5385 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5386 DWORD LightIndex,
5387 D3DLIGHT7 *Light)
5389 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5392 static HRESULT WINAPI
5393 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5394 DWORD LightIndex,
5395 D3DLIGHT7 *Light)
5397 HRESULT hr;
5398 WORD old_fpucw;
5400 old_fpucw = d3d_fpu_setup();
5401 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5402 set_fpu_control_word(old_fpucw);
5404 return hr;
5407 /*****************************************************************************
5408 * IDirect3DDevice7::GetLight
5410 * Returns the light assigned to a light index
5412 * Params:
5413 * Light: Structure to write the light information to
5415 * Returns:
5416 * D3D_OK on success
5417 * DDERR_INVALIDPARAMS if Light is NULL
5418 * For details, see IWineD3DDevice::GetLight
5420 *****************************************************************************/
5421 static HRESULT
5422 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5423 DWORD LightIndex,
5424 D3DLIGHT7 *Light)
5426 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5427 HRESULT rc;
5429 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5431 wined3d_mutex_lock();
5432 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5433 rc = wined3d_device_get_light(This->wined3d_device, LightIndex, (struct wined3d_light *)Light);
5434 wined3d_mutex_unlock();
5436 /* Translate the result. WineD3D returns other values than D3D7 */
5437 return hr_ddraw_from_wined3d(rc);
5440 static HRESULT WINAPI
5441 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5442 DWORD LightIndex,
5443 D3DLIGHT7 *Light)
5445 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5448 static HRESULT WINAPI
5449 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5450 DWORD LightIndex,
5451 D3DLIGHT7 *Light)
5453 HRESULT hr;
5454 WORD old_fpucw;
5456 old_fpucw = d3d_fpu_setup();
5457 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5458 set_fpu_control_word(old_fpucw);
5460 return hr;
5463 /*****************************************************************************
5464 * IDirect3DDevice7::BeginStateBlock
5466 * Begins recording to a stateblock
5468 * Version 7
5470 * Returns:
5471 * D3D_OK on success
5472 * For details see IWineD3DDevice::BeginStateBlock
5474 *****************************************************************************/
5475 static HRESULT
5476 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5478 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5479 HRESULT hr;
5481 TRACE("iface %p.\n", iface);
5483 wined3d_mutex_lock();
5484 hr = wined3d_device_begin_stateblock(This->wined3d_device);
5485 wined3d_mutex_unlock();
5487 return hr_ddraw_from_wined3d(hr);
5490 static HRESULT WINAPI
5491 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5493 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5496 static HRESULT WINAPI
5497 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5499 HRESULT hr;
5500 WORD old_fpucw;
5502 old_fpucw = d3d_fpu_setup();
5503 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5504 set_fpu_control_word(old_fpucw);
5506 return hr;
5509 /*****************************************************************************
5510 * IDirect3DDevice7::EndStateBlock
5512 * Stops recording to a state block and returns the created stateblock
5513 * handle.
5515 * Version 7
5517 * Params:
5518 * BlockHandle: Address to store the stateblock's handle to
5520 * Returns:
5521 * D3D_OK on success
5522 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5523 * See IWineD3DDevice::EndStateBlock for more details
5525 *****************************************************************************/
5526 static HRESULT
5527 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5528 DWORD *BlockHandle)
5530 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5531 struct wined3d_stateblock *wined3d_sb;
5532 HRESULT hr;
5533 DWORD h;
5535 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5537 if(!BlockHandle)
5539 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5540 return DDERR_INVALIDPARAMS;
5543 wined3d_mutex_lock();
5545 hr = wined3d_device_end_stateblock(This->wined3d_device, &wined3d_sb);
5546 if (FAILED(hr))
5548 WARN("Failed to end stateblock, hr %#x.\n", hr);
5549 wined3d_mutex_unlock();
5550 *BlockHandle = 0;
5551 return hr_ddraw_from_wined3d(hr);
5554 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5555 if (h == DDRAW_INVALID_HANDLE)
5557 ERR("Failed to allocate a stateblock handle.\n");
5558 wined3d_stateblock_decref(wined3d_sb);
5559 wined3d_mutex_unlock();
5560 *BlockHandle = 0;
5561 return DDERR_OUTOFMEMORY;
5564 wined3d_mutex_unlock();
5565 *BlockHandle = h + 1;
5567 return hr_ddraw_from_wined3d(hr);
5570 static HRESULT WINAPI
5571 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5572 DWORD *BlockHandle)
5574 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5577 static HRESULT WINAPI
5578 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5579 DWORD *BlockHandle)
5581 HRESULT hr;
5582 WORD old_fpucw;
5584 old_fpucw = d3d_fpu_setup();
5585 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5586 set_fpu_control_word(old_fpucw);
5588 return hr;
5591 /*****************************************************************************
5592 * IDirect3DDevice7::PreLoad
5594 * Allows the app to signal that a texture will be used soon, to allow
5595 * the Direct3DDevice to load it to the video card in the meantime.
5597 * Version 7
5599 * Params:
5600 * Texture: The texture to preload
5602 * Returns:
5603 * D3D_OK on success
5604 * DDERR_INVALIDPARAMS if Texture is NULL
5605 * See IWineD3DSurface::PreLoad for details
5607 *****************************************************************************/
5608 static HRESULT
5609 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5610 IDirectDrawSurface7 *Texture)
5612 IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
5614 TRACE("iface %p, texture %p.\n", iface, Texture);
5616 if(!Texture)
5617 return DDERR_INVALIDPARAMS;
5619 wined3d_mutex_lock();
5620 wined3d_surface_preload(surf->wined3d_surface);
5621 wined3d_mutex_unlock();
5623 return D3D_OK;
5626 static HRESULT WINAPI
5627 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5628 IDirectDrawSurface7 *Texture)
5630 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5633 static HRESULT WINAPI
5634 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5635 IDirectDrawSurface7 *Texture)
5637 HRESULT hr;
5638 WORD old_fpucw;
5640 old_fpucw = d3d_fpu_setup();
5641 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5642 set_fpu_control_word(old_fpucw);
5644 return hr;
5647 /*****************************************************************************
5648 * IDirect3DDevice7::ApplyStateBlock
5650 * Activates the state stored in a state block handle.
5652 * Params:
5653 * BlockHandle: The stateblock handle to activate
5655 * Returns:
5656 * D3D_OK on success
5657 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5659 *****************************************************************************/
5660 static HRESULT
5661 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5662 DWORD BlockHandle)
5664 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5665 struct wined3d_stateblock *wined3d_sb;
5666 HRESULT hr;
5668 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5670 wined3d_mutex_lock();
5671 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5672 if (!wined3d_sb)
5674 WARN("Invalid stateblock handle.\n");
5675 wined3d_mutex_unlock();
5676 return D3DERR_INVALIDSTATEBLOCK;
5679 hr = wined3d_stateblock_apply(wined3d_sb);
5680 wined3d_mutex_unlock();
5682 return hr_ddraw_from_wined3d(hr);
5685 static HRESULT WINAPI
5686 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5687 DWORD BlockHandle)
5689 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5692 static HRESULT WINAPI
5693 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5694 DWORD BlockHandle)
5696 HRESULT hr;
5697 WORD old_fpucw;
5699 old_fpucw = d3d_fpu_setup();
5700 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5701 set_fpu_control_word(old_fpucw);
5703 return hr;
5706 /*****************************************************************************
5707 * IDirect3DDevice7::CaptureStateBlock
5709 * Updates a stateblock's values to the values currently set for the device
5711 * Version 7
5713 * Params:
5714 * BlockHandle: Stateblock to update
5716 * Returns:
5717 * D3D_OK on success
5718 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5719 * See IWineD3DDevice::CaptureStateBlock for more details
5721 *****************************************************************************/
5722 static HRESULT
5723 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5724 DWORD BlockHandle)
5726 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5727 struct wined3d_stateblock *wined3d_sb;
5728 HRESULT hr;
5730 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5732 wined3d_mutex_lock();
5733 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5734 if (!wined3d_sb)
5736 WARN("Invalid stateblock handle.\n");
5737 wined3d_mutex_unlock();
5738 return D3DERR_INVALIDSTATEBLOCK;
5741 hr = wined3d_stateblock_capture(wined3d_sb);
5742 wined3d_mutex_unlock();
5744 return hr_ddraw_from_wined3d(hr);
5747 static HRESULT WINAPI
5748 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5749 DWORD BlockHandle)
5751 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5754 static HRESULT WINAPI
5755 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5756 DWORD BlockHandle)
5758 HRESULT hr;
5759 WORD old_fpucw;
5761 old_fpucw = d3d_fpu_setup();
5762 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5763 set_fpu_control_word(old_fpucw);
5765 return hr;
5768 /*****************************************************************************
5769 * IDirect3DDevice7::DeleteStateBlock
5771 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5773 * Version 7
5775 * Params:
5776 * BlockHandle: Stateblock handle to delete
5778 * Returns:
5779 * D3D_OK on success
5780 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5782 *****************************************************************************/
5783 static HRESULT
5784 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5785 DWORD BlockHandle)
5787 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5788 struct wined3d_stateblock *wined3d_sb;
5789 ULONG ref;
5791 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5793 wined3d_mutex_lock();
5795 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5796 if (!wined3d_sb)
5798 WARN("Invalid stateblock handle.\n");
5799 wined3d_mutex_unlock();
5800 return D3DERR_INVALIDSTATEBLOCK;
5803 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5805 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5808 wined3d_mutex_unlock();
5810 return D3D_OK;
5813 static HRESULT WINAPI
5814 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5815 DWORD BlockHandle)
5817 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5820 static HRESULT WINAPI
5821 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5822 DWORD BlockHandle)
5824 HRESULT hr;
5825 WORD old_fpucw;
5827 old_fpucw = d3d_fpu_setup();
5828 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5829 set_fpu_control_word(old_fpucw);
5831 return hr;
5834 /*****************************************************************************
5835 * IDirect3DDevice7::CreateStateBlock
5837 * Creates a new state block handle.
5839 * Version 7
5841 * Params:
5842 * Type: The state block type
5843 * BlockHandle: Address to write the created handle to
5845 * Returns:
5846 * D3D_OK on success
5847 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5849 *****************************************************************************/
5850 static HRESULT
5851 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5852 D3DSTATEBLOCKTYPE Type,
5853 DWORD *BlockHandle)
5855 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5856 struct wined3d_stateblock *wined3d_sb;
5857 HRESULT hr;
5858 DWORD h;
5860 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5862 if(!BlockHandle)
5864 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5865 return DDERR_INVALIDPARAMS;
5867 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5868 Type != D3DSBT_VERTEXSTATE ) {
5869 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5870 return DDERR_INVALIDPARAMS;
5873 wined3d_mutex_lock();
5875 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5876 hr = wined3d_stateblock_create(This->wined3d_device, Type, &wined3d_sb);
5877 if (FAILED(hr))
5879 WARN("Failed to create stateblock, hr %#x.\n", hr);
5880 wined3d_mutex_unlock();
5881 return hr_ddraw_from_wined3d(hr);
5884 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5885 if (h == DDRAW_INVALID_HANDLE)
5887 ERR("Failed to allocate stateblock handle.\n");
5888 wined3d_stateblock_decref(wined3d_sb);
5889 wined3d_mutex_unlock();
5890 return DDERR_OUTOFMEMORY;
5893 *BlockHandle = h + 1;
5894 wined3d_mutex_unlock();
5896 return hr_ddraw_from_wined3d(hr);
5899 static HRESULT WINAPI
5900 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5901 D3DSTATEBLOCKTYPE Type,
5902 DWORD *BlockHandle)
5904 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5907 static HRESULT WINAPI
5908 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5909 D3DSTATEBLOCKTYPE Type,
5910 DWORD *BlockHandle)
5912 HRESULT hr;
5913 WORD old_fpucw;
5915 old_fpucw = d3d_fpu_setup();
5916 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5917 set_fpu_control_word(old_fpucw);
5919 return hr;
5922 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5923 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
5924 IDirectDrawSurfaceImpl *src)
5926 IDirectDrawSurfaceImpl *src_level, *dest_level;
5927 IDirectDrawSurface7 *temp;
5928 DDSURFACEDESC2 ddsd;
5929 BOOL levelFound; /* at least one suitable sublevel in dest found */
5931 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5932 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5933 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5935 levelFound = FALSE;
5937 src_level = src;
5938 dest_level = dest;
5940 for (;src_level && dest_level;)
5942 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5943 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5945 levelFound = TRUE;
5947 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5948 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5949 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5951 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5953 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5956 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5957 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5958 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5960 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5962 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5965 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5966 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5968 return !dest_level && levelFound;
5971 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5972 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
5973 IDirectDrawSurfaceImpl *dest,
5974 IDirectDrawSurfaceImpl *src,
5975 const POINT *DestPoint,
5976 const RECT *SrcRect)
5978 IDirectDrawSurfaceImpl *src_level, *dest_level;
5979 IDirectDrawSurface7 *temp;
5980 DDSURFACEDESC2 ddsd;
5981 POINT point;
5982 RECT src_rect;
5983 HRESULT hr;
5984 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5985 DWORD ckeyflag;
5986 DDCOLORKEY ddckey;
5988 /* Copy palette, if possible. */
5989 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
5990 IDirectDrawSurface7_GetPalette(&dest->IDirectDrawSurface7_iface, &pal);
5992 if (pal_src != NULL && pal != NULL)
5994 PALETTEENTRY palent[256];
5996 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5997 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
6000 if (pal) IDirectDrawPalette_Release(pal);
6001 if (pal_src) IDirectDrawPalette_Release(pal_src);
6003 /* Copy colorkeys, if present. */
6004 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6006 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6008 if (SUCCEEDED(hr))
6010 IDirectDrawSurface7_SetColorKey(&dest->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6014 src_level = src;
6015 dest_level = dest;
6017 point = *DestPoint;
6018 src_rect = *SrcRect;
6020 for (;src_level && dest_level;)
6022 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6023 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6025 UINT src_w = src_rect.right - src_rect.left;
6026 UINT src_h = src_rect.bottom - src_rect.top;
6027 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
6029 if (FAILED(hr = wined3d_surface_blt(dest_level->wined3d_surface, &dst_rect,
6030 src_level->wined3d_surface, &src_rect, 0, NULL, WINED3DTEXF_POINT)))
6031 ERR("Blit failed, hr %#x.\n", hr);
6033 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6034 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6035 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6037 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6039 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6042 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6043 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6044 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6046 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6048 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6050 point.x /= 2;
6051 point.y /= 2;
6053 src_rect.top /= 2;
6054 src_rect.left /= 2;
6055 src_rect.right = (src_rect.right + 1) / 2;
6056 src_rect.bottom = (src_rect.bottom + 1) / 2;
6059 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6060 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6063 /*****************************************************************************
6064 * IDirect3DDevice7::Load
6066 * Loads a rectangular area from the source into the destination texture.
6067 * It can also copy the source to the faces of a cubic environment map
6069 * Version 7
6071 * Params:
6072 * DestTex: Destination texture
6073 * DestPoint: Point in the destination where the source image should be
6074 * written to
6075 * SrcTex: Source texture
6076 * SrcRect: Source rectangle
6077 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6078 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6079 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6081 * Returns:
6082 * D3D_OK on success
6083 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6086 *****************************************************************************/
6088 static HRESULT
6089 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6090 IDirectDrawSurface7 *DestTex,
6091 POINT *DestPoint,
6092 IDirectDrawSurface7 *SrcTex,
6093 RECT *SrcRect,
6094 DWORD Flags)
6096 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6097 IDirectDrawSurfaceImpl *dest = unsafe_impl_from_IDirectDrawSurface7(DestTex);
6098 IDirectDrawSurfaceImpl *src = unsafe_impl_from_IDirectDrawSurface7(SrcTex);
6099 POINT destpoint;
6100 RECT srcrect;
6102 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6103 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6105 if( (!src) || (!dest) )
6106 return DDERR_INVALIDPARAMS;
6108 wined3d_mutex_lock();
6110 if (SrcRect) srcrect = *SrcRect;
6111 else
6113 srcrect.left = srcrect.top = 0;
6114 srcrect.right = src->surface_desc.dwWidth;
6115 srcrect.bottom = src->surface_desc.dwHeight;
6118 if (DestPoint) destpoint = *DestPoint;
6119 else
6121 destpoint.x = destpoint.y = 0;
6123 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6124 * destination can be a subset of mip levels, in which case actual coordinates used
6125 * for it may be divided. If any dimension of dest is larger than source, it can't be
6126 * mip level subset, so an error can be returned early.
6128 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6129 srcrect.right > src->surface_desc.dwWidth ||
6130 srcrect.bottom > src->surface_desc.dwHeight ||
6131 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6132 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6133 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6134 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6136 wined3d_mutex_unlock();
6137 return DDERR_INVALIDPARAMS;
6140 /* Must be top level surfaces. */
6141 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6142 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6144 wined3d_mutex_unlock();
6145 return DDERR_INVALIDPARAMS;
6148 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6150 DWORD src_face_flag, dest_face_flag;
6151 IDirectDrawSurfaceImpl *src_face, *dest_face;
6152 IDirectDrawSurface7 *temp;
6153 DDSURFACEDESC2 ddsd;
6154 int i;
6156 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6158 wined3d_mutex_unlock();
6159 return DDERR_INVALIDPARAMS;
6162 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6163 * time it's actual surface loading. */
6164 for (i = 0; i < 2; i++)
6166 dest_face = dest;
6167 src_face = src;
6169 for (;dest_face && src_face;)
6171 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6172 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6174 if (src_face_flag == dest_face_flag)
6176 if (i == 0)
6178 /* Destination mip levels must be subset of source mip levels. */
6179 if (!is_mip_level_subset(dest_face, src_face))
6181 wined3d_mutex_unlock();
6182 return DDERR_INVALIDPARAMS;
6185 else if (Flags & dest_face_flag)
6187 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6190 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6192 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6193 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6194 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6196 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6198 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6200 else
6202 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6204 src_face = NULL;
6208 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6210 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6211 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6212 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6214 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6216 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6218 else
6220 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6222 dest_face = NULL;
6226 if (i == 0)
6228 /* Native returns error if src faces are not subset of dest faces. */
6229 if (src_face)
6231 wined3d_mutex_unlock();
6232 return DDERR_INVALIDPARAMS;
6237 wined3d_mutex_unlock();
6238 return D3D_OK;
6240 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6242 wined3d_mutex_unlock();
6243 return DDERR_INVALIDPARAMS;
6246 /* Handle non cube map textures. */
6248 /* Destination mip levels must be subset of source mip levels. */
6249 if (!is_mip_level_subset(dest, src))
6251 wined3d_mutex_unlock();
6252 return DDERR_INVALIDPARAMS;
6255 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6257 wined3d_mutex_unlock();
6259 return D3D_OK;
6262 static HRESULT WINAPI
6263 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6264 IDirectDrawSurface7 *DestTex,
6265 POINT *DestPoint,
6266 IDirectDrawSurface7 *SrcTex,
6267 RECT *SrcRect,
6268 DWORD Flags)
6270 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6273 static HRESULT WINAPI
6274 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6275 IDirectDrawSurface7 *DestTex,
6276 POINT *DestPoint,
6277 IDirectDrawSurface7 *SrcTex,
6278 RECT *SrcRect,
6279 DWORD Flags)
6281 HRESULT hr;
6282 WORD old_fpucw;
6284 old_fpucw = d3d_fpu_setup();
6285 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6286 set_fpu_control_word(old_fpucw);
6288 return hr;
6291 /*****************************************************************************
6292 * IDirect3DDevice7::LightEnable
6294 * Enables or disables a light
6296 * Version 7, IDirect3DLight uses this method too.
6298 * Params:
6299 * LightIndex: The index of the light to enable / disable
6300 * Enable: Enable or disable the light
6302 * Returns:
6303 * D3D_OK on success
6304 * For more details, see IWineD3DDevice::SetLightEnable
6306 *****************************************************************************/
6307 static HRESULT
6308 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6309 DWORD LightIndex,
6310 BOOL Enable)
6312 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6313 HRESULT hr;
6315 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6317 wined3d_mutex_lock();
6318 hr = wined3d_device_set_light_enable(This->wined3d_device, LightIndex, Enable);
6319 wined3d_mutex_unlock();
6321 return hr_ddraw_from_wined3d(hr);
6324 static HRESULT WINAPI
6325 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6326 DWORD LightIndex,
6327 BOOL Enable)
6329 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6332 static HRESULT WINAPI
6333 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6334 DWORD LightIndex,
6335 BOOL Enable)
6337 HRESULT hr;
6338 WORD old_fpucw;
6340 old_fpucw = d3d_fpu_setup();
6341 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6342 set_fpu_control_word(old_fpucw);
6344 return hr;
6347 /*****************************************************************************
6348 * IDirect3DDevice7::GetLightEnable
6350 * Retrieves if the light with the given index is enabled or not
6352 * Version 7
6354 * Params:
6355 * LightIndex: Index of desired light
6356 * Enable: Pointer to a BOOL which contains the result
6358 * Returns:
6359 * D3D_OK on success
6360 * DDERR_INVALIDPARAMS if Enable is NULL
6361 * See IWineD3DDevice::GetLightEnable for more details
6363 *****************************************************************************/
6364 static HRESULT
6365 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6366 DWORD LightIndex,
6367 BOOL* Enable)
6369 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6370 HRESULT hr;
6372 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6374 if(!Enable)
6375 return DDERR_INVALIDPARAMS;
6377 wined3d_mutex_lock();
6378 hr = wined3d_device_get_light_enable(This->wined3d_device, LightIndex, Enable);
6379 wined3d_mutex_unlock();
6381 return hr_ddraw_from_wined3d(hr);
6384 static HRESULT WINAPI
6385 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6386 DWORD LightIndex,
6387 BOOL* Enable)
6389 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6392 static HRESULT WINAPI
6393 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6394 DWORD LightIndex,
6395 BOOL* Enable)
6397 HRESULT hr;
6398 WORD old_fpucw;
6400 old_fpucw = d3d_fpu_setup();
6401 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6402 set_fpu_control_word(old_fpucw);
6404 return hr;
6407 /*****************************************************************************
6408 * IDirect3DDevice7::SetClipPlane
6410 * Sets custom clipping plane
6412 * Version 7
6414 * Params:
6415 * Index: The index of the clipping plane
6416 * PlaneEquation: An equation defining the clipping plane
6418 * Returns:
6419 * D3D_OK on success
6420 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6421 * See IWineD3DDevice::SetClipPlane for more details
6423 *****************************************************************************/
6424 static HRESULT
6425 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6426 DWORD Index,
6427 D3DVALUE* PlaneEquation)
6429 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6430 HRESULT hr;
6432 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6434 if(!PlaneEquation)
6435 return DDERR_INVALIDPARAMS;
6437 wined3d_mutex_lock();
6438 hr = wined3d_device_set_clip_plane(This->wined3d_device, Index, PlaneEquation);
6439 wined3d_mutex_unlock();
6441 return hr;
6444 static HRESULT WINAPI
6445 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6446 DWORD Index,
6447 D3DVALUE* PlaneEquation)
6449 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6452 static HRESULT WINAPI
6453 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6454 DWORD Index,
6455 D3DVALUE* PlaneEquation)
6457 HRESULT hr;
6458 WORD old_fpucw;
6460 old_fpucw = d3d_fpu_setup();
6461 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6462 set_fpu_control_word(old_fpucw);
6464 return hr;
6467 /*****************************************************************************
6468 * IDirect3DDevice7::GetClipPlane
6470 * Returns the clipping plane with a specific index
6472 * Params:
6473 * Index: The index of the desired plane
6474 * PlaneEquation: Address to store the plane equation to
6476 * Returns:
6477 * D3D_OK on success
6478 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6479 * See IWineD3DDevice::GetClipPlane for more details
6481 *****************************************************************************/
6482 static HRESULT
6483 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6484 DWORD Index,
6485 D3DVALUE* PlaneEquation)
6487 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6488 HRESULT hr;
6490 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6492 if(!PlaneEquation)
6493 return DDERR_INVALIDPARAMS;
6495 wined3d_mutex_lock();
6496 hr = wined3d_device_get_clip_plane(This->wined3d_device, Index, PlaneEquation);
6497 wined3d_mutex_unlock();
6499 return hr;
6502 static HRESULT WINAPI
6503 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6504 DWORD Index,
6505 D3DVALUE* PlaneEquation)
6507 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6510 static HRESULT WINAPI
6511 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6512 DWORD Index,
6513 D3DVALUE* PlaneEquation)
6515 HRESULT hr;
6516 WORD old_fpucw;
6518 old_fpucw = d3d_fpu_setup();
6519 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6520 set_fpu_control_word(old_fpucw);
6522 return hr;
6525 /*****************************************************************************
6526 * IDirect3DDevice7::GetInfo
6528 * Retrieves some information about the device. The DirectX sdk says that
6529 * this version returns S_FALSE for all retail builds of DirectX, that's what
6530 * this implementation does.
6532 * Params:
6533 * DevInfoID: Information type requested
6534 * DevInfoStruct: Pointer to a structure to store the info to
6535 * Size: Size of the structure
6537 * Returns:
6538 * S_FALSE, because it's a non-debug driver
6540 *****************************************************************************/
6541 static HRESULT WINAPI
6542 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6543 DWORD DevInfoID,
6544 void *DevInfoStruct,
6545 DWORD Size)
6547 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6548 iface, DevInfoID, DevInfoStruct, Size);
6550 if (TRACE_ON(ddraw))
6552 TRACE(" info requested : ");
6553 switch (DevInfoID)
6555 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6556 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6557 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6558 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6562 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6565 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6566 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6567 * are not duplicated.
6569 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6570 * has already been setup for optimal d3d operation.
6572 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6573 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6574 * by Sacrifice (game). */
6575 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6577 /*** IUnknown Methods ***/
6578 IDirect3DDeviceImpl_7_QueryInterface,
6579 IDirect3DDeviceImpl_7_AddRef,
6580 IDirect3DDeviceImpl_7_Release,
6581 /*** IDirect3DDevice7 ***/
6582 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6583 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6584 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6585 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6586 IDirect3DDeviceImpl_7_GetDirect3D,
6587 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6588 IDirect3DDeviceImpl_7_GetRenderTarget,
6589 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6590 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6591 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6592 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6593 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6594 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6595 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6596 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6597 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6598 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6599 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6600 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6601 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6602 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6603 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6604 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6605 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6606 IDirect3DDeviceImpl_7_SetClipStatus,
6607 IDirect3DDeviceImpl_7_GetClipStatus,
6608 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6609 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6610 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6611 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6612 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6613 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6614 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6615 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6616 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6617 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6618 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6619 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6620 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6621 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6622 IDirect3DDeviceImpl_7_Load_FPUSetup,
6623 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6624 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6625 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6626 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6627 IDirect3DDeviceImpl_7_GetInfo
6630 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6632 /*** IUnknown Methods ***/
6633 IDirect3DDeviceImpl_7_QueryInterface,
6634 IDirect3DDeviceImpl_7_AddRef,
6635 IDirect3DDeviceImpl_7_Release,
6636 /*** IDirect3DDevice7 ***/
6637 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6638 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6639 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6640 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6641 IDirect3DDeviceImpl_7_GetDirect3D,
6642 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6643 IDirect3DDeviceImpl_7_GetRenderTarget,
6644 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6645 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6646 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6647 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6648 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6649 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6650 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6651 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6652 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6653 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6654 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6655 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6656 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6657 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6658 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6659 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6660 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6661 IDirect3DDeviceImpl_7_SetClipStatus,
6662 IDirect3DDeviceImpl_7_GetClipStatus,
6663 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6664 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6665 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6666 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6667 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6668 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6669 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6670 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6671 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6672 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6673 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6674 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6675 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6676 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6677 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6678 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6679 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6680 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6681 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6682 IDirect3DDeviceImpl_7_GetInfo
6685 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6687 /*** IUnknown Methods ***/
6688 IDirect3DDeviceImpl_3_QueryInterface,
6689 IDirect3DDeviceImpl_3_AddRef,
6690 IDirect3DDeviceImpl_3_Release,
6691 /*** IDirect3DDevice3 ***/
6692 IDirect3DDeviceImpl_3_GetCaps,
6693 IDirect3DDeviceImpl_3_GetStats,
6694 IDirect3DDeviceImpl_3_AddViewport,
6695 IDirect3DDeviceImpl_3_DeleteViewport,
6696 IDirect3DDeviceImpl_3_NextViewport,
6697 IDirect3DDeviceImpl_3_EnumTextureFormats,
6698 IDirect3DDeviceImpl_3_BeginScene,
6699 IDirect3DDeviceImpl_3_EndScene,
6700 IDirect3DDeviceImpl_3_GetDirect3D,
6701 IDirect3DDeviceImpl_3_SetCurrentViewport,
6702 IDirect3DDeviceImpl_3_GetCurrentViewport,
6703 IDirect3DDeviceImpl_3_SetRenderTarget,
6704 IDirect3DDeviceImpl_3_GetRenderTarget,
6705 IDirect3DDeviceImpl_3_Begin,
6706 IDirect3DDeviceImpl_3_BeginIndexed,
6707 IDirect3DDeviceImpl_3_Vertex,
6708 IDirect3DDeviceImpl_3_Index,
6709 IDirect3DDeviceImpl_3_End,
6710 IDirect3DDeviceImpl_3_GetRenderState,
6711 IDirect3DDeviceImpl_3_SetRenderState,
6712 IDirect3DDeviceImpl_3_GetLightState,
6713 IDirect3DDeviceImpl_3_SetLightState,
6714 IDirect3DDeviceImpl_3_SetTransform,
6715 IDirect3DDeviceImpl_3_GetTransform,
6716 IDirect3DDeviceImpl_3_MultiplyTransform,
6717 IDirect3DDeviceImpl_3_DrawPrimitive,
6718 IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6719 IDirect3DDeviceImpl_3_SetClipStatus,
6720 IDirect3DDeviceImpl_3_GetClipStatus,
6721 IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6722 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6723 IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6724 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6725 IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6726 IDirect3DDeviceImpl_3_GetTexture,
6727 IDirect3DDeviceImpl_3_SetTexture,
6728 IDirect3DDeviceImpl_3_GetTextureStageState,
6729 IDirect3DDeviceImpl_3_SetTextureStageState,
6730 IDirect3DDeviceImpl_3_ValidateDevice
6733 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6735 /*** IUnknown Methods ***/
6736 IDirect3DDeviceImpl_2_QueryInterface,
6737 IDirect3DDeviceImpl_2_AddRef,
6738 IDirect3DDeviceImpl_2_Release,
6739 /*** IDirect3DDevice2 ***/
6740 IDirect3DDeviceImpl_2_GetCaps,
6741 IDirect3DDeviceImpl_2_SwapTextureHandles,
6742 IDirect3DDeviceImpl_2_GetStats,
6743 IDirect3DDeviceImpl_2_AddViewport,
6744 IDirect3DDeviceImpl_2_DeleteViewport,
6745 IDirect3DDeviceImpl_2_NextViewport,
6746 IDirect3DDeviceImpl_2_EnumTextureFormats,
6747 IDirect3DDeviceImpl_2_BeginScene,
6748 IDirect3DDeviceImpl_2_EndScene,
6749 IDirect3DDeviceImpl_2_GetDirect3D,
6750 IDirect3DDeviceImpl_2_SetCurrentViewport,
6751 IDirect3DDeviceImpl_2_GetCurrentViewport,
6752 IDirect3DDeviceImpl_2_SetRenderTarget,
6753 IDirect3DDeviceImpl_2_GetRenderTarget,
6754 IDirect3DDeviceImpl_2_Begin,
6755 IDirect3DDeviceImpl_2_BeginIndexed,
6756 IDirect3DDeviceImpl_2_Vertex,
6757 IDirect3DDeviceImpl_2_Index,
6758 IDirect3DDeviceImpl_2_End,
6759 IDirect3DDeviceImpl_2_GetRenderState,
6760 IDirect3DDeviceImpl_2_SetRenderState,
6761 IDirect3DDeviceImpl_2_GetLightState,
6762 IDirect3DDeviceImpl_2_SetLightState,
6763 IDirect3DDeviceImpl_2_SetTransform,
6764 IDirect3DDeviceImpl_2_GetTransform,
6765 IDirect3DDeviceImpl_2_MultiplyTransform,
6766 IDirect3DDeviceImpl_2_DrawPrimitive,
6767 IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6768 IDirect3DDeviceImpl_2_SetClipStatus,
6769 IDirect3DDeviceImpl_2_GetClipStatus
6772 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6774 /*** IUnknown Methods ***/
6775 IDirect3DDeviceImpl_1_QueryInterface,
6776 IDirect3DDeviceImpl_1_AddRef,
6777 IDirect3DDeviceImpl_1_Release,
6778 /*** IDirect3DDevice1 ***/
6779 IDirect3DDeviceImpl_1_Initialize,
6780 IDirect3DDeviceImpl_1_GetCaps,
6781 IDirect3DDeviceImpl_1_SwapTextureHandles,
6782 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6783 IDirect3DDeviceImpl_1_GetStats,
6784 IDirect3DDeviceImpl_1_Execute,
6785 IDirect3DDeviceImpl_1_AddViewport,
6786 IDirect3DDeviceImpl_1_DeleteViewport,
6787 IDirect3DDeviceImpl_1_NextViewport,
6788 IDirect3DDeviceImpl_1_Pick,
6789 IDirect3DDeviceImpl_1_GetPickRecords,
6790 IDirect3DDeviceImpl_1_EnumTextureFormats,
6791 IDirect3DDeviceImpl_1_CreateMatrix,
6792 IDirect3DDeviceImpl_1_SetMatrix,
6793 IDirect3DDeviceImpl_1_GetMatrix,
6794 IDirect3DDeviceImpl_1_DeleteMatrix,
6795 IDirect3DDeviceImpl_1_BeginScene,
6796 IDirect3DDeviceImpl_1_EndScene,
6797 IDirect3DDeviceImpl_1_GetDirect3D
6800 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6802 if (!iface) return NULL;
6803 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6804 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice7_iface);
6807 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6809 if (!iface) return NULL;
6810 assert(iface->lpVtbl == &d3d_device3_vtbl);
6811 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice3_iface);
6814 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6816 if (!iface) return NULL;
6817 assert(iface->lpVtbl == &d3d_device2_vtbl);
6818 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice2_iface);
6821 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6823 if (!iface) return NULL;
6824 assert(iface->lpVtbl == &d3d_device1_vtbl);
6825 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice_iface);
6828 /*****************************************************************************
6829 * IDirect3DDeviceImpl_UpdateDepthStencil
6831 * Checks the current render target for attached depth stencils and sets the
6832 * WineD3D depth stencil accordingly.
6834 * Returns:
6835 * The depth stencil state to set if creating the device
6837 *****************************************************************************/
6838 WINED3DZBUFFERTYPE
6839 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6841 IDirectDrawSurface7 *depthStencil = NULL;
6842 IDirectDrawSurfaceImpl *dsi;
6843 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6845 IDirectDrawSurface7_GetAttachedSurface(&This->target->IDirectDrawSurface7_iface, &depthcaps, &depthStencil);
6846 if(!depthStencil)
6848 TRACE("Setting wined3d depth stencil to NULL\n");
6849 wined3d_device_set_depth_stencil(This->wined3d_device, NULL);
6850 return WINED3DZB_FALSE;
6853 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6854 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
6855 wined3d_device_set_depth_stencil(This->wined3d_device, dsi->wined3d_surface);
6857 IDirectDrawSurface7_Release(depthStencil);
6858 return WINED3DZB_TRUE;
6861 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
6863 HRESULT hr;
6865 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6866 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6867 else
6868 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
6870 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6871 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6872 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6873 device->ref = 1;
6874 device->ddraw = ddraw;
6875 device->target = target;
6876 list_init(&device->viewport_list);
6878 if (!ddraw_handle_table_init(&device->handle_table, 64))
6880 ERR("Failed to initialize handle table.\n");
6881 return DDERR_OUTOFMEMORY;
6884 device->legacyTextureBlending = FALSE;
6886 /* Create an index buffer, it's needed for indexed drawing */
6887 hr = wined3d_buffer_create_ib(ddraw->wined3d_device, 0x40000 /* Length. Don't know how long it should be */,
6888 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, NULL,
6889 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
6890 if (FAILED(hr))
6892 ERR("Failed to create an index buffer, hr %#x.\n", hr);
6893 ddraw_handle_table_destroy(&device->handle_table);
6894 return hr;
6897 /* This is for convenience. */
6898 device->wined3d_device = ddraw->wined3d_device;
6899 wined3d_device_incref(ddraw->wined3d_device);
6901 /* Render to the back buffer */
6902 hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
6903 if (FAILED(hr))
6905 ERR("Failed to set render target, hr %#x.\n", hr);
6906 wined3d_buffer_decref(device->indexbuffer);
6907 ddraw_handle_table_destroy(&device->handle_table);
6908 return hr;
6911 /* FIXME: This is broken. The target AddRef() makes some sense, because
6912 * we store a pointer during initialization, but then that's also where
6913 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6914 /* AddRef the render target. Also AddRef the render target from ddraw,
6915 * because if it is released before the app releases the D3D device, the
6916 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6918 * In most cases, those surfaces are the same anyway, but this will simply
6919 * add another ref which is released when the device is destroyed. */
6920 IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
6921 IDirectDrawSurface7_AddRef(&ddraw->d3d_target->IDirectDrawSurface7_iface);
6923 ddraw->d3ddevice = device;
6925 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3DRS_ZENABLE,
6926 IDirect3DDeviceImpl_UpdateDepthStencil(device));
6928 return D3D_OK;