wrc: Fix parsing of virtkey accelerators.
[wine/multimedia.git] / dlls / ddraw / device.c
blob72c3801e2e3e9e9eb1e303fb98c964b6761609ea
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 /* DirectDrawSurface */
183 else if (IsEqualGUID(&IID_IDirectDrawSurface, refiid) && This->from_surface)
185 *obj = &This->target->IDirectDrawSurface_iface;
186 TRACE("Returning IDirectDrawSurface interface %p.\n", *obj);
189 /* Unknown interface */
190 else
192 ERR("(%p)->(%s, %p): No interface found\n", This, debugstr_guid(refiid), obj);
193 return E_NOINTERFACE;
196 /* AddRef the returned interface */
197 IUnknown_AddRef( (IUnknown *) *obj);
198 return D3D_OK;
201 static HRESULT WINAPI IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface, REFIID riid,
202 void **obj)
204 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
205 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
207 return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obj);
210 static HRESULT WINAPI IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface, REFIID riid,
211 void **obj)
213 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
214 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
216 return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obj);
219 static HRESULT WINAPI IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface, REFIID riid,
220 void **obp)
222 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
223 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
225 return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obp);
228 /*****************************************************************************
229 * IDirect3DDevice7::AddRef
231 * Increases the refcount....
232 * The most exciting Method, definitely
234 * Exists in Version 1, 2, 3 and 7
236 * Returns:
237 * The new refcount
239 *****************************************************************************/
240 static ULONG WINAPI
241 IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
243 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
244 ULONG ref = InterlockedIncrement(&This->ref);
246 TRACE("%p increasing refcount to %u.\n", This, ref);
248 return ref;
251 static ULONG WINAPI IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
253 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
254 TRACE("iface %p.\n", iface);
256 return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
259 static ULONG WINAPI IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
261 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
262 TRACE("iface %p.\n", iface);
264 return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
267 static ULONG WINAPI IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
269 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
270 TRACE("iface %p.\n", iface);
272 return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
275 /*****************************************************************************
276 * IDirect3DDevice7::Release
278 * Decreases the refcount of the interface
279 * When the refcount is reduced to 0, the object is destroyed.
281 * Exists in Version 1, 2, 3 and 7
283 * Returns:d
284 * The new refcount
286 *****************************************************************************/
287 static ULONG WINAPI
288 IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
290 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
291 ULONG ref = InterlockedDecrement(&This->ref);
293 TRACE("%p decreasing refcount to %u.\n", This, ref);
295 /* This method doesn't destroy the WineD3DDevice, because it's still in use for
296 * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
297 * when the render target is released
299 if (ref == 0)
301 DWORD i;
303 wined3d_mutex_lock();
305 /* There is no need to unset any resources here, wined3d will take
306 * care of that on Uninit3D(). */
308 /* Free the index buffer. */
309 wined3d_buffer_decref(This->indexbuffer);
311 /* Set the device up to render to the front buffer since the back
312 * buffer will vanish soon. */
313 wined3d_device_set_render_target(This->wined3d_device, 0,
314 This->ddraw->wined3d_frontbuffer, TRUE);
316 /* Release the WineD3DDevice. This won't destroy it. */
317 if (!wined3d_device_decref(This->wined3d_device))
318 ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This->wined3d_device);
320 /* The texture handles should be unset by now, but there might be some bits
321 * missing in our reference counting(needs test). Do a sanity check. */
322 for (i = 0; i < This->handle_table.entry_count; ++i)
324 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
326 switch (entry->type)
328 case DDRAW_HANDLE_FREE:
329 break;
331 case DDRAW_HANDLE_MATERIAL:
333 IDirect3DMaterialImpl *m = entry->object;
334 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
335 m->Handle = 0;
336 break;
339 case DDRAW_HANDLE_MATRIX:
341 /* No FIXME here because this might happen because of sloppy applications. */
342 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
343 IDirect3DDevice_DeleteMatrix(&This->IDirect3DDevice_iface, i + 1);
344 break;
347 case DDRAW_HANDLE_STATEBLOCK:
349 /* No FIXME here because this might happen because of sloppy applications. */
350 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
351 IDirect3DDevice7_DeleteStateBlock(iface, i + 1);
352 break;
355 case DDRAW_HANDLE_SURFACE:
357 IDirectDrawSurfaceImpl *surf = entry->object;
358 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
359 surf->Handle = 0;
360 break;
363 default:
364 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
365 break;
369 ddraw_handle_table_destroy(&This->handle_table);
371 TRACE("Releasing target %p.\n", This->target);
372 /* Release the render target and the WineD3D render target
373 * (See IDirect3D7::CreateDevice for more comments on this)
375 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
376 TRACE("Target release done\n");
378 This->ddraw->d3ddevice = NULL;
380 /* Now free the structure */
381 HeapFree(GetProcessHeap(), 0, This);
382 wined3d_mutex_unlock();
385 TRACE("Done\n");
386 return ref;
389 static ULONG WINAPI IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
391 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
392 TRACE("iface %p.\n", iface);
394 return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
397 static ULONG WINAPI IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
399 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
400 TRACE("iface %p.\n", iface);
402 return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
405 static ULONG WINAPI IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
407 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
408 TRACE("iface %p.\n", iface);
410 return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
413 /*****************************************************************************
414 * IDirect3DDevice Methods
415 *****************************************************************************/
417 /*****************************************************************************
418 * IDirect3DDevice::Initialize
420 * Initializes a Direct3DDevice. This implementation is a no-op, as all
421 * initialization is done at create time.
423 * Exists in Version 1
425 * Parameters:
426 * No idea what they mean, as the MSDN page is gone
428 * Returns: DD_OK
430 *****************************************************************************/
431 static HRESULT WINAPI
432 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
433 IDirect3D *Direct3D, GUID *guid,
434 D3DDEVICEDESC *Desc)
436 /* It shouldn't be crucial, but print a FIXME, I'm interested if
437 * any game calls it and when. */
438 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
439 iface, Direct3D, debugstr_guid(guid), Desc);
441 return D3D_OK;
444 /*****************************************************************************
445 * IDirect3DDevice7::GetCaps
447 * Retrieves the device's capabilities
449 * This implementation is used for Version 7 only, the older versions have
450 * their own implementation.
452 * Parameters:
453 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
455 * Returns:
456 * D3D_OK on success
457 * D3DERR_* if a problem occurs. See WineD3D
459 *****************************************************************************/
460 static HRESULT
461 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
462 D3DDEVICEDESC7 *Desc)
464 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
465 D3DDEVICEDESC OldDesc;
467 TRACE("iface %p, device_desc %p.\n", iface, Desc);
469 if (!Desc)
471 WARN("Desc is NULL, returning DDERR_INVALIDPARAMS.\n");
472 return DDERR_INVALIDPARAMS;
475 /* Call the same function used by IDirect3D, this saves code */
476 return IDirect3DImpl_GetCaps(This->ddraw->wined3d, &OldDesc, Desc);
479 static HRESULT WINAPI
480 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
481 D3DDEVICEDESC7 *Desc)
483 return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
486 static HRESULT WINAPI
487 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
488 D3DDEVICEDESC7 *Desc)
490 HRESULT hr;
491 WORD old_fpucw;
493 old_fpucw = d3d_fpu_setup();
494 hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
495 set_fpu_control_word(old_fpucw);
497 return hr;
499 /*****************************************************************************
500 * IDirect3DDevice3::GetCaps
502 * Retrieves the capabilities of the hardware device and the emulation
503 * device. For Wine, hardware and emulation are the same (it's all HW).
505 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
507 * Parameters:
508 * HWDesc: Structure to fill with the HW caps
509 * HelDesc: Structure to fill with the hardware emulation caps
511 * Returns:
512 * D3D_OK on success
513 * D3DERR_* if a problem occurs. See WineD3D
515 *****************************************************************************/
517 /* There are 3 versions of D3DDEVICEDESC. All 3 share the same name because
518 * Microsoft just expanded the existing structure without naming them
519 * D3DDEVICEDESC2 and D3DDEVICEDESC3. Which version is used have depends
520 * on the version of the DirectX SDK. DirectX 6+ and Wine use the latest
521 * one with 252 bytes.
523 * All 3 versions are allowed as parameters and only the specified amount of
524 * bytes is written.
526 * Note that Direct3D7 and earlier are not available in native Win64
527 * ddraw.dll builds, so possible size differences between 32 bit and
528 * 64 bit are a non-issue.
530 static inline BOOL check_d3ddevicedesc_size(DWORD size)
532 if (size == FIELD_OFFSET(D3DDEVICEDESC, dwMinTextureWidth) /* 172 */
533 || size == FIELD_OFFSET(D3DDEVICEDESC, dwMaxTextureRepeat) /* 204 */
534 || size == sizeof(D3DDEVICEDESC) /* 252 */) return TRUE;
535 return FALSE;
538 static HRESULT WINAPI
539 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
540 D3DDEVICEDESC *HWDesc,
541 D3DDEVICEDESC *HelDesc)
543 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
544 D3DDEVICEDESC oldDesc;
545 D3DDEVICEDESC7 newDesc;
546 HRESULT hr;
548 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
550 if (!HWDesc)
552 WARN("HWDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
553 return DDERR_INVALIDPARAMS;
555 if (!check_d3ddevicedesc_size(HWDesc->dwSize))
557 WARN("HWDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HWDesc->dwSize);
558 return DDERR_INVALIDPARAMS;
560 if (!HelDesc)
562 WARN("HelDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
563 return DDERR_INVALIDPARAMS;
565 if (!check_d3ddevicedesc_size(HelDesc->dwSize))
567 WARN("HelDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HelDesc->dwSize);
568 return DDERR_INVALIDPARAMS;
571 hr = IDirect3DImpl_GetCaps(This->ddraw->wined3d, &oldDesc, &newDesc);
572 if(hr != D3D_OK) return hr;
574 DD_STRUCT_COPY_BYSIZE(HWDesc, &oldDesc);
575 DD_STRUCT_COPY_BYSIZE(HelDesc, &oldDesc);
576 return D3D_OK;
579 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
580 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
582 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
583 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
584 return IDirect3DDevice3_GetCaps(&This->IDirect3DDevice3_iface, D3DHWDevDesc, D3DHELDevDesc);
587 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
588 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
590 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
591 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
592 return IDirect3DDevice3_GetCaps(&This->IDirect3DDevice3_iface, D3DHWDevDesc, D3DHELDevDesc);
595 /*****************************************************************************
596 * IDirect3DDevice2::SwapTextureHandles
598 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
600 * Parameters:
601 * Tex1, Tex2: The 2 Textures to swap
603 * Returns:
604 * D3D_OK
606 *****************************************************************************/
607 static HRESULT WINAPI
608 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
609 IDirect3DTexture2 *Tex1,
610 IDirect3DTexture2 *Tex2)
612 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
613 IDirectDrawSurfaceImpl *surf1 = unsafe_impl_from_IDirect3DTexture2(Tex1);
614 IDirectDrawSurfaceImpl *surf2 = unsafe_impl_from_IDirect3DTexture2(Tex2);
615 DWORD h1, h2;
617 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, Tex1, Tex2);
619 wined3d_mutex_lock();
621 h1 = surf1->Handle - 1;
622 h2 = surf2->Handle - 1;
623 This->handle_table.entries[h1].object = surf2;
624 This->handle_table.entries[h2].object = surf1;
625 surf2->Handle = h1 + 1;
626 surf1->Handle = h2 + 1;
628 wined3d_mutex_unlock();
630 return D3D_OK;
633 static HRESULT WINAPI IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
634 IDirect3DTexture *D3DTex1, IDirect3DTexture *D3DTex2)
636 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
637 IDirectDrawSurfaceImpl *surf1 = unsafe_impl_from_IDirect3DTexture(D3DTex1);
638 IDirectDrawSurfaceImpl *surf2 = unsafe_impl_from_IDirect3DTexture(D3DTex2);
639 IDirect3DTexture2 *t1 = surf1 ? &surf1->IDirect3DTexture2_iface : NULL;
640 IDirect3DTexture2 *t2 = surf2 ? &surf2->IDirect3DTexture2_iface : NULL;
642 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, D3DTex1, D3DTex2);
644 return IDirect3DDevice2_SwapTextureHandles(&This->IDirect3DDevice2_iface, t1, t2);
647 /*****************************************************************************
648 * IDirect3DDevice3::GetStats
650 * This method seems to retrieve some stats from the device.
651 * The MSDN documentation doesn't exist any more, but the D3DSTATS
652 * structure suggests that the amount of drawn primitives and processed
653 * vertices is returned.
655 * Exists in Version 1, 2 and 3
657 * Parameters:
658 * Stats: Pointer to a D3DSTATS structure to be filled
660 * Returns:
661 * D3D_OK on success
662 * DDERR_INVALIDPARAMS if Stats == NULL
664 *****************************************************************************/
665 static HRESULT WINAPI
666 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
667 D3DSTATS *Stats)
669 FIXME("iface %p, stats %p stub!\n", iface, Stats);
671 if(!Stats)
672 return DDERR_INVALIDPARAMS;
674 /* Fill the Stats with 0 */
675 Stats->dwTrianglesDrawn = 0;
676 Stats->dwLinesDrawn = 0;
677 Stats->dwPointsDrawn = 0;
678 Stats->dwSpansDrawn = 0;
679 Stats->dwVerticesProcessed = 0;
681 return D3D_OK;
684 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *Stats)
686 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
688 TRACE("iface %p, stats %p.\n", iface, Stats);
690 return IDirect3DDevice3_GetStats(&This->IDirect3DDevice3_iface, Stats);
693 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface, D3DSTATS *Stats)
695 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
697 TRACE("iface %p, stats %p.\n", iface, Stats);
699 return IDirect3DDevice3_GetStats(&This->IDirect3DDevice3_iface, Stats);
702 /*****************************************************************************
703 * IDirect3DDevice::CreateExecuteBuffer
705 * Creates an IDirect3DExecuteBuffer, used for rendering with a
706 * Direct3DDevice.
708 * Version 1 only.
710 * Params:
711 * Desc: Buffer description
712 * ExecuteBuffer: Address to return the Interface pointer at
713 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
714 * support
716 * Returns:
717 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
718 * DDERR_OUTOFMEMORY if we ran out of memory
719 * D3D_OK on success
721 *****************************************************************************/
722 static HRESULT WINAPI
723 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
724 D3DEXECUTEBUFFERDESC *Desc,
725 IDirect3DExecuteBuffer **ExecuteBuffer,
726 IUnknown *UnkOuter)
728 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
729 IDirect3DExecuteBufferImpl* object;
730 HRESULT hr;
732 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
733 iface, Desc, ExecuteBuffer, UnkOuter);
735 if(UnkOuter)
736 return CLASS_E_NOAGGREGATION;
738 /* Allocate the new Execute Buffer */
739 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
740 if(!object)
742 ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
743 return DDERR_OUTOFMEMORY;
746 hr = d3d_execute_buffer_init(object, This, Desc);
747 if (FAILED(hr))
749 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
750 HeapFree(GetProcessHeap(), 0, object);
751 return hr;
754 *ExecuteBuffer = &object->IDirect3DExecuteBuffer_iface;
756 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
758 return D3D_OK;
761 /*****************************************************************************
762 * IDirect3DDevice::Execute
764 * Executes all the stuff in an execute buffer.
766 * Params:
767 * ExecuteBuffer: The buffer to execute
768 * Viewport: The viewport used for rendering
769 * Flags: Some flags
771 * Returns:
772 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
773 * D3D_OK on success
775 *****************************************************************************/
776 static HRESULT WINAPI IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
777 IDirect3DExecuteBuffer *ExecuteBuffer, IDirect3DViewport *Viewport, DWORD Flags)
779 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
780 IDirect3DExecuteBufferImpl *buffer = unsafe_impl_from_IDirect3DExecuteBuffer(ExecuteBuffer);
781 IDirect3DViewportImpl *Direct3DViewportImpl = unsafe_impl_from_IDirect3DViewport(Viewport);
782 HRESULT hr;
784 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, Viewport, Flags);
786 if(!buffer)
787 return DDERR_INVALIDPARAMS;
789 /* Execute... */
790 wined3d_mutex_lock();
791 hr = d3d_execute_buffer_execute(buffer, This, Direct3DViewportImpl);
792 wined3d_mutex_unlock();
794 return hr;
797 /*****************************************************************************
798 * IDirect3DDevice3::AddViewport
800 * Add a Direct3DViewport to the device's viewport list. These viewports
801 * are wrapped to IDirect3DDevice7 viewports in viewport.c
803 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
804 * are the same interfaces.
806 * Params:
807 * Viewport: The viewport to add
809 * Returns:
810 * DDERR_INVALIDPARAMS if Viewport == NULL
811 * D3D_OK on success
813 *****************************************************************************/
814 static HRESULT WINAPI
815 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
816 IDirect3DViewport3 *Viewport)
818 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
819 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(Viewport);
821 TRACE("iface %p, viewport %p.\n", iface, Viewport);
823 /* Sanity check */
824 if(!vp)
825 return DDERR_INVALIDPARAMS;
827 wined3d_mutex_lock();
828 list_add_head(&This->viewport_list, &vp->entry);
829 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
830 so set active_device here. */
831 wined3d_mutex_unlock();
833 return D3D_OK;
836 static HRESULT WINAPI IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
837 IDirect3DViewport2 *Direct3DViewport2)
839 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
840 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
842 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
844 return IDirect3DDevice3_AddViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
847 static HRESULT WINAPI IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
848 IDirect3DViewport *Direct3DViewport)
850 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
851 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport(Direct3DViewport);
853 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
855 return IDirect3DDevice3_AddViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
858 /*****************************************************************************
859 * IDirect3DDevice3::DeleteViewport
861 * Deletes a Direct3DViewport from the device's viewport list.
863 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
864 * are equal.
866 * Params:
867 * Viewport: The viewport to delete
869 * Returns:
870 * D3D_OK on success
871 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
873 *****************************************************************************/
874 static HRESULT WINAPI IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
876 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
877 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
879 TRACE("iface %p, viewport %p.\n", iface, viewport);
881 wined3d_mutex_lock();
883 if (vp->active_device != This)
885 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
886 wined3d_mutex_unlock();
887 return DDERR_INVALIDPARAMS;
890 vp->active_device = NULL;
891 list_remove(&vp->entry);
893 wined3d_mutex_unlock();
895 return D3D_OK;
898 static HRESULT WINAPI IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
899 IDirect3DViewport2 *Direct3DViewport2)
901 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
902 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
904 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
906 return IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
909 static HRESULT WINAPI IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
910 IDirect3DViewport *Direct3DViewport)
912 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
913 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport(Direct3DViewport);
915 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
917 return IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
920 /*****************************************************************************
921 * IDirect3DDevice3::NextViewport
923 * Returns a viewport from the viewport list, depending on the
924 * passed viewport and the flags.
926 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
927 * are equal.
929 * Params:
930 * Viewport: Viewport to use for beginning the search
931 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
933 * Returns:
934 * D3D_OK on success
935 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
937 *****************************************************************************/
938 static HRESULT WINAPI
939 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
940 IDirect3DViewport3 *Viewport3,
941 IDirect3DViewport3 **lplpDirect3DViewport3,
942 DWORD Flags)
944 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
945 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(Viewport3);
946 IDirect3DViewportImpl *next;
947 struct list *entry;
949 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
950 iface, Viewport3, lplpDirect3DViewport3, Flags);
952 if(!vp)
954 *lplpDirect3DViewport3 = NULL;
955 return DDERR_INVALIDPARAMS;
959 wined3d_mutex_lock();
960 switch (Flags)
962 case D3DNEXT_NEXT:
963 entry = list_next(&This->viewport_list, &vp->entry);
964 break;
966 case D3DNEXT_HEAD:
967 entry = list_head(&This->viewport_list);
968 break;
970 case D3DNEXT_TAIL:
971 entry = list_tail(&This->viewport_list);
972 break;
974 default:
975 WARN("Invalid flags %#x.\n", Flags);
976 *lplpDirect3DViewport3 = NULL;
977 wined3d_mutex_unlock();
978 return DDERR_INVALIDPARAMS;
981 if (entry)
983 next = LIST_ENTRY(entry, IDirect3DViewportImpl, entry);
984 *lplpDirect3DViewport3 = &next->IDirect3DViewport3_iface;
986 else
987 *lplpDirect3DViewport3 = NULL;
989 wined3d_mutex_unlock();
991 return D3D_OK;
994 static HRESULT WINAPI IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
995 IDirect3DViewport2 *Viewport2, IDirect3DViewport2 **lplpDirect3DViewport2, DWORD Flags)
997 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
998 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Viewport2);
999 IDirect3DViewport3 *res;
1000 HRESULT hr;
1002 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
1003 iface, Viewport2, lplpDirect3DViewport2, Flags);
1005 hr = IDirect3DDevice3_NextViewport(&This->IDirect3DDevice3_iface,
1006 &vp->IDirect3DViewport3_iface, &res, Flags);
1007 *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
1008 return hr;
1011 static HRESULT WINAPI IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
1012 IDirect3DViewport *Viewport, IDirect3DViewport **lplpDirect3DViewport, DWORD Flags)
1014 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1015 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport(Viewport);
1016 IDirect3DViewport3 *res;
1017 HRESULT hr;
1019 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
1020 iface, Viewport, lplpDirect3DViewport, Flags);
1022 hr = IDirect3DDevice3_NextViewport(&This->IDirect3DDevice3_iface,
1023 &vp->IDirect3DViewport3_iface, &res, Flags);
1024 *lplpDirect3DViewport = (IDirect3DViewport *)res;
1025 return hr;
1028 /*****************************************************************************
1029 * IDirect3DDevice::Pick
1031 * Executes an execute buffer without performing rendering. Instead, a
1032 * list of primitives that intersect with (x1,y1) of the passed rectangle
1033 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
1034 * this list.
1036 * Version 1 only
1038 * Params:
1039 * ExecuteBuffer: Buffer to execute
1040 * Viewport: Viewport to use for execution
1041 * Flags: None are defined, according to the SDK
1042 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
1043 * x2 and y2 are ignored.
1045 * Returns:
1046 * D3D_OK because it's a stub
1048 *****************************************************************************/
1049 static HRESULT WINAPI
1050 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
1051 IDirect3DExecuteBuffer *ExecuteBuffer,
1052 IDirect3DViewport *Viewport,
1053 DWORD Flags,
1054 D3DRECT *Rect)
1056 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
1057 iface, ExecuteBuffer, Viewport, Flags, wine_dbgstr_rect((RECT *)Rect));
1059 return D3D_OK;
1062 /*****************************************************************************
1063 * IDirect3DDevice::GetPickRecords
1065 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1067 * Version 1 only
1069 * Params:
1070 * Count: Pointer to a DWORD containing the numbers of pick records to
1071 * retrieve
1072 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1074 * Returns:
1075 * D3D_OK, because it's a stub
1077 *****************************************************************************/
1078 static HRESULT WINAPI
1079 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1080 DWORD *Count,
1081 D3DPICKRECORD *D3DPickRec)
1083 FIXME("iface %p, count %p, records %p stub!\n", iface, Count, D3DPickRec);
1085 return D3D_OK;
1088 /*****************************************************************************
1089 * IDirect3DDevice7::EnumTextureformats
1091 * Enumerates the supported texture formats. It has a list of all possible
1092 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1093 * WineD3D supports it. If so, then it is passed to the app.
1095 * This is for Version 7 and 3, older versions have a different
1096 * callback function and their own implementation
1098 * Params:
1099 * Callback: Callback to call for each enumerated format
1100 * Arg: Argument to pass to the callback
1102 * Returns:
1103 * D3D_OK on success
1104 * DDERR_INVALIDPARAMS if Callback == NULL
1106 *****************************************************************************/
1107 static HRESULT
1108 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1109 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1110 void *Arg)
1112 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1113 struct wined3d_display_mode mode;
1114 HRESULT hr;
1115 unsigned int i;
1117 static const enum wined3d_format_id FormatList[] =
1119 /* 16 bit */
1120 WINED3DFMT_B5G5R5X1_UNORM,
1121 WINED3DFMT_B5G5R5A1_UNORM,
1122 WINED3DFMT_B4G4R4A4_UNORM,
1123 WINED3DFMT_B5G6R5_UNORM,
1124 /* 32 bit */
1125 WINED3DFMT_B8G8R8X8_UNORM,
1126 WINED3DFMT_B8G8R8A8_UNORM,
1127 /* 8 bit */
1128 WINED3DFMT_B2G3R3_UNORM,
1129 WINED3DFMT_P8_UINT,
1130 /* FOURCC codes */
1131 WINED3DFMT_DXT1,
1132 WINED3DFMT_DXT3,
1133 WINED3DFMT_DXT5,
1136 static const enum wined3d_format_id BumpFormatList[] =
1138 WINED3DFMT_R8G8_SNORM,
1139 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1140 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1141 WINED3DFMT_R16G16_SNORM,
1142 WINED3DFMT_R10G11B11_SNORM,
1143 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1146 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1148 if(!Callback)
1149 return DDERR_INVALIDPARAMS;
1151 wined3d_mutex_lock();
1153 memset(&mode, 0, sizeof(mode));
1154 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1155 if (FAILED(hr))
1157 wined3d_mutex_unlock();
1158 WARN("Cannot get the current adapter format\n");
1159 return hr;
1162 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1164 hr = wined3d_check_device_format(This->ddraw->wined3d, WINED3DADAPTER_DEFAULT, WINED3D_DEVICE_TYPE_HAL,
1165 mode.format_id, 0, WINED3D_RTYPE_TEXTURE, FormatList[i], WINED3D_SURFACE_TYPE_OPENGL);
1166 if (hr == D3D_OK)
1168 DDPIXELFORMAT pformat;
1170 memset(&pformat, 0, sizeof(pformat));
1171 pformat.dwSize = sizeof(pformat);
1172 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1174 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1175 hr = Callback(&pformat, Arg);
1176 if(hr != DDENUMRET_OK)
1178 TRACE("Format enumeration cancelled by application\n");
1179 wined3d_mutex_unlock();
1180 return D3D_OK;
1185 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1187 hr = wined3d_check_device_format(This->ddraw->wined3d, WINED3DADAPTER_DEFAULT,
1188 WINED3D_DEVICE_TYPE_HAL, mode.format_id, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1189 WINED3D_RTYPE_TEXTURE, BumpFormatList[i], WINED3D_SURFACE_TYPE_OPENGL);
1190 if (hr == D3D_OK)
1192 DDPIXELFORMAT pformat;
1194 memset(&pformat, 0, sizeof(pformat));
1195 pformat.dwSize = sizeof(pformat);
1196 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1198 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1199 hr = Callback(&pformat, Arg);
1200 if(hr != DDENUMRET_OK)
1202 TRACE("Format enumeration cancelled by application\n");
1203 wined3d_mutex_unlock();
1204 return D3D_OK;
1208 TRACE("End of enumeration\n");
1209 wined3d_mutex_unlock();
1211 return D3D_OK;
1214 static HRESULT WINAPI
1215 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1216 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1217 void *Arg)
1219 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1222 static HRESULT WINAPI
1223 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1224 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1225 void *Arg)
1227 HRESULT hr;
1228 WORD old_fpucw;
1230 old_fpucw = d3d_fpu_setup();
1231 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1232 set_fpu_control_word(old_fpucw);
1234 return hr;
1237 static HRESULT WINAPI IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1238 LPD3DENUMPIXELFORMATSCALLBACK Callback, void *Arg)
1240 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1242 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1244 return IDirect3DDevice7_EnumTextureFormats(&This->IDirect3DDevice7_iface, Callback, Arg);
1247 /*****************************************************************************
1248 * IDirect3DDevice2::EnumTextureformats
1250 * EnumTextureFormats for Version 1 and 2, see
1251 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1253 * This version has a different callback and does not enumerate FourCC
1254 * formats
1256 *****************************************************************************/
1257 static HRESULT WINAPI
1258 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1259 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1260 void *Arg)
1262 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1263 struct wined3d_display_mode mode;
1264 HRESULT hr;
1265 unsigned int i;
1267 static const enum wined3d_format_id FormatList[] =
1269 /* 16 bit */
1270 WINED3DFMT_B5G5R5X1_UNORM,
1271 WINED3DFMT_B5G5R5A1_UNORM,
1272 WINED3DFMT_B4G4R4A4_UNORM,
1273 WINED3DFMT_B5G6R5_UNORM,
1274 /* 32 bit */
1275 WINED3DFMT_B8G8R8X8_UNORM,
1276 WINED3DFMT_B8G8R8A8_UNORM,
1277 /* 8 bit */
1278 WINED3DFMT_B2G3R3_UNORM,
1279 WINED3DFMT_P8_UINT,
1280 /* FOURCC codes - Not in this version*/
1283 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1285 if(!Callback)
1286 return DDERR_INVALIDPARAMS;
1288 wined3d_mutex_lock();
1290 memset(&mode, 0, sizeof(mode));
1291 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1292 if (FAILED(hr))
1294 wined3d_mutex_unlock();
1295 WARN("Cannot get the current adapter format\n");
1296 return hr;
1299 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1301 hr = wined3d_check_device_format(This->ddraw->wined3d, 0, WINED3D_DEVICE_TYPE_HAL,
1302 mode.format_id, 0, WINED3D_RTYPE_TEXTURE, FormatList[i], WINED3D_SURFACE_TYPE_OPENGL);
1303 if (hr == D3D_OK)
1305 DDSURFACEDESC sdesc;
1307 memset(&sdesc, 0, sizeof(sdesc));
1308 sdesc.dwSize = sizeof(sdesc);
1309 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1310 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1311 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1312 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1314 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1315 hr = Callback(&sdesc, Arg);
1316 if(hr != DDENUMRET_OK)
1318 TRACE("Format enumeration cancelled by application\n");
1319 wined3d_mutex_unlock();
1320 return D3D_OK;
1324 TRACE("End of enumeration\n");
1325 wined3d_mutex_unlock();
1327 return D3D_OK;
1330 static HRESULT WINAPI IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1331 LPD3DENUMTEXTUREFORMATSCALLBACK Callback, void *Arg)
1333 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1335 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1337 return IDirect3DDevice2_EnumTextureFormats(&This->IDirect3DDevice2_iface, Callback, Arg);
1340 /*****************************************************************************
1341 * IDirect3DDevice::CreateMatrix
1343 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1344 * allocated for the handle.
1346 * Version 1 only
1348 * Params
1349 * D3DMatHandle: Address to return the handle at
1351 * Returns:
1352 * D3D_OK on success
1353 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1355 *****************************************************************************/
1356 static HRESULT WINAPI
1357 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1359 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1360 D3DMATRIX *Matrix;
1361 DWORD h;
1363 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1365 if(!D3DMatHandle)
1366 return DDERR_INVALIDPARAMS;
1368 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1369 if(!Matrix)
1371 ERR("Out of memory when allocating a D3DMATRIX\n");
1372 return DDERR_OUTOFMEMORY;
1375 wined3d_mutex_lock();
1377 h = ddraw_allocate_handle(&This->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1378 if (h == DDRAW_INVALID_HANDLE)
1380 ERR("Failed to allocate a matrix handle.\n");
1381 HeapFree(GetProcessHeap(), 0, Matrix);
1382 wined3d_mutex_unlock();
1383 return DDERR_OUTOFMEMORY;
1386 *D3DMatHandle = h + 1;
1388 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1390 wined3d_mutex_unlock();
1392 return D3D_OK;
1395 /*****************************************************************************
1396 * IDirect3DDevice::SetMatrix
1398 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1399 * allocated for the handle
1401 * Version 1 only
1403 * Params:
1404 * D3DMatHandle: Handle to set the matrix to
1405 * D3DMatrix: Matrix to set
1407 * Returns:
1408 * D3D_OK on success
1409 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1410 * to set is NULL
1412 *****************************************************************************/
1413 static HRESULT WINAPI
1414 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1415 D3DMATRIXHANDLE D3DMatHandle,
1416 D3DMATRIX *D3DMatrix)
1418 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1419 D3DMATRIX *m;
1421 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1423 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1425 wined3d_mutex_lock();
1427 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1428 if (!m)
1430 WARN("Invalid matrix handle.\n");
1431 wined3d_mutex_unlock();
1432 return DDERR_INVALIDPARAMS;
1435 if (TRACE_ON(ddraw))
1436 dump_D3DMATRIX(D3DMatrix);
1438 *m = *D3DMatrix;
1440 if (D3DMatHandle == This->world)
1441 wined3d_device_set_transform(This->wined3d_device,
1442 WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix *)D3DMatrix);
1444 if (D3DMatHandle == This->view)
1445 wined3d_device_set_transform(This->wined3d_device,
1446 WINED3D_TS_VIEW, (struct wined3d_matrix *)D3DMatrix);
1448 if (D3DMatHandle == This->proj)
1449 wined3d_device_set_transform(This->wined3d_device,
1450 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)D3DMatrix);
1452 wined3d_mutex_unlock();
1454 return D3D_OK;
1457 /*****************************************************************************
1458 * IDirect3DDevice::GetMatrix
1460 * Returns the content of a D3DMATRIX handle
1462 * Version 1 only
1464 * Params:
1465 * D3DMatHandle: Matrix handle to read the content from
1466 * D3DMatrix: Address to store the content at
1468 * Returns:
1469 * D3D_OK on success
1470 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1472 *****************************************************************************/
1473 static HRESULT WINAPI
1474 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1475 D3DMATRIXHANDLE D3DMatHandle,
1476 D3DMATRIX *D3DMatrix)
1478 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1479 D3DMATRIX *m;
1481 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1483 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1485 wined3d_mutex_lock();
1487 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1488 if (!m)
1490 WARN("Invalid matrix handle.\n");
1491 wined3d_mutex_unlock();
1492 return DDERR_INVALIDPARAMS;
1495 *D3DMatrix = *m;
1497 wined3d_mutex_unlock();
1499 return D3D_OK;
1502 /*****************************************************************************
1503 * IDirect3DDevice::DeleteMatrix
1505 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1507 * Version 1 only
1509 * Params:
1510 * D3DMatHandle: Handle to destroy
1512 * Returns:
1513 * D3D_OK on success
1514 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1516 *****************************************************************************/
1517 static HRESULT WINAPI
1518 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1519 D3DMATRIXHANDLE D3DMatHandle)
1521 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1522 D3DMATRIX *m;
1524 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1526 wined3d_mutex_lock();
1528 m = ddraw_free_handle(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1529 if (!m)
1531 WARN("Invalid matrix handle.\n");
1532 wined3d_mutex_unlock();
1533 return DDERR_INVALIDPARAMS;
1536 wined3d_mutex_unlock();
1538 HeapFree(GetProcessHeap(), 0, m);
1540 return D3D_OK;
1543 /*****************************************************************************
1544 * IDirect3DDevice7::BeginScene
1546 * This method must be called before any rendering is performed.
1547 * IDirect3DDevice::EndScene has to be called after the scene is complete
1549 * Version 1, 2, 3 and 7
1551 * Returns:
1552 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1553 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1554 * started scene).
1556 *****************************************************************************/
1557 static HRESULT
1558 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1560 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1561 HRESULT hr;
1563 TRACE("iface %p.\n", iface);
1565 wined3d_mutex_lock();
1566 hr = wined3d_device_begin_scene(This->wined3d_device);
1567 wined3d_mutex_unlock();
1569 if(hr == WINED3D_OK) return D3D_OK;
1570 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1573 static HRESULT WINAPI
1574 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1576 return IDirect3DDeviceImpl_7_BeginScene(iface);
1579 static HRESULT WINAPI
1580 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1582 HRESULT hr;
1583 WORD old_fpucw;
1585 old_fpucw = d3d_fpu_setup();
1586 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1587 set_fpu_control_word(old_fpucw);
1589 return hr;
1592 static HRESULT WINAPI IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1594 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1595 TRACE("iface %p.\n", iface);
1597 return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
1600 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1602 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1603 TRACE("iface %p.\n", iface);
1605 return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
1608 static HRESULT WINAPI IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1610 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1611 TRACE("iface %p.\n", iface);
1613 return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
1616 /*****************************************************************************
1617 * IDirect3DDevice7::EndScene
1619 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1620 * This method must be called after rendering is finished.
1622 * Version 1, 2, 3 and 7
1624 * Returns:
1625 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1626 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1627 * that only if the scene was already ended.
1629 *****************************************************************************/
1630 static HRESULT
1631 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1633 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1634 HRESULT hr;
1636 TRACE("iface %p.\n", iface);
1638 wined3d_mutex_lock();
1639 hr = wined3d_device_end_scene(This->wined3d_device);
1640 wined3d_mutex_unlock();
1642 if(hr == WINED3D_OK) return D3D_OK;
1643 else return D3DERR_SCENE_NOT_IN_SCENE;
1646 static HRESULT WINAPI DECLSPEC_HOTPATCH
1647 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1649 return IDirect3DDeviceImpl_7_EndScene(iface);
1652 static HRESULT WINAPI DECLSPEC_HOTPATCH
1653 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1655 HRESULT hr;
1656 WORD old_fpucw;
1658 old_fpucw = d3d_fpu_setup();
1659 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1660 set_fpu_control_word(old_fpucw);
1662 return hr;
1665 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1667 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1668 TRACE("iface %p.\n", iface);
1670 return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
1673 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1675 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1676 TRACE("iface %p.\n", iface);
1678 return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
1681 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1683 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1684 TRACE("iface %p.\n", iface);
1686 return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
1689 /*****************************************************************************
1690 * IDirect3DDevice7::GetDirect3D
1692 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1693 * this device.
1695 * Params:
1696 * Direct3D7: Address to store the interface pointer at
1698 * Returns:
1699 * D3D_OK on success
1700 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1702 *****************************************************************************/
1703 static HRESULT WINAPI
1704 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1705 IDirect3D7 **Direct3D7)
1707 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1709 TRACE("iface %p, d3d %p.\n", iface, Direct3D7);
1711 if(!Direct3D7)
1712 return DDERR_INVALIDPARAMS;
1714 *Direct3D7 = &This->ddraw->IDirect3D7_iface;
1715 IDirect3D7_AddRef(*Direct3D7);
1717 TRACE(" returning interface %p\n", *Direct3D7);
1718 return D3D_OK;
1721 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1722 IDirect3D3 **Direct3D3)
1724 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1726 TRACE("iface %p, d3d %p.\n", iface, Direct3D3);
1728 if(!Direct3D3)
1729 return DDERR_INVALIDPARAMS;
1731 IDirect3D3_AddRef(&This->ddraw->IDirect3D3_iface);
1732 *Direct3D3 = &This->ddraw->IDirect3D3_iface;
1733 TRACE(" returning interface %p\n", *Direct3D3);
1734 return D3D_OK;
1737 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1738 IDirect3D2 **Direct3D2)
1740 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1742 TRACE("iface %p, d3d %p.\n", iface, Direct3D2);
1744 if(!Direct3D2)
1745 return DDERR_INVALIDPARAMS;
1747 IDirect3D2_AddRef(&This->ddraw->IDirect3D2_iface);
1748 *Direct3D2 = &This->ddraw->IDirect3D2_iface;
1749 TRACE(" returning interface %p\n", *Direct3D2);
1750 return D3D_OK;
1753 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1754 IDirect3D **Direct3D)
1756 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1758 TRACE("iface %p, d3d %p.\n", iface, Direct3D);
1760 if(!Direct3D)
1761 return DDERR_INVALIDPARAMS;
1763 IDirect3D_AddRef(&This->ddraw->IDirect3D_iface);
1764 *Direct3D = &This->ddraw->IDirect3D_iface;
1765 TRACE(" returning interface %p\n", *Direct3D);
1766 return D3D_OK;
1769 /*****************************************************************************
1770 * IDirect3DDevice3::SetCurrentViewport
1772 * Sets a Direct3DViewport as the current viewport.
1773 * For the thunks note that all viewport interface versions are equal
1775 * Params:
1776 * Direct3DViewport3: The viewport to set
1778 * Version 2 and 3
1780 * Returns:
1781 * D3D_OK on success
1782 * (Is a NULL viewport valid?)
1784 *****************************************************************************/
1785 static HRESULT WINAPI
1786 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1787 IDirect3DViewport3 *Direct3DViewport3)
1789 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1790 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(Direct3DViewport3);
1792 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1794 wined3d_mutex_lock();
1795 /* Do nothing if the specified viewport is the same as the current one */
1796 if (This->current_viewport == vp )
1798 wined3d_mutex_unlock();
1799 return D3D_OK;
1802 if (vp->active_device != This)
1804 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1805 wined3d_mutex_unlock();
1806 return DDERR_INVALIDPARAMS;
1809 /* Release previous viewport and AddRef the new one */
1810 if (This->current_viewport)
1812 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1813 &This->current_viewport->IDirect3DViewport3_iface);
1814 IDirect3DViewport3_Release(&This->current_viewport->IDirect3DViewport3_iface);
1816 IDirect3DViewport3_AddRef(Direct3DViewport3);
1818 /* Set this viewport as the current viewport */
1819 This->current_viewport = vp;
1821 /* Activate this viewport */
1822 viewport_activate(This->current_viewport, FALSE);
1824 wined3d_mutex_unlock();
1826 return D3D_OK;
1829 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1830 IDirect3DViewport2 *Direct3DViewport2)
1832 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1833 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
1835 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1837 return IDirect3DDevice3_SetCurrentViewport(&This->IDirect3DDevice3_iface,
1838 &vp->IDirect3DViewport3_iface);
1841 /*****************************************************************************
1842 * IDirect3DDevice3::GetCurrentViewport
1844 * Returns the currently active viewport.
1846 * Version 2 and 3
1848 * Params:
1849 * Direct3DViewport3: Address to return the interface pointer at
1851 * Returns:
1852 * D3D_OK on success
1853 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1855 *****************************************************************************/
1856 static HRESULT WINAPI
1857 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1858 IDirect3DViewport3 **Direct3DViewport3)
1860 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1862 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1864 if(!Direct3DViewport3)
1865 return DDERR_INVALIDPARAMS;
1867 wined3d_mutex_lock();
1868 *Direct3DViewport3 = &This->current_viewport->IDirect3DViewport3_iface;
1870 /* AddRef the returned viewport */
1871 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1873 TRACE(" returning interface %p\n", *Direct3DViewport3);
1875 wined3d_mutex_unlock();
1877 return D3D_OK;
1880 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1881 IDirect3DViewport2 **Direct3DViewport2)
1883 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1884 HRESULT hr;
1886 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1888 hr = IDirect3DDevice3_GetCurrentViewport(&This->IDirect3DDevice3_iface,
1889 (IDirect3DViewport3 **)Direct3DViewport2);
1890 if(hr != D3D_OK) return hr;
1891 return D3D_OK;
1894 /*****************************************************************************
1895 * IDirect3DDevice7::SetRenderTarget
1897 * Sets the render target for the Direct3DDevice.
1898 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1899 * IDirectDrawSurface3 == IDirectDrawSurface
1901 * Version 2, 3 and 7
1903 * Params:
1904 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1905 * render target
1906 * Flags: Some flags
1908 * Returns:
1909 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1911 *****************************************************************************/
1912 static HRESULT d3d_device_set_render_target(IDirect3DDeviceImpl *This, IDirectDrawSurfaceImpl *Target)
1914 HRESULT hr;
1916 wined3d_mutex_lock();
1918 if(This->target == Target)
1920 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1921 wined3d_mutex_unlock();
1922 return D3D_OK;
1924 This->target = Target;
1925 hr = wined3d_device_set_render_target(This->wined3d_device, 0,
1926 Target ? Target->wined3d_surface : NULL, FALSE);
1927 if(hr != D3D_OK)
1929 wined3d_mutex_unlock();
1930 return hr;
1932 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1934 wined3d_mutex_unlock();
1936 return D3D_OK;
1939 static HRESULT
1940 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1941 IDirectDrawSurface7 *NewTarget,
1942 DWORD Flags)
1944 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1945 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface7(NewTarget);
1947 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, Flags);
1948 /* Flags: Not used */
1950 IDirectDrawSurface7_AddRef(NewTarget);
1951 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
1952 return d3d_device_set_render_target(This, Target);
1955 static HRESULT WINAPI
1956 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1957 IDirectDrawSurface7 *NewTarget,
1958 DWORD Flags)
1960 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1963 static HRESULT WINAPI
1964 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1965 IDirectDrawSurface7 *NewTarget,
1966 DWORD Flags)
1968 HRESULT hr;
1969 WORD old_fpucw;
1971 old_fpucw = d3d_fpu_setup();
1972 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1973 set_fpu_control_word(old_fpucw);
1975 return hr;
1978 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
1979 IDirectDrawSurface4 *NewRenderTarget, DWORD Flags)
1981 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1982 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface4(NewRenderTarget);
1984 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1986 IDirectDrawSurface4_AddRef(NewRenderTarget);
1987 IDirectDrawSurface4_Release(&This->target->IDirectDrawSurface4_iface);
1988 return d3d_device_set_render_target(This, Target);
1991 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
1992 IDirectDrawSurface *NewRenderTarget, DWORD Flags)
1994 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1995 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface(NewRenderTarget);
1997 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1999 IDirectDrawSurface_AddRef(NewRenderTarget);
2000 IDirectDrawSurface_Release(&This->target->IDirectDrawSurface_iface);
2001 return d3d_device_set_render_target(This, Target);
2004 /*****************************************************************************
2005 * IDirect3DDevice7::GetRenderTarget
2007 * Returns the current render target.
2008 * This is handled locally, because the WineD3D render target's parent
2009 * is an IParent
2011 * Version 2, 3 and 7
2013 * Params:
2014 * RenderTarget: Address to store the surface interface pointer
2016 * Returns:
2017 * D3D_OK on success
2018 * DDERR_INVALIDPARAMS if RenderTarget == NULL
2020 *****************************************************************************/
2021 static HRESULT WINAPI
2022 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
2023 IDirectDrawSurface7 **RenderTarget)
2025 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
2027 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2029 if(!RenderTarget)
2030 return DDERR_INVALIDPARAMS;
2032 wined3d_mutex_lock();
2033 *RenderTarget = &This->target->IDirectDrawSurface7_iface;
2034 IDirectDrawSurface7_AddRef(*RenderTarget);
2035 wined3d_mutex_unlock();
2037 return D3D_OK;
2040 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
2041 IDirectDrawSurface4 **RenderTarget)
2043 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2044 IDirectDrawSurface7 *RenderTarget7;
2045 IDirectDrawSurfaceImpl *RenderTargetImpl;
2046 HRESULT hr;
2048 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2050 if(!RenderTarget)
2051 return DDERR_INVALIDPARAMS;
2053 hr = IDirect3DDevice7_GetRenderTarget(&This->IDirect3DDevice7_iface, &RenderTarget7);
2054 if(hr != D3D_OK) return hr;
2055 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2056 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface;
2057 IDirectDrawSurface4_AddRef(*RenderTarget);
2058 IDirectDrawSurface7_Release(RenderTarget7);
2059 return D3D_OK;
2062 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
2063 IDirectDrawSurface **RenderTarget)
2065 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2066 IDirectDrawSurface7 *RenderTarget7;
2067 IDirectDrawSurfaceImpl *RenderTargetImpl;
2068 HRESULT hr;
2070 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2072 if(!RenderTarget)
2073 return DDERR_INVALIDPARAMS;
2075 hr = IDirect3DDevice7_GetRenderTarget(&This->IDirect3DDevice7_iface, &RenderTarget7);
2076 if(hr != D3D_OK) return hr;
2077 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2078 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
2079 IDirectDrawSurface_AddRef(*RenderTarget);
2080 IDirectDrawSurface7_Release(RenderTarget7);
2081 return D3D_OK;
2084 /*****************************************************************************
2085 * IDirect3DDevice3::Begin
2087 * Begins a description block of vertices. This is similar to glBegin()
2088 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2089 * described with IDirect3DDevice::Vertex are drawn.
2091 * Version 2 and 3
2093 * Params:
2094 * PrimitiveType: The type of primitives to draw
2095 * VertexTypeDesc: A flexible vertex format description of the vertices
2096 * Flags: Some flags..
2098 * Returns:
2099 * D3D_OK on success
2101 *****************************************************************************/
2102 static HRESULT WINAPI
2103 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2104 D3DPRIMITIVETYPE PrimitiveType,
2105 DWORD VertexTypeDesc,
2106 DWORD Flags)
2108 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2110 TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
2111 iface, PrimitiveType, VertexTypeDesc, Flags);
2113 wined3d_mutex_lock();
2114 This->primitive_type = PrimitiveType;
2115 This->vertex_type = VertexTypeDesc;
2116 This->render_flags = Flags;
2117 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2118 This->nb_vertices = 0;
2119 wined3d_mutex_unlock();
2121 return D3D_OK;
2124 static HRESULT WINAPI IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface, D3DPRIMITIVETYPE d3dpt,
2125 D3DVERTEXTYPE dwVertexTypeDesc, DWORD dwFlags)
2127 DWORD FVF;
2128 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2130 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2131 iface, d3dpt, dwVertexTypeDesc, dwFlags);
2133 switch(dwVertexTypeDesc)
2135 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2136 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2137 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2138 default:
2139 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2140 return DDERR_INVALIDPARAMS; /* Should never happen */
2143 return IDirect3DDevice3_Begin(&This->IDirect3DDevice3_iface, d3dpt, FVF, dwFlags);
2146 /*****************************************************************************
2147 * IDirect3DDevice3::BeginIndexed
2149 * Draws primitives based on vertices in a vertex array which are specified
2150 * by indices.
2152 * Version 2 and 3
2154 * Params:
2155 * PrimitiveType: Primitive type to draw
2156 * VertexType: A FVF description of the vertex format
2157 * Vertices: pointer to an array containing the vertices
2158 * NumVertices: The number of vertices in the vertex array
2159 * Flags: Some flags ...
2161 * Returns:
2162 * D3D_OK, because it's a stub
2164 *****************************************************************************/
2165 static HRESULT WINAPI
2166 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2167 D3DPRIMITIVETYPE PrimitiveType,
2168 DWORD VertexType,
2169 void *Vertices,
2170 DWORD NumVertices,
2171 DWORD Flags)
2173 FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2174 iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2176 return D3D_OK;
2180 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2181 D3DPRIMITIVETYPE d3dptPrimitiveType, D3DVERTEXTYPE d3dvtVertexType,
2182 void *lpvVertices, DWORD dwNumVertices, DWORD dwFlags)
2184 DWORD FVF;
2185 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2187 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2188 iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2190 switch(d3dvtVertexType)
2192 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2193 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2194 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2195 default:
2196 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2197 return DDERR_INVALIDPARAMS; /* Should never happen */
2200 return IDirect3DDevice3_BeginIndexed(&This->IDirect3DDevice3_iface,
2201 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2204 /*****************************************************************************
2205 * IDirect3DDevice3::Vertex
2207 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2208 * drawn vertices in a vertex buffer. If the buffer is too small, its
2209 * size is increased.
2211 * Version 2 and 3
2213 * Params:
2214 * Vertex: Pointer to the vertex
2216 * Returns:
2217 * D3D_OK, on success
2218 * DDERR_INVALIDPARAMS if Vertex is NULL
2220 *****************************************************************************/
2221 static HRESULT WINAPI
2222 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2223 void *Vertex)
2225 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2227 TRACE("iface %p, vertex %p.\n", iface, Vertex);
2229 if(!Vertex)
2230 return DDERR_INVALIDPARAMS;
2232 wined3d_mutex_lock();
2233 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2235 BYTE *old_buffer;
2236 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2237 old_buffer = This->vertex_buffer;
2238 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2239 if (old_buffer)
2241 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2242 HeapFree(GetProcessHeap(), 0, old_buffer);
2246 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2247 wined3d_mutex_unlock();
2249 return D3D_OK;
2252 static HRESULT WINAPI IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface, void *lpVertexType)
2254 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2256 TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
2258 return IDirect3DDevice3_Vertex(&This->IDirect3DDevice3_iface, lpVertexType);
2261 /*****************************************************************************
2262 * IDirect3DDevice3::Index
2264 * Specifies an index to a vertex to be drawn. The vertex array has to
2265 * be specified with BeginIndexed first.
2267 * Parameters:
2268 * VertexIndex: The index of the vertex to draw
2270 * Returns:
2271 * D3D_OK because it's a stub
2273 *****************************************************************************/
2274 static HRESULT WINAPI
2275 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2276 WORD VertexIndex)
2278 FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
2280 return D3D_OK;
2283 static HRESULT WINAPI IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface, WORD wVertexIndex)
2285 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2287 TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
2289 return IDirect3DDevice3_Index(&This->IDirect3DDevice3_iface, wVertexIndex);
2292 /*****************************************************************************
2293 * IDirect3DDevice3::End
2295 * Ends a draw begun with IDirect3DDevice3::Begin or
2296 * IDirect3DDevice::BeginIndexed. The vertices specified with
2297 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2298 * the IDirect3DDevice7::DrawPrimitive method. So far only
2299 * non-indexed mode is supported
2301 * Version 2 and 3
2303 * Params:
2304 * Flags: Some flags, as usual. Don't know which are defined
2306 * Returns:
2307 * The return value of IDirect3DDevice7::DrawPrimitive
2309 *****************************************************************************/
2310 static HRESULT WINAPI
2311 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2312 DWORD Flags)
2314 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2316 TRACE("iface %p, flags %#x.\n", iface, Flags);
2318 return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface, This->primitive_type,
2319 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2322 static HRESULT WINAPI IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface, DWORD dwFlags)
2324 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2326 TRACE("iface %p, flags %#x.\n", iface, dwFlags);
2328 return IDirect3DDevice3_End(&This->IDirect3DDevice3_iface, dwFlags);
2331 /*****************************************************************************
2332 * IDirect3DDevice7::GetRenderState
2334 * Returns the value of a render state. The possible render states are
2335 * defined in include/d3dtypes.h
2337 * Version 2, 3 and 7
2339 * Params:
2340 * RenderStateType: Render state to return the current setting of
2341 * Value: Address to store the value at
2343 * Returns:
2344 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2345 * DDERR_INVALIDPARAMS if Value == NULL
2347 *****************************************************************************/
2348 static HRESULT IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2349 D3DRENDERSTATETYPE RenderStateType, DWORD *Value)
2351 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
2352 HRESULT hr;
2354 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2356 if(!Value)
2357 return DDERR_INVALIDPARAMS;
2359 wined3d_mutex_lock();
2360 switch(RenderStateType)
2362 case D3DRENDERSTATE_TEXTUREMAG:
2364 enum wined3d_texture_filter_type tex_mag;
2366 hr = wined3d_device_get_sampler_state(This->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, &tex_mag);
2368 switch (tex_mag)
2370 case WINED3D_TEXF_POINT:
2371 *Value = D3DFILTER_NEAREST;
2372 break;
2373 case WINED3D_TEXF_LINEAR:
2374 *Value = D3DFILTER_LINEAR;
2375 break;
2376 default:
2377 ERR("Unhandled texture mag %d !\n",tex_mag);
2378 *Value = 0;
2380 break;
2383 case D3DRENDERSTATE_TEXTUREMIN:
2385 enum wined3d_texture_filter_type tex_min;
2386 enum wined3d_texture_filter_type tex_mip;
2388 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2389 0, WINED3D_SAMP_MIN_FILTER, &tex_min);
2390 if (FAILED(hr))
2392 wined3d_mutex_unlock();
2393 return hr;
2395 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2396 0, WINED3D_SAMP_MIP_FILTER, &tex_mip);
2398 switch (tex_min)
2400 case WINED3D_TEXF_POINT:
2401 switch (tex_mip)
2403 case WINED3D_TEXF_NONE:
2404 *Value = D3DFILTER_NEAREST;
2405 break;
2406 case WINED3D_TEXF_POINT:
2407 *Value = D3DFILTER_MIPNEAREST;
2408 break;
2409 case WINED3D_TEXF_LINEAR:
2410 *Value = D3DFILTER_LINEARMIPNEAREST;
2411 break;
2412 default:
2413 ERR("Unhandled mip filter %#x.\n", tex_mip);
2414 *Value = D3DFILTER_NEAREST;
2415 break;
2417 break;
2418 case WINED3D_TEXF_LINEAR:
2419 switch (tex_mip)
2421 case WINED3D_TEXF_NONE:
2422 *Value = D3DFILTER_LINEAR;
2423 break;
2424 case WINED3D_TEXF_POINT:
2425 *Value = D3DFILTER_MIPLINEAR;
2426 break;
2427 case WINED3D_TEXF_LINEAR:
2428 *Value = D3DFILTER_LINEARMIPLINEAR;
2429 break;
2430 default:
2431 ERR("Unhandled mip filter %#x.\n", tex_mip);
2432 *Value = D3DFILTER_LINEAR;
2433 break;
2435 break;
2436 default:
2437 ERR("Unhandled texture min filter %#x.\n",tex_min);
2438 *Value = D3DFILTER_NEAREST;
2439 break;
2441 break;
2444 case D3DRENDERSTATE_TEXTUREADDRESS:
2445 case D3DRENDERSTATE_TEXTUREADDRESSU:
2446 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2447 0, WINED3D_SAMP_ADDRESS_U, Value);
2448 break;
2449 case D3DRENDERSTATE_TEXTUREADDRESSV:
2450 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2451 0, WINED3D_SAMP_ADDRESS_V, Value);
2452 break;
2454 case D3DRENDERSTATE_BORDERCOLOR:
2455 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2456 hr = E_NOTIMPL;
2457 break;
2459 case D3DRENDERSTATE_TEXTUREHANDLE:
2460 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2461 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2462 hr = DDERR_INVALIDPARAMS;
2463 break;
2465 case D3DRENDERSTATE_ZBIAS:
2466 hr = wined3d_device_get_render_state(This->wined3d_device, WINED3D_RS_DEPTHBIAS, Value);
2467 break;
2469 default:
2470 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2471 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2473 FIXME("Unhandled stipple pattern render state (%#x).\n",
2474 RenderStateType);
2475 hr = E_NOTIMPL;
2476 break;
2478 hr = wined3d_device_get_render_state(This->wined3d_device, RenderStateType, Value);
2480 wined3d_mutex_unlock();
2482 return hr;
2485 static HRESULT WINAPI
2486 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2487 D3DRENDERSTATETYPE RenderStateType,
2488 DWORD *Value)
2490 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2493 static HRESULT WINAPI
2494 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2495 D3DRENDERSTATETYPE RenderStateType,
2496 DWORD *Value)
2498 HRESULT hr;
2499 WORD old_fpucw;
2501 old_fpucw = d3d_fpu_setup();
2502 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2503 set_fpu_control_word(old_fpucw);
2505 return hr;
2508 static HRESULT WINAPI
2509 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2510 D3DRENDERSTATETYPE dwRenderStateType,
2511 DWORD *lpdwRenderState)
2513 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2514 HRESULT hr;
2516 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2518 switch(dwRenderStateType)
2520 case D3DRENDERSTATE_TEXTUREHANDLE:
2522 /* This state is wrapped to SetTexture in SetRenderState, so
2523 * it has to be wrapped to GetTexture here. */
2524 struct wined3d_texture *tex = NULL;
2525 *lpdwRenderState = 0;
2527 wined3d_mutex_lock();
2528 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2529 if (SUCCEEDED(hr) && tex)
2531 /* The parent of the texture is the IDirectDrawSurface7
2532 * interface of the ddraw surface. */
2533 IDirectDrawSurfaceImpl *parent = wined3d_texture_get_parent(tex);
2534 if (parent) *lpdwRenderState = parent->Handle;
2535 wined3d_texture_decref(tex);
2537 wined3d_mutex_unlock();
2539 return hr;
2542 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2544 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2545 the mapping to get the value. */
2546 DWORD colorop, colorarg1, colorarg2;
2547 DWORD alphaop, alphaarg1, alphaarg2;
2549 wined3d_mutex_lock();
2551 This->legacyTextureBlending = TRUE;
2553 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_COLOR_OP, &colorop);
2554 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_COLOR_ARG1, &colorarg1);
2555 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_COLOR_ARG2, &colorarg2);
2556 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_ALPHA_OP, &alphaop);
2557 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG1, &alphaarg1);
2558 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG2, &alphaarg2);
2560 if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2561 && alphaop == WINED3D_TOP_SELECT_ARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2562 *lpdwRenderState = D3DTBLEND_DECAL;
2563 else if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2564 && alphaop == WINED3D_TOP_MODULATE
2565 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2566 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2567 else if (colorop == WINED3D_TOP_MODULATE
2568 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2569 && alphaop == WINED3D_TOP_MODULATE
2570 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2571 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2572 else
2574 struct wined3d_texture *tex = NULL;
2575 HRESULT hr;
2576 BOOL tex_alpha = FALSE;
2577 DDPIXELFORMAT ddfmt;
2579 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2581 if(hr == WINED3D_OK && tex)
2583 struct wined3d_resource *sub_resource;
2585 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2587 struct wined3d_resource_desc desc;
2589 wined3d_resource_get_desc(sub_resource, &desc);
2590 ddfmt.dwSize = sizeof(ddfmt);
2591 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2592 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2595 wined3d_texture_decref(tex);
2598 if (!(colorop == WINED3D_TOP_MODULATE
2599 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2600 && alphaop == (tex_alpha ? WINED3D_TOP_SELECT_ARG1 : WINED3D_TOP_SELECT_ARG2)
2601 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2602 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous.\n");
2604 *lpdwRenderState = D3DTBLEND_MODULATE;
2607 wined3d_mutex_unlock();
2609 return D3D_OK;
2612 default:
2613 return IDirect3DDevice7_GetRenderState(&This->IDirect3DDevice7_iface, dwRenderStateType, lpdwRenderState);
2617 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2618 D3DRENDERSTATETYPE dwRenderStateType, DWORD *lpdwRenderState)
2620 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2622 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2624 return IDirect3DDevice3_GetRenderState(&This->IDirect3DDevice3_iface,
2625 dwRenderStateType, lpdwRenderState);
2628 /*****************************************************************************
2629 * IDirect3DDevice7::SetRenderState
2631 * Sets a render state. The possible render states are defined in
2632 * include/d3dtypes.h
2634 * Version 2, 3 and 7
2636 * Params:
2637 * RenderStateType: State to set
2638 * Value: Value to assign to that state
2640 * Returns:
2641 * D3D_OK on success,
2642 * for details see IWineD3DDevice::SetRenderState
2644 *****************************************************************************/
2645 static HRESULT
2646 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2647 D3DRENDERSTATETYPE RenderStateType,
2648 DWORD Value)
2650 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
2651 HRESULT hr;
2653 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2655 wined3d_mutex_lock();
2656 /* Some render states need special care */
2657 switch(RenderStateType)
2660 * The ddraw texture filter mapping works like this:
2661 * D3DFILTER_NEAREST Point min/mag, no mip
2662 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2663 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2665 * D3DFILTER_LINEAR Linear min/mag, no mip
2666 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2667 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2669 * This is the opposite of the GL naming convention,
2670 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2672 case D3DRENDERSTATE_TEXTUREMAG:
2674 enum wined3d_texture_filter_type tex_mag;
2676 switch (Value)
2678 case D3DFILTER_NEAREST:
2679 case D3DFILTER_MIPNEAREST:
2680 case D3DFILTER_LINEARMIPNEAREST:
2681 tex_mag = WINED3D_TEXF_POINT;
2682 break;
2683 case D3DFILTER_LINEAR:
2684 case D3DFILTER_MIPLINEAR:
2685 case D3DFILTER_LINEARMIPLINEAR:
2686 tex_mag = WINED3D_TEXF_LINEAR;
2687 break;
2688 default:
2689 tex_mag = WINED3D_TEXF_POINT;
2690 ERR("Unhandled texture mag %d !\n",Value);
2691 break;
2694 hr = wined3d_device_set_sampler_state(This->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, tex_mag);
2695 break;
2698 case D3DRENDERSTATE_TEXTUREMIN:
2700 enum wined3d_texture_filter_type tex_min;
2701 enum wined3d_texture_filter_type tex_mip;
2703 switch ((D3DTEXTUREFILTER)Value)
2705 case D3DFILTER_NEAREST:
2706 tex_min = WINED3D_TEXF_POINT;
2707 tex_mip = WINED3D_TEXF_NONE;
2708 break;
2709 case D3DFILTER_LINEAR:
2710 tex_min = WINED3D_TEXF_LINEAR;
2711 tex_mip = WINED3D_TEXF_NONE;
2712 break;
2713 case D3DFILTER_MIPNEAREST:
2714 tex_min = WINED3D_TEXF_POINT;
2715 tex_mip = WINED3D_TEXF_POINT;
2716 break;
2717 case D3DFILTER_MIPLINEAR:
2718 tex_min = WINED3D_TEXF_LINEAR;
2719 tex_mip = WINED3D_TEXF_POINT;
2720 break;
2721 case D3DFILTER_LINEARMIPNEAREST:
2722 tex_min = WINED3D_TEXF_POINT;
2723 tex_mip = WINED3D_TEXF_LINEAR;
2724 break;
2725 case D3DFILTER_LINEARMIPLINEAR:
2726 tex_min = WINED3D_TEXF_LINEAR;
2727 tex_mip = WINED3D_TEXF_LINEAR;
2728 break;
2730 default:
2731 ERR("Unhandled texture min %d !\n",Value);
2732 tex_min = WINED3D_TEXF_POINT;
2733 tex_mip = WINED3D_TEXF_NONE;
2734 break;
2737 wined3d_device_set_sampler_state(This->wined3d_device,
2738 0, WINED3D_SAMP_MIP_FILTER, tex_mip);
2739 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2740 0, WINED3D_SAMP_MIN_FILTER, tex_min);
2741 break;
2744 case D3DRENDERSTATE_TEXTUREADDRESS:
2745 wined3d_device_set_sampler_state(This->wined3d_device,
2746 0, WINED3D_SAMP_ADDRESS_V, Value);
2747 /* Drop through */
2748 case D3DRENDERSTATE_TEXTUREADDRESSU:
2749 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2750 0, WINED3D_SAMP_ADDRESS_U, Value);
2751 break;
2752 case D3DRENDERSTATE_TEXTUREADDRESSV:
2753 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2754 0, WINED3D_SAMP_ADDRESS_V, Value);
2755 break;
2757 case D3DRENDERSTATE_BORDERCOLOR:
2758 /* This should probably just forward to the corresponding sampler
2759 * state. Needs tests. */
2760 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2761 hr = E_NOTIMPL;
2762 break;
2764 case D3DRENDERSTATE_TEXTUREHANDLE:
2765 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2766 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2767 hr = DDERR_INVALIDPARAMS;
2768 break;
2770 case D3DRENDERSTATE_ZBIAS:
2771 hr = wined3d_device_set_render_state(This->wined3d_device, WINED3D_RS_DEPTHBIAS, Value);
2772 break;
2774 default:
2775 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2776 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2778 FIXME("Unhandled stipple pattern render state (%#x).\n",
2779 RenderStateType);
2780 hr = E_NOTIMPL;
2781 break;
2784 hr = wined3d_device_set_render_state(This->wined3d_device, RenderStateType, Value);
2785 break;
2787 wined3d_mutex_unlock();
2789 return hr;
2792 static HRESULT WINAPI
2793 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2794 D3DRENDERSTATETYPE RenderStateType,
2795 DWORD Value)
2797 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2800 static HRESULT WINAPI
2801 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2802 D3DRENDERSTATETYPE RenderStateType,
2803 DWORD Value)
2805 HRESULT hr;
2806 WORD old_fpucw;
2808 old_fpucw = d3d_fpu_setup();
2809 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2810 set_fpu_control_word(old_fpucw);
2812 return hr;
2815 static HRESULT WINAPI
2816 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2817 D3DRENDERSTATETYPE RenderStateType,
2818 DWORD Value)
2820 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2821 for this state can be directly mapped to texture stage colorop and alphaop, but
2822 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2823 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2824 alphaarg when needed.
2826 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2828 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2829 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2830 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2831 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2832 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2833 in device - TRUE if the app is using TEXTUREMAPBLEND.
2835 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2836 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2837 unless some broken game will be found that cares. */
2839 HRESULT hr;
2840 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2842 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2844 wined3d_mutex_lock();
2846 switch(RenderStateType)
2848 case D3DRENDERSTATE_TEXTUREHANDLE:
2850 IDirectDrawSurfaceImpl *surf;
2852 if(Value == 0)
2854 hr = wined3d_device_set_texture(This->wined3d_device, 0, NULL);
2855 break;
2858 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2859 if (!surf)
2861 WARN("Invalid texture handle.\n");
2862 hr = DDERR_INVALIDPARAMS;
2863 break;
2866 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2867 break;
2870 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2872 This->legacyTextureBlending = TRUE;
2874 switch ( (D3DTEXTUREBLEND) Value)
2876 case D3DTBLEND_MODULATE:
2878 struct wined3d_texture *tex = NULL;
2879 BOOL tex_alpha = FALSE;
2880 DDPIXELFORMAT ddfmt;
2882 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2884 if(hr == WINED3D_OK && tex)
2886 struct wined3d_resource *sub_resource;
2888 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2890 struct wined3d_resource_desc desc;
2892 wined3d_resource_get_desc(sub_resource, &desc);
2893 ddfmt.dwSize = sizeof(ddfmt);
2894 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2895 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2898 wined3d_texture_decref(tex);
2901 if (tex_alpha)
2902 wined3d_device_set_texture_stage_state(This->wined3d_device,
2903 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2904 else
2905 wined3d_device_set_texture_stage_state(This->wined3d_device,
2906 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2907 wined3d_device_set_texture_stage_state(This->wined3d_device,
2908 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2909 wined3d_device_set_texture_stage_state(This->wined3d_device,
2910 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2911 wined3d_device_set_texture_stage_state(This->wined3d_device,
2912 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2913 wined3d_device_set_texture_stage_state(This->wined3d_device,
2914 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2915 wined3d_device_set_texture_stage_state(This->wined3d_device,
2916 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2917 break;
2920 case D3DTBLEND_ADD:
2921 wined3d_device_set_texture_stage_state(This->wined3d_device,
2922 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_ADD);
2923 wined3d_device_set_texture_stage_state(This->wined3d_device,
2924 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2925 wined3d_device_set_texture_stage_state(This->wined3d_device,
2926 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2927 wined3d_device_set_texture_stage_state(This->wined3d_device,
2928 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2929 wined3d_device_set_texture_stage_state(This->wined3d_device,
2930 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2931 break;
2933 case D3DTBLEND_MODULATEALPHA:
2934 wined3d_device_set_texture_stage_state(This->wined3d_device,
2935 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2936 wined3d_device_set_texture_stage_state(This->wined3d_device,
2937 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2938 wined3d_device_set_texture_stage_state(This->wined3d_device,
2939 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2940 wined3d_device_set_texture_stage_state(This->wined3d_device,
2941 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2942 wined3d_device_set_texture_stage_state(This->wined3d_device,
2943 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2944 wined3d_device_set_texture_stage_state(This->wined3d_device,
2945 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_MODULATE);
2946 break;
2948 case D3DTBLEND_COPY:
2949 case D3DTBLEND_DECAL:
2950 wined3d_device_set_texture_stage_state(This->wined3d_device,
2951 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2952 wined3d_device_set_texture_stage_state(This->wined3d_device,
2953 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2954 wined3d_device_set_texture_stage_state(This->wined3d_device,
2955 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_SELECT_ARG1);
2956 wined3d_device_set_texture_stage_state(This->wined3d_device,
2957 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2958 break;
2960 case D3DTBLEND_DECALALPHA:
2961 wined3d_device_set_texture_stage_state(This->wined3d_device,
2962 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_BLEND_TEXTURE_ALPHA);
2963 wined3d_device_set_texture_stage_state(This->wined3d_device,
2964 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2965 wined3d_device_set_texture_stage_state(This->wined3d_device,
2966 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2967 wined3d_device_set_texture_stage_state(This->wined3d_device,
2968 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2969 wined3d_device_set_texture_stage_state(This->wined3d_device,
2970 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2971 break;
2973 default:
2974 ERR("Unhandled texture environment %d !\n",Value);
2977 hr = D3D_OK;
2978 break;
2981 default:
2982 hr = IDirect3DDevice7_SetRenderState(&This->IDirect3DDevice7_iface, RenderStateType, Value);
2983 break;
2985 wined3d_mutex_unlock();
2987 return hr;
2990 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2991 D3DRENDERSTATETYPE RenderStateType, DWORD Value)
2993 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2995 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2997 return IDirect3DDevice3_SetRenderState(&This->IDirect3DDevice3_iface, RenderStateType, Value);
3000 /*****************************************************************************
3001 * Direct3DDevice3::SetLightState
3003 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
3004 * light states are forwarded to Direct3DDevice7 render states
3006 * Version 2 and 3
3008 * Params:
3009 * LightStateType: The light state to change
3010 * Value: The value to assign to that light state
3012 * Returns:
3013 * D3D_OK on success
3014 * DDERR_INVALIDPARAMS if the parameters were incorrect
3015 * Also check IDirect3DDevice7::SetRenderState
3017 *****************************************************************************/
3018 static HRESULT WINAPI
3019 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
3020 D3DLIGHTSTATETYPE LightStateType,
3021 DWORD Value)
3023 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3024 HRESULT hr;
3026 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3028 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3030 TRACE("Unexpected Light State Type\n");
3031 return DDERR_INVALIDPARAMS;
3034 wined3d_mutex_lock();
3035 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3037 IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
3038 if (!m)
3040 WARN("Invalid material handle.\n");
3041 wined3d_mutex_unlock();
3042 return DDERR_INVALIDPARAMS;
3045 TRACE(" activating material %p.\n", m);
3046 material_activate(m);
3048 This->material = Value;
3050 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3052 switch (Value)
3054 case D3DCOLOR_MONO:
3055 ERR("DDCOLOR_MONO should not happen!\n");
3056 break;
3057 case D3DCOLOR_RGB:
3058 /* We are already in this mode */
3059 TRACE("Setting color model to RGB (no-op).\n");
3060 break;
3061 default:
3062 ERR("Unknown color model!\n");
3063 wined3d_mutex_unlock();
3064 return DDERR_INVALIDPARAMS;
3067 else
3069 D3DRENDERSTATETYPE rs;
3070 switch (LightStateType)
3072 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3073 rs = D3DRENDERSTATE_AMBIENT;
3074 break;
3075 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3076 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3077 break;
3078 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3079 rs = D3DRENDERSTATE_FOGSTART;
3080 break;
3081 case D3DLIGHTSTATE_FOGEND: /* 6 */
3082 rs = D3DRENDERSTATE_FOGEND;
3083 break;
3084 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3085 rs = D3DRENDERSTATE_FOGDENSITY;
3086 break;
3087 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3088 rs = D3DRENDERSTATE_COLORVERTEX;
3089 break;
3090 default:
3091 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3092 wined3d_mutex_unlock();
3093 return DDERR_INVALIDPARAMS;
3096 hr = IDirect3DDevice7_SetRenderState(&This->IDirect3DDevice7_iface, rs, Value);
3097 wined3d_mutex_unlock();
3098 return hr;
3100 wined3d_mutex_unlock();
3102 return D3D_OK;
3105 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3106 D3DLIGHTSTATETYPE LightStateType, DWORD Value)
3108 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3110 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3112 return IDirect3DDevice3_SetLightState(&This->IDirect3DDevice3_iface, LightStateType, Value);
3115 /*****************************************************************************
3116 * IDirect3DDevice3::GetLightState
3118 * Returns the current setting of a light state. The state is read from
3119 * the Direct3DDevice7 render state.
3121 * Version 2 and 3
3123 * Params:
3124 * LightStateType: The light state to return
3125 * Value: The address to store the light state setting at
3127 * Returns:
3128 * D3D_OK on success
3129 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3130 * Also see IDirect3DDevice7::GetRenderState
3132 *****************************************************************************/
3133 static HRESULT WINAPI
3134 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3135 D3DLIGHTSTATETYPE LightStateType,
3136 DWORD *Value)
3138 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3139 HRESULT hr;
3141 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3143 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3145 TRACE("Unexpected Light State Type\n");
3146 return DDERR_INVALIDPARAMS;
3149 if(!Value)
3150 return DDERR_INVALIDPARAMS;
3152 wined3d_mutex_lock();
3153 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3155 *Value = This->material;
3157 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3159 *Value = D3DCOLOR_RGB;
3161 else
3163 D3DRENDERSTATETYPE rs;
3164 switch (LightStateType)
3166 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3167 rs = D3DRENDERSTATE_AMBIENT;
3168 break;
3169 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3170 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3171 break;
3172 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3173 rs = D3DRENDERSTATE_FOGSTART;
3174 break;
3175 case D3DLIGHTSTATE_FOGEND: /* 6 */
3176 rs = D3DRENDERSTATE_FOGEND;
3177 break;
3178 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3179 rs = D3DRENDERSTATE_FOGDENSITY;
3180 break;
3181 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3182 rs = D3DRENDERSTATE_COLORVERTEX;
3183 break;
3184 default:
3185 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3186 wined3d_mutex_unlock();
3187 return DDERR_INVALIDPARAMS;
3190 hr = IDirect3DDevice7_GetRenderState(&This->IDirect3DDevice7_iface, rs, Value);
3191 wined3d_mutex_unlock();
3192 return hr;
3194 wined3d_mutex_unlock();
3196 return D3D_OK;
3199 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3200 D3DLIGHTSTATETYPE LightStateType, DWORD *Value)
3202 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3204 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3206 return IDirect3DDevice3_GetLightState(&This->IDirect3DDevice3_iface, LightStateType, Value);
3209 /*****************************************************************************
3210 * IDirect3DDevice7::SetTransform
3212 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3213 * in include/d3dtypes.h.
3214 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3215 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3216 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3218 * Version 2, 3 and 7
3220 * Params:
3221 * TransformStateType: transform state to set
3222 * Matrix: Matrix to assign to the state
3224 * Returns:
3225 * D3D_OK on success
3226 * DDERR_INVALIDPARAMS if Matrix == NULL
3227 * For details see IWineD3DDevice::SetTransform
3229 *****************************************************************************/
3230 static HRESULT
3231 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3232 D3DTRANSFORMSTATETYPE TransformStateType,
3233 D3DMATRIX *Matrix)
3235 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3236 D3DTRANSFORMSTATETYPE type;
3237 HRESULT hr;
3239 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3241 switch (TransformStateType)
3243 case D3DTRANSFORMSTATE_WORLD:
3244 type = WINED3D_TS_WORLD_MATRIX(0);
3245 break;
3246 case D3DTRANSFORMSTATE_WORLD1:
3247 type = WINED3D_TS_WORLD_MATRIX(1);
3248 break;
3249 case D3DTRANSFORMSTATE_WORLD2:
3250 type = WINED3D_TS_WORLD_MATRIX(2);
3251 break;
3252 case D3DTRANSFORMSTATE_WORLD3:
3253 type = WINED3D_TS_WORLD_MATRIX(3);
3254 break;
3255 default:
3256 type = TransformStateType;
3259 if (!Matrix)
3260 return DDERR_INVALIDPARAMS;
3262 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3263 wined3d_mutex_lock();
3264 hr = wined3d_device_set_transform(This->wined3d_device, type, (struct wined3d_matrix *)Matrix);
3265 wined3d_mutex_unlock();
3267 return hr;
3270 static HRESULT WINAPI
3271 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3272 D3DTRANSFORMSTATETYPE TransformStateType,
3273 D3DMATRIX *Matrix)
3275 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3278 static HRESULT WINAPI
3279 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3280 D3DTRANSFORMSTATETYPE TransformStateType,
3281 D3DMATRIX *Matrix)
3283 HRESULT hr;
3284 WORD old_fpucw;
3286 old_fpucw = d3d_fpu_setup();
3287 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3288 set_fpu_control_word(old_fpucw);
3290 return hr;
3293 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3294 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3296 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3298 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3300 if (!matrix)
3301 return DDERR_INVALIDPARAMS;
3303 if (state == D3DTRANSFORMSTATE_PROJECTION)
3305 D3DMATRIX projection;
3306 HRESULT hr;
3308 wined3d_mutex_lock();
3309 multiply_matrix(&projection, &This->legacy_clipspace, matrix);
3310 hr = wined3d_device_set_transform(This->wined3d_device,
3311 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3312 if (SUCCEEDED(hr))
3313 This->legacy_projection = *matrix;
3314 wined3d_mutex_unlock();
3316 return hr;
3319 return IDirect3DDevice7_SetTransform(&This->IDirect3DDevice7_iface, state, matrix);
3322 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3323 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3325 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3327 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3329 return IDirect3DDevice7_SetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3332 /*****************************************************************************
3333 * IDirect3DDevice7::GetTransform
3335 * Returns the matrix assigned to a transform state
3336 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3337 * SetTransform
3339 * Params:
3340 * TransformStateType: State to read the matrix from
3341 * Matrix: Address to store the matrix at
3343 * Returns:
3344 * D3D_OK on success
3345 * DDERR_INVALIDPARAMS if Matrix == NULL
3346 * For details, see IWineD3DDevice::GetTransform
3348 *****************************************************************************/
3349 static HRESULT
3350 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3351 D3DTRANSFORMSTATETYPE TransformStateType,
3352 D3DMATRIX *Matrix)
3354 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3355 D3DTRANSFORMSTATETYPE type;
3356 HRESULT hr;
3358 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3360 switch(TransformStateType)
3362 case D3DTRANSFORMSTATE_WORLD:
3363 type = WINED3D_TS_WORLD_MATRIX(0);
3364 break;
3365 case D3DTRANSFORMSTATE_WORLD1:
3366 type = WINED3D_TS_WORLD_MATRIX(1);
3367 break;
3368 case D3DTRANSFORMSTATE_WORLD2:
3369 type = WINED3D_TS_WORLD_MATRIX(2);
3370 break;
3371 case D3DTRANSFORMSTATE_WORLD3:
3372 type = WINED3D_TS_WORLD_MATRIX(3);
3373 break;
3374 default:
3375 type = TransformStateType;
3378 if(!Matrix)
3379 return DDERR_INVALIDPARAMS;
3381 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3382 wined3d_mutex_lock();
3383 hr = wined3d_device_get_transform(This->wined3d_device, type, (struct wined3d_matrix *)Matrix);
3384 wined3d_mutex_unlock();
3386 return hr;
3389 static HRESULT WINAPI
3390 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3391 D3DTRANSFORMSTATETYPE TransformStateType,
3392 D3DMATRIX *Matrix)
3394 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3397 static HRESULT WINAPI
3398 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3399 D3DTRANSFORMSTATETYPE TransformStateType,
3400 D3DMATRIX *Matrix)
3402 HRESULT hr;
3403 WORD old_fpucw;
3405 old_fpucw = d3d_fpu_setup();
3406 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3407 set_fpu_control_word(old_fpucw);
3409 return hr;
3412 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3413 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3415 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3417 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3419 if (!matrix)
3420 return DDERR_INVALIDPARAMS;
3422 if (state == D3DTRANSFORMSTATE_PROJECTION)
3424 wined3d_mutex_lock();
3425 *matrix = This->legacy_projection;
3426 wined3d_mutex_unlock();
3427 return DD_OK;
3430 return IDirect3DDevice7_GetTransform(&This->IDirect3DDevice7_iface, state, matrix);
3433 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3434 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3436 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3438 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3440 return IDirect3DDevice7_GetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3443 /*****************************************************************************
3444 * IDirect3DDevice7::MultiplyTransform
3446 * Multiplies the already-set transform matrix of a transform state
3447 * with another matrix. For the world matrix, see SetTransform
3449 * Version 2, 3 and 7
3451 * Params:
3452 * TransformStateType: Transform state to multiply
3453 * D3DMatrix Matrix to multiply with.
3455 * Returns
3456 * D3D_OK on success
3457 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3458 * For details, see IWineD3DDevice::MultiplyTransform
3460 *****************************************************************************/
3461 static HRESULT
3462 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3463 D3DTRANSFORMSTATETYPE TransformStateType,
3464 D3DMATRIX *D3DMatrix)
3466 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3467 HRESULT hr;
3468 D3DTRANSFORMSTATETYPE type;
3470 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3472 switch(TransformStateType)
3474 case D3DTRANSFORMSTATE_WORLD:
3475 type = WINED3D_TS_WORLD_MATRIX(0);
3476 break;
3477 case D3DTRANSFORMSTATE_WORLD1:
3478 type = WINED3D_TS_WORLD_MATRIX(1);
3479 break;
3480 case D3DTRANSFORMSTATE_WORLD2:
3481 type = WINED3D_TS_WORLD_MATRIX(2);
3482 break;
3483 case D3DTRANSFORMSTATE_WORLD3:
3484 type = WINED3D_TS_WORLD_MATRIX(3);
3485 break;
3486 default:
3487 type = TransformStateType;
3490 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3491 wined3d_mutex_lock();
3492 hr = wined3d_device_multiply_transform(This->wined3d_device,
3493 type, (struct wined3d_matrix *)D3DMatrix);
3494 wined3d_mutex_unlock();
3496 return hr;
3499 static HRESULT WINAPI
3500 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3501 D3DTRANSFORMSTATETYPE TransformStateType,
3502 D3DMATRIX *D3DMatrix)
3504 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3507 static HRESULT WINAPI
3508 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3509 D3DTRANSFORMSTATETYPE TransformStateType,
3510 D3DMATRIX *D3DMatrix)
3512 HRESULT hr;
3513 WORD old_fpucw;
3515 old_fpucw = d3d_fpu_setup();
3516 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3517 set_fpu_control_word(old_fpucw);
3519 return hr;
3522 static HRESULT WINAPI IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3523 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3525 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3527 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3529 if (state == D3DTRANSFORMSTATE_PROJECTION)
3531 D3DMATRIX projection, tmp;
3532 HRESULT hr;
3534 wined3d_mutex_lock();
3535 multiply_matrix(&tmp, &This->legacy_projection, matrix);
3536 multiply_matrix(&projection, &This->legacy_clipspace, &tmp);
3537 hr = wined3d_device_set_transform(This->wined3d_device,
3538 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3539 if (SUCCEEDED(hr))
3540 This->legacy_projection = tmp;
3541 wined3d_mutex_unlock();
3543 return hr;
3546 return IDirect3DDevice7_MultiplyTransform(&This->IDirect3DDevice7_iface, state, matrix);
3549 static HRESULT WINAPI IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3550 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3552 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3554 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3556 return IDirect3DDevice7_MultiplyTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3559 /*****************************************************************************
3560 * IDirect3DDevice7::DrawPrimitive
3562 * Draws primitives based on vertices in an application-provided pointer
3564 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3565 * an FVF format for D3D7
3567 * Params:
3568 * PrimitiveType: The type of the primitives to draw
3569 * Vertex type: Flexible vertex format vertex description
3570 * Vertices: Pointer to the vertex array
3571 * VertexCount: The number of vertices to draw
3572 * Flags: As usual a few flags
3574 * Returns:
3575 * D3D_OK on success
3576 * DDERR_INVALIDPARAMS if Vertices is NULL
3577 * For details, see IWineD3DDevice::DrawPrimitiveUP
3579 *****************************************************************************/
3580 static HRESULT
3581 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3582 D3DPRIMITIVETYPE PrimitiveType,
3583 DWORD VertexType,
3584 void *Vertices,
3585 DWORD VertexCount,
3586 DWORD Flags)
3588 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3589 UINT stride;
3590 HRESULT hr;
3592 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3593 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3595 if(!Vertices)
3596 return DDERR_INVALIDPARAMS;
3598 /* Get the stride */
3599 stride = get_flexible_vertex_size(VertexType);
3601 /* Set the FVF */
3602 wined3d_mutex_lock();
3603 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3604 if(hr != D3D_OK)
3606 wined3d_mutex_unlock();
3607 return hr;
3610 /* This method translates to the user pointer draw of WineD3D */
3611 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3612 hr = wined3d_device_draw_primitive_up(This->wined3d_device, VertexCount, Vertices, stride);
3613 wined3d_mutex_unlock();
3615 return hr;
3618 static HRESULT WINAPI
3619 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3620 D3DPRIMITIVETYPE PrimitiveType,
3621 DWORD VertexType,
3622 void *Vertices,
3623 DWORD VertexCount,
3624 DWORD Flags)
3626 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3629 static HRESULT WINAPI
3630 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3631 D3DPRIMITIVETYPE PrimitiveType,
3632 DWORD VertexType,
3633 void *Vertices,
3634 DWORD VertexCount,
3635 DWORD Flags)
3637 HRESULT hr;
3638 WORD old_fpucw;
3640 old_fpucw = d3d_fpu_setup();
3641 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3642 set_fpu_control_word(old_fpucw);
3644 return hr;
3647 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3648 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3649 DWORD Flags)
3651 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3652 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3653 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3655 return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface,
3656 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3659 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3660 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3661 DWORD VertexCount, DWORD Flags)
3663 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3664 DWORD FVF;
3666 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3667 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3669 switch(VertexType)
3671 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3672 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3673 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3674 default:
3675 ERR("Unexpected vertex type %d\n", VertexType);
3676 return DDERR_INVALIDPARAMS; /* Should never happen */
3679 return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface,
3680 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3683 /*****************************************************************************
3684 * IDirect3DDevice7::DrawIndexedPrimitive
3686 * Draws vertices from an application-provided pointer, based on the index
3687 * numbers in a WORD array.
3689 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3690 * an FVF format for D3D7
3692 * Params:
3693 * PrimitiveType: The primitive type to draw
3694 * VertexType: The FVF vertex description
3695 * Vertices: Pointer to the vertex array
3696 * VertexCount: ?
3697 * Indices: Pointer to the index array
3698 * IndexCount: Number of indices = Number of vertices to draw
3699 * Flags: As usual, some flags
3701 * Returns:
3702 * D3D_OK on success
3703 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3704 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3706 *****************************************************************************/
3707 static HRESULT
3708 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3709 D3DPRIMITIVETYPE PrimitiveType,
3710 DWORD VertexType,
3711 void *Vertices,
3712 DWORD VertexCount,
3713 WORD *Indices,
3714 DWORD IndexCount,
3715 DWORD Flags)
3717 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3718 HRESULT hr;
3720 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3721 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3723 /* Set the D3DDevice's FVF */
3724 wined3d_mutex_lock();
3725 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3726 if(FAILED(hr))
3728 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3729 wined3d_mutex_unlock();
3730 return hr;
3733 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3734 hr = wined3d_device_draw_indexed_primitive_up(This->wined3d_device, IndexCount, Indices,
3735 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3736 wined3d_mutex_unlock();
3738 return hr;
3741 static HRESULT WINAPI
3742 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3743 D3DPRIMITIVETYPE PrimitiveType,
3744 DWORD VertexType,
3745 void *Vertices,
3746 DWORD VertexCount,
3747 WORD *Indices,
3748 DWORD IndexCount,
3749 DWORD Flags)
3751 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3754 static HRESULT WINAPI
3755 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3756 D3DPRIMITIVETYPE PrimitiveType,
3757 DWORD VertexType,
3758 void *Vertices,
3759 DWORD VertexCount,
3760 WORD *Indices,
3761 DWORD IndexCount,
3762 DWORD Flags)
3764 HRESULT hr;
3765 WORD old_fpucw;
3767 old_fpucw = d3d_fpu_setup();
3768 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3769 set_fpu_control_word(old_fpucw);
3771 return hr;
3774 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3775 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3776 WORD *Indices, DWORD IndexCount, DWORD Flags)
3778 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3779 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3780 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3782 return IDirect3DDevice7_DrawIndexedPrimitive(&This->IDirect3DDevice7_iface,
3783 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3786 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3787 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3788 DWORD VertexCount, WORD *Indices, DWORD IndexCount, DWORD Flags)
3790 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3791 DWORD FVF;
3793 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3794 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3796 switch(VertexType)
3798 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3799 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3800 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3801 default:
3802 ERR("Unexpected vertex type %d\n", VertexType);
3803 return DDERR_INVALIDPARAMS; /* Should never happen */
3806 return IDirect3DDevice7_DrawIndexedPrimitive(&This->IDirect3DDevice7_iface,
3807 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3810 /*****************************************************************************
3811 * IDirect3DDevice7::SetClipStatus
3813 * Sets the clip status. This defines things as clipping conditions and
3814 * the extents of the clipping region.
3816 * Version 2, 3 and 7
3818 * Params:
3819 * ClipStatus:
3821 * Returns:
3822 * D3D_OK because it's a stub
3823 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3825 *****************************************************************************/
3826 static HRESULT WINAPI
3827 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3828 D3DCLIPSTATUS *ClipStatus)
3830 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3832 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3833 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3835 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3836 return D3D_OK;
3839 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3840 D3DCLIPSTATUS *ClipStatus)
3842 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3843 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3845 return IDirect3DDevice7_SetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3848 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3849 D3DCLIPSTATUS *ClipStatus)
3851 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3852 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3854 return IDirect3DDevice7_SetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3857 /*****************************************************************************
3858 * IDirect3DDevice7::GetClipStatus
3860 * Returns the clip status
3862 * Params:
3863 * ClipStatus: Address to write the clip status to
3865 * Returns:
3866 * D3D_OK because it's a stub
3868 *****************************************************************************/
3869 static HRESULT WINAPI
3870 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3871 D3DCLIPSTATUS *ClipStatus)
3873 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3875 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3876 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3877 return D3D_OK;
3880 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3881 D3DCLIPSTATUS *ClipStatus)
3883 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3884 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3886 return IDirect3DDevice7_GetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3889 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3890 D3DCLIPSTATUS *ClipStatus)
3892 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3893 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3895 return IDirect3DDevice7_GetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3898 /*****************************************************************************
3899 * IDirect3DDevice::DrawPrimitiveStrided
3901 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3903 * Version 3 and 7
3905 * Params:
3906 * PrimitiveType: The primitive type to draw
3907 * VertexType: The FVF description of the vertices to draw (for the stride??)
3908 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3909 * the vertex data locations
3910 * VertexCount: The number of vertices to draw
3911 * Flags: Some flags
3913 * Returns:
3914 * D3D_OK, because it's a stub
3915 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3916 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3918 *****************************************************************************/
3919 static HRESULT
3920 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3921 D3DPRIMITIVETYPE PrimitiveType,
3922 DWORD VertexType,
3923 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3924 DWORD VertexCount,
3925 DWORD Flags)
3927 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3928 struct wined3d_strided_data wined3d_strided;
3929 DWORD i;
3930 HRESULT hr;
3932 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3933 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3935 memset(&wined3d_strided, 0, sizeof(wined3d_strided));
3936 /* Get the strided data right. the wined3d structure is a bit bigger
3937 * Watch out: The contents of the strided data are determined by the fvf,
3938 * not by the members set in D3DDrawPrimStrideData. So it's valid
3939 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3940 * not set in the fvf.
3942 if(VertexType & D3DFVF_POSITION_MASK)
3944 wined3d_strided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3945 wined3d_strided.position.data = D3DDrawPrimStrideData->position.lpvData;
3946 wined3d_strided.position.stride = D3DDrawPrimStrideData->position.dwStride;
3947 if (VertexType & D3DFVF_XYZRHW)
3949 wined3d_strided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3950 wined3d_strided.position_transformed = TRUE;
3952 else
3954 wined3d_strided.position_transformed = FALSE;
3958 if (VertexType & D3DFVF_NORMAL)
3960 wined3d_strided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3961 wined3d_strided.normal.data = D3DDrawPrimStrideData->normal.lpvData;
3962 wined3d_strided.normal.stride = D3DDrawPrimStrideData->normal.dwStride;
3965 if (VertexType & D3DFVF_DIFFUSE)
3967 wined3d_strided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3968 wined3d_strided.diffuse.data = D3DDrawPrimStrideData->diffuse.lpvData;
3969 wined3d_strided.diffuse.stride = D3DDrawPrimStrideData->diffuse.dwStride;
3972 if (VertexType & D3DFVF_SPECULAR)
3974 wined3d_strided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3975 wined3d_strided.specular.data = D3DDrawPrimStrideData->specular.lpvData;
3976 wined3d_strided.specular.stride = D3DDrawPrimStrideData->specular.dwStride;
3979 for (i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); ++i)
3981 switch (GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3983 case 1: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32_FLOAT; break;
3984 case 2: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3985 case 3: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3986 case 4: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3987 default: ERR("Unexpected texture coordinate size %d\n",
3988 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3990 wined3d_strided.tex_coords[i].data = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3991 wined3d_strided.tex_coords[i].stride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3994 /* WineD3D doesn't need the FVF here */
3995 wined3d_mutex_lock();
3996 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3997 hr = wined3d_device_draw_primitive_strided(This->wined3d_device, VertexCount, &wined3d_strided);
3998 wined3d_mutex_unlock();
4000 return hr;
4003 static HRESULT WINAPI
4004 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4005 D3DPRIMITIVETYPE PrimitiveType,
4006 DWORD VertexType,
4007 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4008 DWORD VertexCount,
4009 DWORD Flags)
4011 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4014 static HRESULT WINAPI
4015 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4016 D3DPRIMITIVETYPE PrimitiveType,
4017 DWORD VertexType,
4018 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4019 DWORD VertexCount,
4020 DWORD Flags)
4022 HRESULT hr;
4023 WORD old_fpucw;
4025 old_fpucw = d3d_fpu_setup();
4026 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4027 set_fpu_control_word(old_fpucw);
4029 return hr;
4032 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
4033 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4034 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4036 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4038 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
4039 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4041 return IDirect3DDevice7_DrawPrimitiveStrided(&This->IDirect3DDevice7_iface,
4042 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4045 /*****************************************************************************
4046 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
4048 * Draws primitives specified by strided data locations based on indices
4050 * Version 3 and 7
4052 * Params:
4053 * PrimitiveType:
4055 * Returns:
4056 * D3D_OK, because it's a stub
4057 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
4058 * (DDERR_INVALIDPARAMS if Indices is NULL)
4059 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
4061 *****************************************************************************/
4062 static HRESULT
4063 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
4064 D3DPRIMITIVETYPE PrimitiveType,
4065 DWORD VertexType,
4066 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4067 DWORD VertexCount,
4068 WORD *Indices,
4069 DWORD IndexCount,
4070 DWORD Flags)
4072 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4073 struct wined3d_strided_data wined3d_strided;
4074 DWORD i;
4075 HRESULT hr;
4077 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4078 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4080 memset(&wined3d_strided, 0, sizeof(wined3d_strided));
4081 /* Get the strided data right. the wined3d structure is a bit bigger
4082 * Watch out: The contents of the strided data are determined by the fvf,
4083 * not by the members set in D3DDrawPrimStrideData. So it's valid
4084 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
4085 * not set in the fvf. */
4086 if (VertexType & D3DFVF_POSITION_MASK)
4088 wined3d_strided.position.format = WINED3DFMT_R32G32B32_FLOAT;
4089 wined3d_strided.position.data = D3DDrawPrimStrideData->position.lpvData;
4090 wined3d_strided.position.stride = D3DDrawPrimStrideData->position.dwStride;
4091 if (VertexType & D3DFVF_XYZRHW)
4093 wined3d_strided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
4094 wined3d_strided.position_transformed = TRUE;
4096 else
4098 wined3d_strided.position_transformed = FALSE;
4102 if (VertexType & D3DFVF_NORMAL)
4104 wined3d_strided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
4105 wined3d_strided.normal.data = D3DDrawPrimStrideData->normal.lpvData;
4106 wined3d_strided.normal.stride = D3DDrawPrimStrideData->normal.dwStride;
4109 if (VertexType & D3DFVF_DIFFUSE)
4111 wined3d_strided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
4112 wined3d_strided.diffuse.data = D3DDrawPrimStrideData->diffuse.lpvData;
4113 wined3d_strided.diffuse.stride = D3DDrawPrimStrideData->diffuse.dwStride;
4116 if (VertexType & D3DFVF_SPECULAR)
4118 wined3d_strided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
4119 wined3d_strided.specular.data = D3DDrawPrimStrideData->specular.lpvData;
4120 wined3d_strided.specular.stride = D3DDrawPrimStrideData->specular.dwStride;
4123 for (i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); ++i)
4125 switch (GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
4127 case 1: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32_FLOAT; break;
4128 case 2: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32_FLOAT; break;
4129 case 3: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
4130 case 4: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
4131 default: ERR("Unexpected texture coordinate size %d\n",
4132 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4134 wined3d_strided.tex_coords[i].data = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4135 wined3d_strided.tex_coords[i].stride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4138 /* WineD3D doesn't need the FVF here */
4139 wined3d_mutex_lock();
4140 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4141 hr = wined3d_device_draw_indexed_primitive_strided(This->wined3d_device,
4142 IndexCount, &wined3d_strided, VertexCount, Indices, WINED3DFMT_R16_UINT);
4143 wined3d_mutex_unlock();
4145 return hr;
4148 static HRESULT WINAPI
4149 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4150 D3DPRIMITIVETYPE PrimitiveType,
4151 DWORD VertexType,
4152 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4153 DWORD VertexCount,
4154 WORD *Indices,
4155 DWORD IndexCount,
4156 DWORD Flags)
4158 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4161 static HRESULT WINAPI
4162 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4163 D3DPRIMITIVETYPE PrimitiveType,
4164 DWORD VertexType,
4165 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4166 DWORD VertexCount,
4167 WORD *Indices,
4168 DWORD IndexCount,
4169 DWORD Flags)
4171 HRESULT hr;
4172 WORD old_fpucw;
4174 old_fpucw = d3d_fpu_setup();
4175 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4176 set_fpu_control_word(old_fpucw);
4178 return hr;
4181 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4182 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4183 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4184 DWORD IndexCount, DWORD Flags)
4186 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4188 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4189 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4191 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&This->IDirect3DDevice7_iface,
4192 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4195 /*****************************************************************************
4196 * IDirect3DDevice7::DrawPrimitiveVB
4198 * Draws primitives from a vertex buffer to the screen.
4200 * Version 3 and 7
4202 * Params:
4203 * PrimitiveType: Type of primitive to be rendered.
4204 * D3DVertexBuf: Source Vertex Buffer
4205 * StartVertex: Index of the first vertex from the buffer to be rendered
4206 * NumVertices: Number of vertices to be rendered
4207 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4209 * Return values
4210 * D3D_OK on success
4211 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4213 *****************************************************************************/
4214 static HRESULT
4215 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4216 D3DPRIMITIVETYPE PrimitiveType,
4217 IDirect3DVertexBuffer7 *D3DVertexBuf,
4218 DWORD StartVertex,
4219 DWORD NumVertices,
4220 DWORD Flags)
4222 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4223 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4224 HRESULT hr;
4225 DWORD stride;
4227 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4228 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4230 /* Sanity checks */
4231 if(!vb)
4233 ERR("(%p) No Vertex buffer specified\n", This);
4234 return DDERR_INVALIDPARAMS;
4236 stride = get_flexible_vertex_size(vb->fvf);
4238 wined3d_mutex_lock();
4239 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4240 if (FAILED(hr))
4242 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4243 wined3d_mutex_unlock();
4244 return hr;
4247 /* Set the vertex stream source */
4248 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4249 if(hr != D3D_OK)
4251 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4252 wined3d_mutex_unlock();
4253 return hr;
4256 /* Now draw the primitives */
4257 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4258 hr = wined3d_device_draw_primitive(This->wined3d_device, StartVertex, NumVertices);
4259 wined3d_mutex_unlock();
4261 return hr;
4264 static HRESULT WINAPI
4265 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4266 D3DPRIMITIVETYPE PrimitiveType,
4267 IDirect3DVertexBuffer7 *D3DVertexBuf,
4268 DWORD StartVertex,
4269 DWORD NumVertices,
4270 DWORD Flags)
4272 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4275 static HRESULT WINAPI
4276 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4277 D3DPRIMITIVETYPE PrimitiveType,
4278 IDirect3DVertexBuffer7 *D3DVertexBuf,
4279 DWORD StartVertex,
4280 DWORD NumVertices,
4281 DWORD Flags)
4283 HRESULT hr;
4284 WORD old_fpucw;
4286 old_fpucw = d3d_fpu_setup();
4287 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4288 set_fpu_control_word(old_fpucw);
4290 return hr;
4293 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4294 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex,
4295 DWORD NumVertices, DWORD Flags)
4297 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4298 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4300 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4301 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4303 return IDirect3DDevice7_DrawPrimitiveVB(&This->IDirect3DDevice7_iface,
4304 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4308 /*****************************************************************************
4309 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4311 * Draws primitives from a vertex buffer to the screen
4313 * Params:
4314 * PrimitiveType: Type of primitive to be rendered.
4315 * D3DVertexBuf: Source Vertex Buffer
4316 * StartVertex: Index of the first vertex from the buffer to be rendered
4317 * NumVertices: Number of vertices to be rendered
4318 * Indices: Array of DWORDs used to index into the Vertices
4319 * IndexCount: Number of indices in Indices
4320 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4322 * Return values
4324 *****************************************************************************/
4325 static HRESULT
4326 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4327 D3DPRIMITIVETYPE PrimitiveType,
4328 IDirect3DVertexBuffer7 *D3DVertexBuf,
4329 DWORD StartVertex,
4330 DWORD NumVertices,
4331 WORD *Indices,
4332 DWORD IndexCount,
4333 DWORD Flags)
4335 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4336 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4337 DWORD stride = get_flexible_vertex_size(vb->fvf);
4338 struct wined3d_resource *wined3d_resource;
4339 struct wined3d_resource_desc desc;
4340 WORD *LockedIndices;
4341 HRESULT hr;
4343 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4344 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4346 /* Steps:
4347 * 1) Upload the Indices to the index buffer
4348 * 2) Set the index source
4349 * 3) Set the Vertex Buffer as the Stream source
4350 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4353 wined3d_mutex_lock();
4355 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4356 if (FAILED(hr))
4358 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4359 wined3d_mutex_unlock();
4360 return hr;
4363 /* check that the buffer is large enough to hold the indices,
4364 * reallocate if necessary. */
4365 wined3d_resource = wined3d_buffer_get_resource(This->indexbuffer);
4366 wined3d_resource_get_desc(wined3d_resource, &desc);
4367 if (desc.size < IndexCount * sizeof(WORD))
4369 UINT size = max(desc.size * 2, IndexCount * sizeof(WORD));
4370 struct wined3d_buffer *buffer;
4372 TRACE("Growing index buffer to %u bytes\n", size);
4374 hr = wined3d_buffer_create_ib(This->wined3d_device, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4375 WINED3D_POOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
4376 if (FAILED(hr))
4378 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4379 wined3d_mutex_unlock();
4380 return hr;
4383 wined3d_buffer_decref(This->indexbuffer);
4384 This->indexbuffer = buffer;
4387 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4388 * method could be created which takes an user pointer containing the
4389 * indices or a SetData-Method for the index buffer, which overrides the
4390 * index buffer data with our pointer. */
4391 hr = wined3d_buffer_map(This->indexbuffer, 0, IndexCount * sizeof(WORD),
4392 (BYTE **)&LockedIndices, 0);
4393 if (FAILED(hr))
4395 ERR("Failed to map buffer, hr %#x.\n", hr);
4396 wined3d_mutex_unlock();
4397 return hr;
4399 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4400 wined3d_buffer_unmap(This->indexbuffer);
4402 /* Set the index stream */
4403 wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4404 hr = wined3d_device_set_index_buffer(This->wined3d_device, This->indexbuffer, WINED3DFMT_R16_UINT);
4406 /* Set the vertex stream source */
4407 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4408 if (FAILED(hr))
4410 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4411 wined3d_mutex_unlock();
4412 return hr;
4416 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4417 hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, 0, IndexCount);
4419 wined3d_mutex_unlock();
4421 return hr;
4424 static HRESULT WINAPI
4425 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4426 D3DPRIMITIVETYPE PrimitiveType,
4427 IDirect3DVertexBuffer7 *D3DVertexBuf,
4428 DWORD StartVertex,
4429 DWORD NumVertices,
4430 WORD *Indices,
4431 DWORD IndexCount,
4432 DWORD Flags)
4434 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4437 static HRESULT WINAPI
4438 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4439 D3DPRIMITIVETYPE PrimitiveType,
4440 IDirect3DVertexBuffer7 *D3DVertexBuf,
4441 DWORD StartVertex,
4442 DWORD NumVertices,
4443 WORD *Indices,
4444 DWORD IndexCount,
4445 DWORD Flags)
4447 HRESULT hr;
4448 WORD old_fpucw;
4450 old_fpucw = d3d_fpu_setup();
4451 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4452 set_fpu_control_word(old_fpucw);
4454 return hr;
4457 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4458 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4459 DWORD IndexCount, DWORD Flags)
4461 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4462 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4464 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4465 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4467 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&This->IDirect3DDevice7_iface,
4468 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount,
4469 Flags);
4472 /*****************************************************************************
4473 * IDirect3DDevice7::ComputeSphereVisibility
4475 * Calculates the visibility of spheres in the current viewport. The spheres
4476 * are passed in the Centers and Radii arrays, the results are passed back
4477 * in the ReturnValues array. Return values are either completely visible,
4478 * partially visible or completely invisible.
4479 * The return value consist of a combination of D3DCLIP_* flags, or it's
4480 * 0 if the sphere is completely visible(according to the SDK, not checked)
4482 * Version 3 and 7
4484 * Params:
4485 * Centers: Array containing the sphere centers
4486 * Radii: Array containing the sphere radii
4487 * NumSpheres: The number of centers and radii in the arrays
4488 * Flags: Some flags
4489 * ReturnValues: Array to write the results to
4491 * Returns:
4492 * D3D_OK
4493 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4494 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4495 * is singular)
4497 *****************************************************************************/
4499 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4501 float distance, norm;
4503 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4504 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4506 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4507 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4508 return 0;
4511 static HRESULT WINAPI
4512 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4513 D3DVECTOR *Centers,
4514 D3DVALUE *Radii,
4515 DWORD NumSpheres,
4516 DWORD Flags,
4517 DWORD *ReturnValues)
4519 D3DMATRIX m, temp;
4520 D3DVALUE origin_plane[6];
4521 D3DVECTOR vec[6];
4522 HRESULT hr;
4523 UINT i, j;
4525 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4526 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4528 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4529 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4530 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4531 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4532 multiply_matrix(&m, &temp, &m);
4534 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4535 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4536 multiply_matrix(&m, &temp, &m);
4538 /* Left plane */
4539 vec[0].u1.x = m._14 + m._11;
4540 vec[0].u2.y = m._24 + m._21;
4541 vec[0].u3.z = m._34 + m._31;
4542 origin_plane[0] = m._44 + m._41;
4544 /* Right plane */
4545 vec[1].u1.x = m._14 - m._11;
4546 vec[1].u2.y = m._24 - m._21;
4547 vec[1].u3.z = m._34 - m._31;
4548 origin_plane[1] = m._44 - m._41;
4550 /* Top plane */
4551 vec[2].u1.x = m._14 - m._12;
4552 vec[2].u2.y = m._24 - m._22;
4553 vec[2].u3.z = m._34 - m._32;
4554 origin_plane[2] = m._44 - m._42;
4556 /* Bottom plane */
4557 vec[3].u1.x = m._14 + m._12;
4558 vec[3].u2.y = m._24 + m._22;
4559 vec[3].u3.z = m._34 + m._32;
4560 origin_plane[3] = m._44 + m._42;
4562 /* Front plane */
4563 vec[4].u1.x = m._13;
4564 vec[4].u2.y = m._23;
4565 vec[4].u3.z = m._33;
4566 origin_plane[4] = m._43;
4568 /* Back plane*/
4569 vec[5].u1.x = m._14 - m._13;
4570 vec[5].u2.y = m._24 - m._23;
4571 vec[5].u3.z = m._34 - m._33;
4572 origin_plane[5] = m._44 - m._43;
4574 for(i=0; i<NumSpheres; i++)
4576 ReturnValues[i] = 0;
4577 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4580 return D3D_OK;
4583 static HRESULT WINAPI IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4584 D3DVECTOR *Centers, D3DVALUE *Radii, DWORD NumSpheres, DWORD Flags, DWORD *ReturnValues)
4586 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4588 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4589 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4591 return IDirect3DDevice7_ComputeSphereVisibility(&This->IDirect3DDevice7_iface,
4592 Centers, Radii, NumSpheres, Flags, ReturnValues);
4595 /*****************************************************************************
4596 * IDirect3DDevice7::GetTexture
4598 * Returns the texture interface handle assigned to a texture stage.
4599 * The returned texture is AddRefed. This is taken from old ddraw,
4600 * not checked in Windows.
4602 * Version 3 and 7
4604 * Params:
4605 * Stage: Texture stage to read the texture from
4606 * Texture: Address to store the interface pointer at
4608 * Returns:
4609 * D3D_OK on success
4610 * DDERR_INVALIDPARAMS if Texture is NULL
4611 * For details, see IWineD3DDevice::GetTexture
4613 *****************************************************************************/
4614 static HRESULT
4615 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4616 DWORD Stage,
4617 IDirectDrawSurface7 **Texture)
4619 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4620 struct wined3d_texture *wined3d_texture;
4621 HRESULT hr;
4623 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4625 if(!Texture)
4627 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4628 return DDERR_INVALIDPARAMS;
4631 wined3d_mutex_lock();
4632 hr = wined3d_device_get_texture(This->wined3d_device, Stage, &wined3d_texture);
4633 if (FAILED(hr) || !wined3d_texture)
4635 *Texture = NULL;
4636 wined3d_mutex_unlock();
4637 return hr;
4640 *Texture = wined3d_texture_get_parent(wined3d_texture);
4641 IDirectDrawSurface7_AddRef(*Texture);
4642 wined3d_texture_decref(wined3d_texture);
4643 wined3d_mutex_unlock();
4645 return hr;
4648 static HRESULT WINAPI
4649 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4650 DWORD Stage,
4651 IDirectDrawSurface7 **Texture)
4653 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4656 static HRESULT WINAPI
4657 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4658 DWORD Stage,
4659 IDirectDrawSurface7 **Texture)
4661 HRESULT hr;
4662 WORD old_fpucw;
4664 old_fpucw = d3d_fpu_setup();
4665 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4666 set_fpu_control_word(old_fpucw);
4668 return hr;
4671 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface, DWORD Stage,
4672 IDirect3DTexture2 **Texture2)
4674 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4675 HRESULT ret;
4676 IDirectDrawSurface7 *ret_val;
4677 IDirectDrawSurfaceImpl *ret_val_impl;
4679 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4681 ret = IDirect3DDevice7_GetTexture(&This->IDirect3DDevice7_iface, Stage, &ret_val);
4683 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4684 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4686 TRACE("Returning texture %p.\n", *Texture2);
4688 return ret;
4691 /*****************************************************************************
4692 * IDirect3DDevice7::SetTexture
4694 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4696 * Version 3 and 7
4698 * Params:
4699 * Stage: The stage to assign the texture to
4700 * Texture: Interface pointer to the texture surface
4702 * Returns
4703 * D3D_OK on success
4704 * For details, see IWineD3DDevice::SetTexture
4706 *****************************************************************************/
4707 static HRESULT
4708 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4709 DWORD Stage,
4710 IDirectDrawSurface7 *Texture)
4712 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4713 IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
4714 HRESULT hr;
4716 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4718 /* Texture may be NULL here */
4719 wined3d_mutex_lock();
4720 hr = wined3d_device_set_texture(This->wined3d_device,
4721 Stage, surf ? surf->wined3d_texture : NULL);
4722 wined3d_mutex_unlock();
4724 return hr;
4727 static HRESULT WINAPI
4728 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4729 DWORD Stage,
4730 IDirectDrawSurface7 *Texture)
4732 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4735 static HRESULT WINAPI
4736 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4737 DWORD Stage,
4738 IDirectDrawSurface7 *Texture)
4740 HRESULT hr;
4741 WORD old_fpucw;
4743 old_fpucw = d3d_fpu_setup();
4744 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4745 set_fpu_control_word(old_fpucw);
4747 return hr;
4750 static HRESULT WINAPI
4751 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4752 DWORD Stage,
4753 IDirect3DTexture2 *Texture2)
4755 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4756 IDirectDrawSurfaceImpl *tex = unsafe_impl_from_IDirect3DTexture2(Texture2);
4757 DWORD texmapblend;
4758 HRESULT hr;
4760 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4762 wined3d_mutex_lock();
4764 if (This->legacyTextureBlending)
4765 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4767 hr = IDirect3DDevice7_SetTexture(&This->IDirect3DDevice7_iface, Stage, &tex->IDirectDrawSurface7_iface);
4769 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4771 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4772 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4773 struct wined3d_texture *tex = NULL;
4774 BOOL tex_alpha = FALSE;
4775 DDPIXELFORMAT ddfmt;
4776 HRESULT result;
4778 result = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
4779 if (result == WINED3D_OK && tex)
4781 struct wined3d_resource *sub_resource;
4783 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4785 struct wined3d_resource_desc desc;
4787 wined3d_resource_get_desc(sub_resource, &desc);
4788 ddfmt.dwSize = sizeof(ddfmt);
4789 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4790 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4793 wined3d_texture_decref(tex);
4796 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4797 if (tex_alpha)
4798 wined3d_device_set_texture_stage_state(This->wined3d_device,
4799 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
4800 else
4801 wined3d_device_set_texture_stage_state(This->wined3d_device,
4802 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
4805 wined3d_mutex_unlock();
4807 return hr;
4810 static const struct tss_lookup
4812 BOOL sampler_state;
4813 enum wined3d_texture_stage_state state;
4815 tss_lookup[] =
4817 {FALSE, WINED3D_TSS_INVALID}, /* 0, unused */
4818 {FALSE, WINED3D_TSS_COLOR_OP}, /* 1, D3DTSS_COLOROP */
4819 {FALSE, WINED3D_TSS_COLOR_ARG1}, /* 2, D3DTSS_COLORARG1 */
4820 {FALSE, WINED3D_TSS_COLOR_ARG2}, /* 3, D3DTSS_COLORARG2 */
4821 {FALSE, WINED3D_TSS_ALPHA_OP}, /* 4, D3DTSS_ALPHAOP */
4822 {FALSE, WINED3D_TSS_ALPHA_ARG1}, /* 5, D3DTSS_ALPHAARG1 */
4823 {FALSE, WINED3D_TSS_ALPHA_ARG2}, /* 6, D3DTSS_ALPHAARG2 */
4824 {FALSE, WINED3D_TSS_BUMPENV_MAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4825 {FALSE, WINED3D_TSS_BUMPENV_MAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4826 {FALSE, WINED3D_TSS_BUMPENV_MAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4827 {FALSE, WINED3D_TSS_BUMPENV_MAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4828 {FALSE, WINED3D_TSS_TEXCOORD_INDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4829 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 12, D3DTSS_ADDRESS */
4830 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 13, D3DTSS_ADDRESSU */
4831 {TRUE, WINED3D_SAMP_ADDRESS_V}, /* 14, D3DTSS_ADDRESSV */
4832 {TRUE, WINED3D_SAMP_BORDER_COLOR}, /* 15, D3DTSS_BORDERCOLOR */
4833 {TRUE, WINED3D_SAMP_MAG_FILTER}, /* 16, D3DTSS_MAGFILTER */
4834 {TRUE, WINED3D_SAMP_MIN_FILTER}, /* 17, D3DTSS_MINFILTER */
4835 {TRUE, WINED3D_SAMP_MIP_FILTER}, /* 18, D3DTSS_MIPFILTER */
4836 {TRUE, WINED3D_SAMP_MIPMAP_LOD_BIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4837 {TRUE, WINED3D_SAMP_MAX_MIP_LEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4838 {TRUE, WINED3D_SAMP_MAX_ANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4839 {FALSE, WINED3D_TSS_BUMPENV_LSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4840 {FALSE, WINED3D_TSS_BUMPENV_LOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4841 {FALSE, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4844 /*****************************************************************************
4845 * IDirect3DDevice7::GetTextureStageState
4847 * Retrieves a state from a texture stage.
4849 * Version 3 and 7
4851 * Params:
4852 * Stage: The stage to retrieve the state from
4853 * TexStageStateType: The state type to retrieve
4854 * State: Address to store the state's value at
4856 * Returns:
4857 * D3D_OK on success
4858 * DDERR_INVALIDPARAMS if State is NULL
4859 * For details, see IWineD3DDevice::GetTextureStageState
4861 *****************************************************************************/
4862 static HRESULT
4863 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4864 DWORD Stage,
4865 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4866 DWORD *State)
4868 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4869 HRESULT hr;
4870 const struct tss_lookup *l;
4872 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4873 iface, Stage, TexStageStateType, State);
4875 if(!State)
4876 return DDERR_INVALIDPARAMS;
4878 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4880 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4881 return DD_OK;
4884 l = &tss_lookup[TexStageStateType];
4886 wined3d_mutex_lock();
4888 if (l->sampler_state)
4890 hr = wined3d_device_get_sampler_state(This->wined3d_device, Stage, l->state, State);
4892 switch(TexStageStateType)
4894 /* Mipfilter is a sampler state with different values */
4895 case D3DTSS_MIPFILTER:
4897 switch(*State)
4899 case WINED3D_TEXF_NONE:
4900 *State = D3DTFP_NONE;
4901 break;
4902 case WINED3D_TEXF_POINT:
4903 *State = D3DTFP_POINT;
4904 break;
4905 case WINED3D_TEXF_LINEAR:
4906 *State = D3DTFP_LINEAR;
4907 break;
4908 default:
4909 ERR("Unexpected mipfilter value %#x\n", *State);
4910 *State = D3DTFP_NONE;
4911 break;
4913 break;
4916 /* Magfilter has slightly different values */
4917 case D3DTSS_MAGFILTER:
4919 switch(*State)
4921 case WINED3D_TEXF_POINT:
4922 *State = D3DTFG_POINT;
4923 break;
4924 case WINED3D_TEXF_LINEAR:
4925 *State = D3DTFG_LINEAR;
4926 break;
4927 case WINED3D_TEXF_ANISOTROPIC:
4928 *State = D3DTFG_ANISOTROPIC;
4929 break;
4930 case WINED3D_TEXF_FLAT_CUBIC:
4931 *State = D3DTFG_FLATCUBIC;
4932 break;
4933 case WINED3D_TEXF_GAUSSIAN_CUBIC:
4934 *State = D3DTFG_GAUSSIANCUBIC;
4935 break;
4936 default:
4937 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4938 *State = D3DTFG_POINT;
4939 break;
4941 break;
4944 default:
4945 break;
4948 else
4950 hr = wined3d_device_get_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4953 wined3d_mutex_unlock();
4955 return hr;
4958 static HRESULT WINAPI
4959 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4960 DWORD Stage,
4961 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4962 DWORD *State)
4964 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4967 static HRESULT WINAPI
4968 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4969 DWORD Stage,
4970 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4971 DWORD *State)
4973 HRESULT hr;
4974 WORD old_fpucw;
4976 old_fpucw = d3d_fpu_setup();
4977 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4978 set_fpu_control_word(old_fpucw);
4980 return hr;
4983 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4984 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD *State)
4986 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4988 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4989 iface, Stage, TexStageStateType, State);
4991 return IDirect3DDevice7_GetTextureStageState(&This->IDirect3DDevice7_iface,
4992 Stage, TexStageStateType, State);
4995 /*****************************************************************************
4996 * IDirect3DDevice7::SetTextureStageState
4998 * Sets a texture stage state. Some stage types need to be handled specially,
4999 * because they do not exist in WineD3D and were moved to another place
5001 * Version 3 and 7
5003 * Params:
5004 * Stage: The stage to modify
5005 * TexStageStateType: The state to change
5006 * State: The new value for the state
5008 * Returns:
5009 * D3D_OK on success
5010 * For details, see IWineD3DDevice::SetTextureStageState
5012 *****************************************************************************/
5013 static HRESULT
5014 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
5015 DWORD Stage,
5016 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5017 DWORD State)
5019 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5020 const struct tss_lookup *l;
5021 HRESULT hr;
5023 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5024 iface, Stage, TexStageStateType, State);
5026 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
5028 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
5029 return DD_OK;
5032 l = &tss_lookup[TexStageStateType];
5034 wined3d_mutex_lock();
5036 if (l->sampler_state)
5038 switch(TexStageStateType)
5040 /* Mipfilter is a sampler state with different values */
5041 case D3DTSS_MIPFILTER:
5043 switch(State)
5045 case D3DTFP_NONE:
5046 State = WINED3D_TEXF_NONE;
5047 break;
5048 case D3DTFP_POINT:
5049 State = WINED3D_TEXF_POINT;
5050 break;
5051 case 0: /* Unchecked */
5052 case D3DTFP_LINEAR:
5053 State = WINED3D_TEXF_LINEAR;
5054 break;
5055 default:
5056 ERR("Unexpected mipfilter value %d\n", State);
5057 State = WINED3D_TEXF_NONE;
5058 break;
5060 break;
5063 /* Magfilter has slightly different values */
5064 case D3DTSS_MAGFILTER:
5066 switch(State)
5068 case D3DTFG_POINT:
5069 State = WINED3D_TEXF_POINT;
5070 break;
5071 case D3DTFG_LINEAR:
5072 State = WINED3D_TEXF_LINEAR;
5073 break;
5074 case D3DTFG_FLATCUBIC:
5075 State = WINED3D_TEXF_FLAT_CUBIC;
5076 break;
5077 case D3DTFG_GAUSSIANCUBIC:
5078 State = WINED3D_TEXF_GAUSSIAN_CUBIC;
5079 break;
5080 case D3DTFG_ANISOTROPIC:
5081 State = WINED3D_TEXF_ANISOTROPIC;
5082 break;
5083 default:
5084 ERR("Unexpected d3d7 mag filter type %d\n", State);
5085 State = WINED3D_TEXF_POINT;
5086 break;
5088 break;
5091 case D3DTSS_ADDRESS:
5092 wined3d_device_set_sampler_state(This->wined3d_device, Stage, WINED3D_SAMP_ADDRESS_V, State);
5093 break;
5095 default:
5096 break;
5099 hr = wined3d_device_set_sampler_state(This->wined3d_device, Stage, l->state, State);
5101 else
5103 hr = wined3d_device_set_texture_stage_state(This->wined3d_device, Stage, l->state, State);
5106 wined3d_mutex_unlock();
5108 return hr;
5111 static HRESULT WINAPI
5112 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5113 DWORD Stage,
5114 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5115 DWORD State)
5117 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5120 static HRESULT WINAPI
5121 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5122 DWORD Stage,
5123 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5124 DWORD State)
5126 HRESULT hr;
5127 WORD old_fpucw;
5129 old_fpucw = d3d_fpu_setup();
5130 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5131 set_fpu_control_word(old_fpucw);
5133 return hr;
5136 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
5137 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD State)
5139 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
5141 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5142 iface, Stage, TexStageStateType, State);
5144 return IDirect3DDevice7_SetTextureStageState(&This->IDirect3DDevice7_iface,
5145 Stage, TexStageStateType, State);
5148 /*****************************************************************************
5149 * IDirect3DDevice7::ValidateDevice
5151 * SDK: "Reports the device's ability to render the currently set
5152 * texture-blending operations in a single pass". Whatever that means
5153 * exactly...
5155 * Version 3 and 7
5157 * Params:
5158 * NumPasses: Address to write the number of necessary passes for the
5159 * desired effect to.
5161 * Returns:
5162 * D3D_OK on success
5163 * See IWineD3DDevice::ValidateDevice for more details
5165 *****************************************************************************/
5166 static HRESULT
5167 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
5168 DWORD *NumPasses)
5170 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5171 HRESULT hr;
5173 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
5175 wined3d_mutex_lock();
5176 hr = wined3d_device_validate_device(This->wined3d_device, NumPasses);
5177 wined3d_mutex_unlock();
5179 return hr;
5182 static HRESULT WINAPI
5183 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
5184 DWORD *NumPasses)
5186 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5189 static HRESULT WINAPI
5190 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
5191 DWORD *NumPasses)
5193 HRESULT hr;
5194 WORD old_fpucw;
5196 old_fpucw = d3d_fpu_setup();
5197 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5198 set_fpu_control_word(old_fpucw);
5200 return hr;
5203 static HRESULT WINAPI IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *Passes)
5205 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
5207 TRACE("iface %p, pass_count %p.\n", iface, Passes);
5209 return IDirect3DDevice7_ValidateDevice(&This->IDirect3DDevice7_iface, Passes);
5212 /*****************************************************************************
5213 * IDirect3DDevice7::Clear
5215 * Fills the render target, the z buffer and the stencil buffer with a
5216 * clear color / value
5218 * Version 7 only
5220 * Params:
5221 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5222 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5223 * Flags: Some flags, as usual
5224 * Color: Clear color for the render target
5225 * Z: Clear value for the Z buffer
5226 * Stencil: Clear value to store in each stencil buffer entry
5228 * Returns:
5229 * D3D_OK on success
5230 * For details, see IWineD3DDevice::Clear
5232 *****************************************************************************/
5233 static HRESULT IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface, DWORD count,
5234 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5236 const struct wined3d_color c =
5238 ((color >> 16) & 0xff) / 255.0f,
5239 ((color >> 8) & 0xff) / 255.0f,
5240 (color & 0xff) / 255.0f,
5241 ((color >> 24) & 0xff) / 255.0f,
5243 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5244 HRESULT hr;
5246 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5247 iface, count, rects, flags, color, z, stencil);
5249 wined3d_mutex_lock();
5250 hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
5251 wined3d_mutex_unlock();
5253 return hr;
5256 static HRESULT WINAPI
5257 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5258 DWORD Count,
5259 D3DRECT *Rects,
5260 DWORD Flags,
5261 D3DCOLOR Color,
5262 D3DVALUE Z,
5263 DWORD Stencil)
5265 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5268 static HRESULT WINAPI
5269 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5270 DWORD Count,
5271 D3DRECT *Rects,
5272 DWORD Flags,
5273 D3DCOLOR Color,
5274 D3DVALUE Z,
5275 DWORD Stencil)
5277 HRESULT hr;
5278 WORD old_fpucw;
5280 old_fpucw = d3d_fpu_setup();
5281 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5282 set_fpu_control_word(old_fpucw);
5284 return hr;
5287 /*****************************************************************************
5288 * IDirect3DDevice7::SetViewport
5290 * Sets the current viewport.
5292 * Version 7 only, but IDirect3DViewport uses this call for older
5293 * versions
5295 * Params:
5296 * Data: The new viewport to set
5298 * Returns:
5299 * D3D_OK on success
5300 * DDERR_INVALIDPARAMS if Data is NULL
5301 * For more details, see IWineDDDevice::SetViewport
5303 *****************************************************************************/
5304 static HRESULT
5305 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5306 D3DVIEWPORT7 *Data)
5308 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5309 HRESULT hr;
5311 TRACE("iface %p, viewport %p.\n", iface, Data);
5313 if(!Data)
5314 return DDERR_INVALIDPARAMS;
5316 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5317 wined3d_mutex_lock();
5318 hr = wined3d_device_set_viewport(This->wined3d_device, (struct wined3d_viewport *)Data);
5319 wined3d_mutex_unlock();
5321 return hr;
5324 static HRESULT WINAPI
5325 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5326 D3DVIEWPORT7 *Data)
5328 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5331 static HRESULT WINAPI
5332 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5333 D3DVIEWPORT7 *Data)
5335 HRESULT hr;
5336 WORD old_fpucw;
5338 old_fpucw = d3d_fpu_setup();
5339 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5340 set_fpu_control_word(old_fpucw);
5342 return hr;
5345 /*****************************************************************************
5346 * IDirect3DDevice::GetViewport
5348 * Returns the current viewport
5350 * Version 7
5352 * Params:
5353 * Data: D3D7Viewport structure to write the viewport information to
5355 * Returns:
5356 * D3D_OK on success
5357 * DDERR_INVALIDPARAMS if Data is NULL
5358 * For more details, see IWineD3DDevice::GetViewport
5360 *****************************************************************************/
5361 static HRESULT
5362 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5363 D3DVIEWPORT7 *Data)
5365 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5366 HRESULT hr;
5368 TRACE("iface %p, viewport %p.\n", iface, Data);
5370 if(!Data)
5371 return DDERR_INVALIDPARAMS;
5373 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5374 wined3d_mutex_lock();
5375 hr = wined3d_device_get_viewport(This->wined3d_device, (struct wined3d_viewport *)Data);
5376 wined3d_mutex_unlock();
5378 return hr_ddraw_from_wined3d(hr);
5381 static HRESULT WINAPI
5382 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5383 D3DVIEWPORT7 *Data)
5385 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5388 static HRESULT WINAPI
5389 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5390 D3DVIEWPORT7 *Data)
5392 HRESULT hr;
5393 WORD old_fpucw;
5395 old_fpucw = d3d_fpu_setup();
5396 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5397 set_fpu_control_word(old_fpucw);
5399 return hr;
5402 /*****************************************************************************
5403 * IDirect3DDevice7::SetMaterial
5405 * Sets the Material
5407 * Version 7
5409 * Params:
5410 * Mat: The material to set
5412 * Returns:
5413 * D3D_OK on success
5414 * DDERR_INVALIDPARAMS if Mat is NULL.
5415 * For more details, see IWineD3DDevice::SetMaterial
5417 *****************************************************************************/
5418 static HRESULT
5419 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5420 D3DMATERIAL7 *Mat)
5422 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5423 HRESULT hr;
5425 TRACE("iface %p, material %p.\n", iface, Mat);
5427 if (!Mat) return DDERR_INVALIDPARAMS;
5429 wined3d_mutex_lock();
5430 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5431 hr = wined3d_device_set_material(This->wined3d_device, (struct wined3d_material *)Mat);
5432 wined3d_mutex_unlock();
5434 return hr_ddraw_from_wined3d(hr);
5437 static HRESULT WINAPI
5438 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5439 D3DMATERIAL7 *Mat)
5441 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5444 static HRESULT WINAPI
5445 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5446 D3DMATERIAL7 *Mat)
5448 HRESULT hr;
5449 WORD old_fpucw;
5451 old_fpucw = d3d_fpu_setup();
5452 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5453 set_fpu_control_word(old_fpucw);
5455 return hr;
5458 /*****************************************************************************
5459 * IDirect3DDevice7::GetMaterial
5461 * Returns the current material
5463 * Version 7
5465 * Params:
5466 * Mat: D3DMATERIAL7 structure to write the material parameters to
5468 * Returns:
5469 * D3D_OK on success
5470 * DDERR_INVALIDPARAMS if Mat is NULL
5471 * For more details, see IWineD3DDevice::GetMaterial
5473 *****************************************************************************/
5474 static HRESULT
5475 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5476 D3DMATERIAL7 *Mat)
5478 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5479 HRESULT hr;
5481 TRACE("iface %p, material %p.\n", iface, Mat);
5483 wined3d_mutex_lock();
5484 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5485 hr = wined3d_device_get_material(This->wined3d_device, (struct wined3d_material *)Mat);
5486 wined3d_mutex_unlock();
5488 return hr_ddraw_from_wined3d(hr);
5491 static HRESULT WINAPI
5492 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5493 D3DMATERIAL7 *Mat)
5495 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5498 static HRESULT WINAPI
5499 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5500 D3DMATERIAL7 *Mat)
5502 HRESULT hr;
5503 WORD old_fpucw;
5505 old_fpucw = d3d_fpu_setup();
5506 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5507 set_fpu_control_word(old_fpucw);
5509 return hr;
5512 /*****************************************************************************
5513 * IDirect3DDevice7::SetLight
5515 * Assigns a light to a light index, but doesn't activate it yet.
5517 * Version 7, IDirect3DLight uses this method for older versions
5519 * Params:
5520 * LightIndex: The index of the new light
5521 * Light: A D3DLIGHT7 structure describing the light
5523 * Returns:
5524 * D3D_OK on success
5525 * For more details, see IWineD3DDevice::SetLight
5527 *****************************************************************************/
5528 static HRESULT
5529 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5530 DWORD LightIndex,
5531 D3DLIGHT7 *Light)
5533 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5534 HRESULT hr;
5536 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5538 wined3d_mutex_lock();
5539 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5540 hr = wined3d_device_set_light(This->wined3d_device, LightIndex, (struct wined3d_light *)Light);
5541 wined3d_mutex_unlock();
5543 return hr_ddraw_from_wined3d(hr);
5546 static HRESULT WINAPI
5547 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5548 DWORD LightIndex,
5549 D3DLIGHT7 *Light)
5551 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5554 static HRESULT WINAPI
5555 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5556 DWORD LightIndex,
5557 D3DLIGHT7 *Light)
5559 HRESULT hr;
5560 WORD old_fpucw;
5562 old_fpucw = d3d_fpu_setup();
5563 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5564 set_fpu_control_word(old_fpucw);
5566 return hr;
5569 /*****************************************************************************
5570 * IDirect3DDevice7::GetLight
5572 * Returns the light assigned to a light index
5574 * Params:
5575 * Light: Structure to write the light information to
5577 * Returns:
5578 * D3D_OK on success
5579 * DDERR_INVALIDPARAMS if Light is NULL
5580 * For details, see IWineD3DDevice::GetLight
5582 *****************************************************************************/
5583 static HRESULT
5584 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5585 DWORD LightIndex,
5586 D3DLIGHT7 *Light)
5588 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5589 HRESULT rc;
5591 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5593 wined3d_mutex_lock();
5594 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5595 rc = wined3d_device_get_light(This->wined3d_device, LightIndex, (struct wined3d_light *)Light);
5596 wined3d_mutex_unlock();
5598 /* Translate the result. WineD3D returns other values than D3D7 */
5599 return hr_ddraw_from_wined3d(rc);
5602 static HRESULT WINAPI
5603 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5604 DWORD LightIndex,
5605 D3DLIGHT7 *Light)
5607 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5610 static HRESULT WINAPI
5611 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5612 DWORD LightIndex,
5613 D3DLIGHT7 *Light)
5615 HRESULT hr;
5616 WORD old_fpucw;
5618 old_fpucw = d3d_fpu_setup();
5619 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5620 set_fpu_control_word(old_fpucw);
5622 return hr;
5625 /*****************************************************************************
5626 * IDirect3DDevice7::BeginStateBlock
5628 * Begins recording to a stateblock
5630 * Version 7
5632 * Returns:
5633 * D3D_OK on success
5634 * For details see IWineD3DDevice::BeginStateBlock
5636 *****************************************************************************/
5637 static HRESULT
5638 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5640 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5641 HRESULT hr;
5643 TRACE("iface %p.\n", iface);
5645 wined3d_mutex_lock();
5646 hr = wined3d_device_begin_stateblock(This->wined3d_device);
5647 wined3d_mutex_unlock();
5649 return hr_ddraw_from_wined3d(hr);
5652 static HRESULT WINAPI
5653 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5655 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5658 static HRESULT WINAPI
5659 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5661 HRESULT hr;
5662 WORD old_fpucw;
5664 old_fpucw = d3d_fpu_setup();
5665 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5666 set_fpu_control_word(old_fpucw);
5668 return hr;
5671 /*****************************************************************************
5672 * IDirect3DDevice7::EndStateBlock
5674 * Stops recording to a state block and returns the created stateblock
5675 * handle.
5677 * Version 7
5679 * Params:
5680 * BlockHandle: Address to store the stateblock's handle to
5682 * Returns:
5683 * D3D_OK on success
5684 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5685 * See IWineD3DDevice::EndStateBlock for more details
5687 *****************************************************************************/
5688 static HRESULT
5689 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5690 DWORD *BlockHandle)
5692 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5693 struct wined3d_stateblock *wined3d_sb;
5694 HRESULT hr;
5695 DWORD h;
5697 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5699 if(!BlockHandle)
5701 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5702 return DDERR_INVALIDPARAMS;
5705 wined3d_mutex_lock();
5707 hr = wined3d_device_end_stateblock(This->wined3d_device, &wined3d_sb);
5708 if (FAILED(hr))
5710 WARN("Failed to end stateblock, hr %#x.\n", hr);
5711 wined3d_mutex_unlock();
5712 *BlockHandle = 0;
5713 return hr_ddraw_from_wined3d(hr);
5716 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5717 if (h == DDRAW_INVALID_HANDLE)
5719 ERR("Failed to allocate a stateblock handle.\n");
5720 wined3d_stateblock_decref(wined3d_sb);
5721 wined3d_mutex_unlock();
5722 *BlockHandle = 0;
5723 return DDERR_OUTOFMEMORY;
5726 wined3d_mutex_unlock();
5727 *BlockHandle = h + 1;
5729 return hr_ddraw_from_wined3d(hr);
5732 static HRESULT WINAPI
5733 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5734 DWORD *BlockHandle)
5736 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5739 static HRESULT WINAPI
5740 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5741 DWORD *BlockHandle)
5743 HRESULT hr;
5744 WORD old_fpucw;
5746 old_fpucw = d3d_fpu_setup();
5747 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5748 set_fpu_control_word(old_fpucw);
5750 return hr;
5753 /*****************************************************************************
5754 * IDirect3DDevice7::PreLoad
5756 * Allows the app to signal that a texture will be used soon, to allow
5757 * the Direct3DDevice to load it to the video card in the meantime.
5759 * Version 7
5761 * Params:
5762 * Texture: The texture to preload
5764 * Returns:
5765 * D3D_OK on success
5766 * DDERR_INVALIDPARAMS if Texture is NULL
5767 * See IWineD3DSurface::PreLoad for details
5769 *****************************************************************************/
5770 static HRESULT
5771 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5772 IDirectDrawSurface7 *Texture)
5774 IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
5776 TRACE("iface %p, texture %p.\n", iface, Texture);
5778 if(!Texture)
5779 return DDERR_INVALIDPARAMS;
5781 wined3d_mutex_lock();
5782 wined3d_surface_preload(surf->wined3d_surface);
5783 wined3d_mutex_unlock();
5785 return D3D_OK;
5788 static HRESULT WINAPI
5789 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5790 IDirectDrawSurface7 *Texture)
5792 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5795 static HRESULT WINAPI
5796 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5797 IDirectDrawSurface7 *Texture)
5799 HRESULT hr;
5800 WORD old_fpucw;
5802 old_fpucw = d3d_fpu_setup();
5803 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5804 set_fpu_control_word(old_fpucw);
5806 return hr;
5809 /*****************************************************************************
5810 * IDirect3DDevice7::ApplyStateBlock
5812 * Activates the state stored in a state block handle.
5814 * Params:
5815 * BlockHandle: The stateblock handle to activate
5817 * Returns:
5818 * D3D_OK on success
5819 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5821 *****************************************************************************/
5822 static HRESULT
5823 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5824 DWORD BlockHandle)
5826 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5827 struct wined3d_stateblock *wined3d_sb;
5828 HRESULT hr;
5830 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5832 wined3d_mutex_lock();
5833 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5834 if (!wined3d_sb)
5836 WARN("Invalid stateblock handle.\n");
5837 wined3d_mutex_unlock();
5838 return D3DERR_INVALIDSTATEBLOCK;
5841 hr = wined3d_stateblock_apply(wined3d_sb);
5842 wined3d_mutex_unlock();
5844 return hr_ddraw_from_wined3d(hr);
5847 static HRESULT WINAPI
5848 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5849 DWORD BlockHandle)
5851 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5854 static HRESULT WINAPI
5855 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5856 DWORD BlockHandle)
5858 HRESULT hr;
5859 WORD old_fpucw;
5861 old_fpucw = d3d_fpu_setup();
5862 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5863 set_fpu_control_word(old_fpucw);
5865 return hr;
5868 /*****************************************************************************
5869 * IDirect3DDevice7::CaptureStateBlock
5871 * Updates a stateblock's values to the values currently set for the device
5873 * Version 7
5875 * Params:
5876 * BlockHandle: Stateblock to update
5878 * Returns:
5879 * D3D_OK on success
5880 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5881 * See IWineD3DDevice::CaptureStateBlock for more details
5883 *****************************************************************************/
5884 static HRESULT
5885 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5886 DWORD BlockHandle)
5888 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5889 struct wined3d_stateblock *wined3d_sb;
5890 HRESULT hr;
5892 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5894 wined3d_mutex_lock();
5895 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5896 if (!wined3d_sb)
5898 WARN("Invalid stateblock handle.\n");
5899 wined3d_mutex_unlock();
5900 return D3DERR_INVALIDSTATEBLOCK;
5903 hr = wined3d_stateblock_capture(wined3d_sb);
5904 wined3d_mutex_unlock();
5906 return hr_ddraw_from_wined3d(hr);
5909 static HRESULT WINAPI
5910 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5911 DWORD BlockHandle)
5913 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5916 static HRESULT WINAPI
5917 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5918 DWORD BlockHandle)
5920 HRESULT hr;
5921 WORD old_fpucw;
5923 old_fpucw = d3d_fpu_setup();
5924 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5925 set_fpu_control_word(old_fpucw);
5927 return hr;
5930 /*****************************************************************************
5931 * IDirect3DDevice7::DeleteStateBlock
5933 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5935 * Version 7
5937 * Params:
5938 * BlockHandle: Stateblock handle to delete
5940 * Returns:
5941 * D3D_OK on success
5942 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5944 *****************************************************************************/
5945 static HRESULT
5946 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5947 DWORD BlockHandle)
5949 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5950 struct wined3d_stateblock *wined3d_sb;
5951 ULONG ref;
5953 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5955 wined3d_mutex_lock();
5957 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5958 if (!wined3d_sb)
5960 WARN("Invalid stateblock handle.\n");
5961 wined3d_mutex_unlock();
5962 return D3DERR_INVALIDSTATEBLOCK;
5965 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5967 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5970 wined3d_mutex_unlock();
5972 return D3D_OK;
5975 static HRESULT WINAPI
5976 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5977 DWORD BlockHandle)
5979 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5982 static HRESULT WINAPI
5983 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5984 DWORD BlockHandle)
5986 HRESULT hr;
5987 WORD old_fpucw;
5989 old_fpucw = d3d_fpu_setup();
5990 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5991 set_fpu_control_word(old_fpucw);
5993 return hr;
5996 /*****************************************************************************
5997 * IDirect3DDevice7::CreateStateBlock
5999 * Creates a new state block handle.
6001 * Version 7
6003 * Params:
6004 * Type: The state block type
6005 * BlockHandle: Address to write the created handle to
6007 * Returns:
6008 * D3D_OK on success
6009 * DDERR_INVALIDPARAMS if BlockHandle is NULL
6011 *****************************************************************************/
6012 static HRESULT
6013 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
6014 D3DSTATEBLOCKTYPE Type,
6015 DWORD *BlockHandle)
6017 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6018 struct wined3d_stateblock *wined3d_sb;
6019 HRESULT hr;
6020 DWORD h;
6022 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
6024 if(!BlockHandle)
6026 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
6027 return DDERR_INVALIDPARAMS;
6029 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
6030 Type != D3DSBT_VERTEXSTATE ) {
6031 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
6032 return DDERR_INVALIDPARAMS;
6035 wined3d_mutex_lock();
6037 /* The D3DSTATEBLOCKTYPE enum is fine here. */
6038 hr = wined3d_stateblock_create(This->wined3d_device, Type, &wined3d_sb);
6039 if (FAILED(hr))
6041 WARN("Failed to create stateblock, hr %#x.\n", hr);
6042 wined3d_mutex_unlock();
6043 return hr_ddraw_from_wined3d(hr);
6046 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
6047 if (h == DDRAW_INVALID_HANDLE)
6049 ERR("Failed to allocate stateblock handle.\n");
6050 wined3d_stateblock_decref(wined3d_sb);
6051 wined3d_mutex_unlock();
6052 return DDERR_OUTOFMEMORY;
6055 *BlockHandle = h + 1;
6056 wined3d_mutex_unlock();
6058 return hr_ddraw_from_wined3d(hr);
6061 static HRESULT WINAPI
6062 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
6063 D3DSTATEBLOCKTYPE Type,
6064 DWORD *BlockHandle)
6066 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6069 static HRESULT WINAPI
6070 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
6071 D3DSTATEBLOCKTYPE Type,
6072 DWORD *BlockHandle)
6074 HRESULT hr;
6075 WORD old_fpucw;
6077 old_fpucw = d3d_fpu_setup();
6078 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6079 set_fpu_control_word(old_fpucw);
6081 return hr;
6084 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6085 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
6086 IDirectDrawSurfaceImpl *src)
6088 IDirectDrawSurfaceImpl *src_level, *dest_level;
6089 IDirectDrawSurface7 *temp;
6090 DDSURFACEDESC2 ddsd;
6091 BOOL levelFound; /* at least one suitable sublevel in dest found */
6093 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
6094 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
6095 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
6097 levelFound = FALSE;
6099 src_level = src;
6100 dest_level = dest;
6102 for (;src_level && dest_level;)
6104 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6105 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6107 levelFound = TRUE;
6109 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6110 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6111 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6113 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6115 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6118 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6119 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6120 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6122 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6124 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6127 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6128 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6130 return !dest_level && levelFound;
6133 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6134 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
6135 IDirectDrawSurfaceImpl *dest,
6136 IDirectDrawSurfaceImpl *src,
6137 const POINT *DestPoint,
6138 const RECT *SrcRect)
6140 IDirectDrawSurfaceImpl *src_level, *dest_level;
6141 IDirectDrawSurface7 *temp;
6142 DDSURFACEDESC2 ddsd;
6143 POINT point;
6144 RECT src_rect;
6145 HRESULT hr;
6146 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
6147 DWORD ckeyflag;
6148 DDCOLORKEY ddckey;
6150 /* Copy palette, if possible. */
6151 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
6152 IDirectDrawSurface7_GetPalette(&dest->IDirectDrawSurface7_iface, &pal);
6154 if (pal_src != NULL && pal != NULL)
6156 PALETTEENTRY palent[256];
6158 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
6159 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
6162 if (pal) IDirectDrawPalette_Release(pal);
6163 if (pal_src) IDirectDrawPalette_Release(pal_src);
6165 /* Copy colorkeys, if present. */
6166 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6168 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6170 if (SUCCEEDED(hr))
6172 IDirectDrawSurface7_SetColorKey(&dest->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6176 src_level = src;
6177 dest_level = dest;
6179 point = *DestPoint;
6180 src_rect = *SrcRect;
6182 for (;src_level && dest_level;)
6184 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6185 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6187 UINT src_w = src_rect.right - src_rect.left;
6188 UINT src_h = src_rect.bottom - src_rect.top;
6189 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
6191 if (FAILED(hr = wined3d_surface_blt(dest_level->wined3d_surface, &dst_rect,
6192 src_level->wined3d_surface, &src_rect, 0, NULL, WINED3D_TEXF_POINT)))
6193 ERR("Blit failed, hr %#x.\n", hr);
6195 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6196 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6197 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6199 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6201 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6204 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6205 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6206 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6208 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6210 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6212 point.x /= 2;
6213 point.y /= 2;
6215 src_rect.top /= 2;
6216 src_rect.left /= 2;
6217 src_rect.right = (src_rect.right + 1) / 2;
6218 src_rect.bottom = (src_rect.bottom + 1) / 2;
6221 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6222 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6225 /*****************************************************************************
6226 * IDirect3DDevice7::Load
6228 * Loads a rectangular area from the source into the destination texture.
6229 * It can also copy the source to the faces of a cubic environment map
6231 * Version 7
6233 * Params:
6234 * DestTex: Destination texture
6235 * DestPoint: Point in the destination where the source image should be
6236 * written to
6237 * SrcTex: Source texture
6238 * SrcRect: Source rectangle
6239 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6240 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6241 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6243 * Returns:
6244 * D3D_OK on success
6245 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6248 *****************************************************************************/
6250 static HRESULT
6251 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6252 IDirectDrawSurface7 *DestTex,
6253 POINT *DestPoint,
6254 IDirectDrawSurface7 *SrcTex,
6255 RECT *SrcRect,
6256 DWORD Flags)
6258 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6259 IDirectDrawSurfaceImpl *dest = unsafe_impl_from_IDirectDrawSurface7(DestTex);
6260 IDirectDrawSurfaceImpl *src = unsafe_impl_from_IDirectDrawSurface7(SrcTex);
6261 POINT destpoint;
6262 RECT srcrect;
6264 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6265 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6267 if( (!src) || (!dest) )
6268 return DDERR_INVALIDPARAMS;
6270 wined3d_mutex_lock();
6272 if (SrcRect) srcrect = *SrcRect;
6273 else
6275 srcrect.left = srcrect.top = 0;
6276 srcrect.right = src->surface_desc.dwWidth;
6277 srcrect.bottom = src->surface_desc.dwHeight;
6280 if (DestPoint) destpoint = *DestPoint;
6281 else
6283 destpoint.x = destpoint.y = 0;
6285 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6286 * destination can be a subset of mip levels, in which case actual coordinates used
6287 * for it may be divided. If any dimension of dest is larger than source, it can't be
6288 * mip level subset, so an error can be returned early.
6290 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6291 srcrect.right > src->surface_desc.dwWidth ||
6292 srcrect.bottom > src->surface_desc.dwHeight ||
6293 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6294 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6295 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6296 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6298 wined3d_mutex_unlock();
6299 return DDERR_INVALIDPARAMS;
6302 /* Must be top level surfaces. */
6303 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6304 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6306 wined3d_mutex_unlock();
6307 return DDERR_INVALIDPARAMS;
6310 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6312 DWORD src_face_flag, dest_face_flag;
6313 IDirectDrawSurfaceImpl *src_face, *dest_face;
6314 IDirectDrawSurface7 *temp;
6315 DDSURFACEDESC2 ddsd;
6316 int i;
6318 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6320 wined3d_mutex_unlock();
6321 return DDERR_INVALIDPARAMS;
6324 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6325 * time it's actual surface loading. */
6326 for (i = 0; i < 2; i++)
6328 dest_face = dest;
6329 src_face = src;
6331 for (;dest_face && src_face;)
6333 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6334 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6336 if (src_face_flag == dest_face_flag)
6338 if (i == 0)
6340 /* Destination mip levels must be subset of source mip levels. */
6341 if (!is_mip_level_subset(dest_face, src_face))
6343 wined3d_mutex_unlock();
6344 return DDERR_INVALIDPARAMS;
6347 else if (Flags & dest_face_flag)
6349 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6352 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6354 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6355 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6356 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6358 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6360 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6362 else
6364 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6366 src_face = NULL;
6370 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6372 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6373 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6374 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6376 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6378 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6380 else
6382 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6384 dest_face = NULL;
6388 if (i == 0)
6390 /* Native returns error if src faces are not subset of dest faces. */
6391 if (src_face)
6393 wined3d_mutex_unlock();
6394 return DDERR_INVALIDPARAMS;
6399 wined3d_mutex_unlock();
6400 return D3D_OK;
6402 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6404 wined3d_mutex_unlock();
6405 return DDERR_INVALIDPARAMS;
6408 /* Handle non cube map textures. */
6410 /* Destination mip levels must be subset of source mip levels. */
6411 if (!is_mip_level_subset(dest, src))
6413 wined3d_mutex_unlock();
6414 return DDERR_INVALIDPARAMS;
6417 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6419 wined3d_mutex_unlock();
6421 return D3D_OK;
6424 static HRESULT WINAPI
6425 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6426 IDirectDrawSurface7 *DestTex,
6427 POINT *DestPoint,
6428 IDirectDrawSurface7 *SrcTex,
6429 RECT *SrcRect,
6430 DWORD Flags)
6432 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6435 static HRESULT WINAPI
6436 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6437 IDirectDrawSurface7 *DestTex,
6438 POINT *DestPoint,
6439 IDirectDrawSurface7 *SrcTex,
6440 RECT *SrcRect,
6441 DWORD Flags)
6443 HRESULT hr;
6444 WORD old_fpucw;
6446 old_fpucw = d3d_fpu_setup();
6447 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6448 set_fpu_control_word(old_fpucw);
6450 return hr;
6453 /*****************************************************************************
6454 * IDirect3DDevice7::LightEnable
6456 * Enables or disables a light
6458 * Version 7, IDirect3DLight uses this method too.
6460 * Params:
6461 * LightIndex: The index of the light to enable / disable
6462 * Enable: Enable or disable the light
6464 * Returns:
6465 * D3D_OK on success
6466 * For more details, see IWineD3DDevice::SetLightEnable
6468 *****************************************************************************/
6469 static HRESULT
6470 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6471 DWORD LightIndex,
6472 BOOL Enable)
6474 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6475 HRESULT hr;
6477 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6479 wined3d_mutex_lock();
6480 hr = wined3d_device_set_light_enable(This->wined3d_device, LightIndex, Enable);
6481 wined3d_mutex_unlock();
6483 return hr_ddraw_from_wined3d(hr);
6486 static HRESULT WINAPI
6487 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6488 DWORD LightIndex,
6489 BOOL Enable)
6491 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6494 static HRESULT WINAPI
6495 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6496 DWORD LightIndex,
6497 BOOL Enable)
6499 HRESULT hr;
6500 WORD old_fpucw;
6502 old_fpucw = d3d_fpu_setup();
6503 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6504 set_fpu_control_word(old_fpucw);
6506 return hr;
6509 /*****************************************************************************
6510 * IDirect3DDevice7::GetLightEnable
6512 * Retrieves if the light with the given index is enabled or not
6514 * Version 7
6516 * Params:
6517 * LightIndex: Index of desired light
6518 * Enable: Pointer to a BOOL which contains the result
6520 * Returns:
6521 * D3D_OK on success
6522 * DDERR_INVALIDPARAMS if Enable is NULL
6523 * See IWineD3DDevice::GetLightEnable for more details
6525 *****************************************************************************/
6526 static HRESULT
6527 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6528 DWORD LightIndex,
6529 BOOL* Enable)
6531 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6532 HRESULT hr;
6534 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6536 if(!Enable)
6537 return DDERR_INVALIDPARAMS;
6539 wined3d_mutex_lock();
6540 hr = wined3d_device_get_light_enable(This->wined3d_device, LightIndex, Enable);
6541 wined3d_mutex_unlock();
6543 return hr_ddraw_from_wined3d(hr);
6546 static HRESULT WINAPI
6547 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6548 DWORD LightIndex,
6549 BOOL* Enable)
6551 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6554 static HRESULT WINAPI
6555 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6556 DWORD LightIndex,
6557 BOOL* Enable)
6559 HRESULT hr;
6560 WORD old_fpucw;
6562 old_fpucw = d3d_fpu_setup();
6563 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6564 set_fpu_control_word(old_fpucw);
6566 return hr;
6569 /*****************************************************************************
6570 * IDirect3DDevice7::SetClipPlane
6572 * Sets custom clipping plane
6574 * Version 7
6576 * Params:
6577 * Index: The index of the clipping plane
6578 * PlaneEquation: An equation defining the clipping plane
6580 * Returns:
6581 * D3D_OK on success
6582 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6583 * See IWineD3DDevice::SetClipPlane for more details
6585 *****************************************************************************/
6586 static HRESULT
6587 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6588 DWORD Index,
6589 D3DVALUE* PlaneEquation)
6591 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6592 HRESULT hr;
6594 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6596 if(!PlaneEquation)
6597 return DDERR_INVALIDPARAMS;
6599 wined3d_mutex_lock();
6600 hr = wined3d_device_set_clip_plane(This->wined3d_device, Index, PlaneEquation);
6601 wined3d_mutex_unlock();
6603 return hr;
6606 static HRESULT WINAPI
6607 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6608 DWORD Index,
6609 D3DVALUE* PlaneEquation)
6611 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6614 static HRESULT WINAPI
6615 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6616 DWORD Index,
6617 D3DVALUE* PlaneEquation)
6619 HRESULT hr;
6620 WORD old_fpucw;
6622 old_fpucw = d3d_fpu_setup();
6623 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6624 set_fpu_control_word(old_fpucw);
6626 return hr;
6629 /*****************************************************************************
6630 * IDirect3DDevice7::GetClipPlane
6632 * Returns the clipping plane with a specific index
6634 * Params:
6635 * Index: The index of the desired plane
6636 * PlaneEquation: Address to store the plane equation to
6638 * Returns:
6639 * D3D_OK on success
6640 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6641 * See IWineD3DDevice::GetClipPlane for more details
6643 *****************************************************************************/
6644 static HRESULT
6645 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6646 DWORD Index,
6647 D3DVALUE* PlaneEquation)
6649 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6650 HRESULT hr;
6652 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6654 if(!PlaneEquation)
6655 return DDERR_INVALIDPARAMS;
6657 wined3d_mutex_lock();
6658 hr = wined3d_device_get_clip_plane(This->wined3d_device, Index, PlaneEquation);
6659 wined3d_mutex_unlock();
6661 return hr;
6664 static HRESULT WINAPI
6665 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6666 DWORD Index,
6667 D3DVALUE* PlaneEquation)
6669 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6672 static HRESULT WINAPI
6673 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6674 DWORD Index,
6675 D3DVALUE* PlaneEquation)
6677 HRESULT hr;
6678 WORD old_fpucw;
6680 old_fpucw = d3d_fpu_setup();
6681 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6682 set_fpu_control_word(old_fpucw);
6684 return hr;
6687 /*****************************************************************************
6688 * IDirect3DDevice7::GetInfo
6690 * Retrieves some information about the device. The DirectX sdk says that
6691 * this version returns S_FALSE for all retail builds of DirectX, that's what
6692 * this implementation does.
6694 * Params:
6695 * DevInfoID: Information type requested
6696 * DevInfoStruct: Pointer to a structure to store the info to
6697 * Size: Size of the structure
6699 * Returns:
6700 * S_FALSE, because it's a non-debug driver
6702 *****************************************************************************/
6703 static HRESULT WINAPI
6704 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6705 DWORD DevInfoID,
6706 void *DevInfoStruct,
6707 DWORD Size)
6709 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6710 iface, DevInfoID, DevInfoStruct, Size);
6712 if (TRACE_ON(ddraw))
6714 TRACE(" info requested : ");
6715 switch (DevInfoID)
6717 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6718 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6719 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6720 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6724 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6727 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6728 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6729 * are not duplicated.
6731 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6732 * has already been setup for optimal d3d operation.
6734 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6735 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6736 * by Sacrifice (game). */
6737 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6739 /*** IUnknown Methods ***/
6740 IDirect3DDeviceImpl_7_QueryInterface,
6741 IDirect3DDeviceImpl_7_AddRef,
6742 IDirect3DDeviceImpl_7_Release,
6743 /*** IDirect3DDevice7 ***/
6744 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6745 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6746 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6747 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6748 IDirect3DDeviceImpl_7_GetDirect3D,
6749 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6750 IDirect3DDeviceImpl_7_GetRenderTarget,
6751 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6752 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6753 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6754 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6755 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6756 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6757 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6758 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6759 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6760 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6761 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6762 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6763 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6764 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6765 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6766 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6767 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6768 IDirect3DDeviceImpl_7_SetClipStatus,
6769 IDirect3DDeviceImpl_7_GetClipStatus,
6770 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6771 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6772 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6773 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6774 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6775 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6776 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6777 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6778 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6779 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6780 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6781 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6782 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6783 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6784 IDirect3DDeviceImpl_7_Load_FPUSetup,
6785 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6786 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6787 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6788 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6789 IDirect3DDeviceImpl_7_GetInfo
6792 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6794 /*** IUnknown Methods ***/
6795 IDirect3DDeviceImpl_7_QueryInterface,
6796 IDirect3DDeviceImpl_7_AddRef,
6797 IDirect3DDeviceImpl_7_Release,
6798 /*** IDirect3DDevice7 ***/
6799 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6800 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6801 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6802 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6803 IDirect3DDeviceImpl_7_GetDirect3D,
6804 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6805 IDirect3DDeviceImpl_7_GetRenderTarget,
6806 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6807 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6808 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6809 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6810 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6811 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6812 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6813 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6814 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6815 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6816 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6817 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6818 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6819 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6820 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6821 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6822 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6823 IDirect3DDeviceImpl_7_SetClipStatus,
6824 IDirect3DDeviceImpl_7_GetClipStatus,
6825 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6826 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6827 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6828 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6829 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6830 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6831 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6832 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6833 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6834 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6835 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6836 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6837 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6838 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6839 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6840 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6841 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6842 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6843 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6844 IDirect3DDeviceImpl_7_GetInfo
6847 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6849 /*** IUnknown Methods ***/
6850 IDirect3DDeviceImpl_3_QueryInterface,
6851 IDirect3DDeviceImpl_3_AddRef,
6852 IDirect3DDeviceImpl_3_Release,
6853 /*** IDirect3DDevice3 ***/
6854 IDirect3DDeviceImpl_3_GetCaps,
6855 IDirect3DDeviceImpl_3_GetStats,
6856 IDirect3DDeviceImpl_3_AddViewport,
6857 IDirect3DDeviceImpl_3_DeleteViewport,
6858 IDirect3DDeviceImpl_3_NextViewport,
6859 IDirect3DDeviceImpl_3_EnumTextureFormats,
6860 IDirect3DDeviceImpl_3_BeginScene,
6861 IDirect3DDeviceImpl_3_EndScene,
6862 IDirect3DDeviceImpl_3_GetDirect3D,
6863 IDirect3DDeviceImpl_3_SetCurrentViewport,
6864 IDirect3DDeviceImpl_3_GetCurrentViewport,
6865 IDirect3DDeviceImpl_3_SetRenderTarget,
6866 IDirect3DDeviceImpl_3_GetRenderTarget,
6867 IDirect3DDeviceImpl_3_Begin,
6868 IDirect3DDeviceImpl_3_BeginIndexed,
6869 IDirect3DDeviceImpl_3_Vertex,
6870 IDirect3DDeviceImpl_3_Index,
6871 IDirect3DDeviceImpl_3_End,
6872 IDirect3DDeviceImpl_3_GetRenderState,
6873 IDirect3DDeviceImpl_3_SetRenderState,
6874 IDirect3DDeviceImpl_3_GetLightState,
6875 IDirect3DDeviceImpl_3_SetLightState,
6876 IDirect3DDeviceImpl_3_SetTransform,
6877 IDirect3DDeviceImpl_3_GetTransform,
6878 IDirect3DDeviceImpl_3_MultiplyTransform,
6879 IDirect3DDeviceImpl_3_DrawPrimitive,
6880 IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6881 IDirect3DDeviceImpl_3_SetClipStatus,
6882 IDirect3DDeviceImpl_3_GetClipStatus,
6883 IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6884 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6885 IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6886 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6887 IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6888 IDirect3DDeviceImpl_3_GetTexture,
6889 IDirect3DDeviceImpl_3_SetTexture,
6890 IDirect3DDeviceImpl_3_GetTextureStageState,
6891 IDirect3DDeviceImpl_3_SetTextureStageState,
6892 IDirect3DDeviceImpl_3_ValidateDevice
6895 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6897 /*** IUnknown Methods ***/
6898 IDirect3DDeviceImpl_2_QueryInterface,
6899 IDirect3DDeviceImpl_2_AddRef,
6900 IDirect3DDeviceImpl_2_Release,
6901 /*** IDirect3DDevice2 ***/
6902 IDirect3DDeviceImpl_2_GetCaps,
6903 IDirect3DDeviceImpl_2_SwapTextureHandles,
6904 IDirect3DDeviceImpl_2_GetStats,
6905 IDirect3DDeviceImpl_2_AddViewport,
6906 IDirect3DDeviceImpl_2_DeleteViewport,
6907 IDirect3DDeviceImpl_2_NextViewport,
6908 IDirect3DDeviceImpl_2_EnumTextureFormats,
6909 IDirect3DDeviceImpl_2_BeginScene,
6910 IDirect3DDeviceImpl_2_EndScene,
6911 IDirect3DDeviceImpl_2_GetDirect3D,
6912 IDirect3DDeviceImpl_2_SetCurrentViewport,
6913 IDirect3DDeviceImpl_2_GetCurrentViewport,
6914 IDirect3DDeviceImpl_2_SetRenderTarget,
6915 IDirect3DDeviceImpl_2_GetRenderTarget,
6916 IDirect3DDeviceImpl_2_Begin,
6917 IDirect3DDeviceImpl_2_BeginIndexed,
6918 IDirect3DDeviceImpl_2_Vertex,
6919 IDirect3DDeviceImpl_2_Index,
6920 IDirect3DDeviceImpl_2_End,
6921 IDirect3DDeviceImpl_2_GetRenderState,
6922 IDirect3DDeviceImpl_2_SetRenderState,
6923 IDirect3DDeviceImpl_2_GetLightState,
6924 IDirect3DDeviceImpl_2_SetLightState,
6925 IDirect3DDeviceImpl_2_SetTransform,
6926 IDirect3DDeviceImpl_2_GetTransform,
6927 IDirect3DDeviceImpl_2_MultiplyTransform,
6928 IDirect3DDeviceImpl_2_DrawPrimitive,
6929 IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6930 IDirect3DDeviceImpl_2_SetClipStatus,
6931 IDirect3DDeviceImpl_2_GetClipStatus
6934 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6936 /*** IUnknown Methods ***/
6937 IDirect3DDeviceImpl_1_QueryInterface,
6938 IDirect3DDeviceImpl_1_AddRef,
6939 IDirect3DDeviceImpl_1_Release,
6940 /*** IDirect3DDevice1 ***/
6941 IDirect3DDeviceImpl_1_Initialize,
6942 IDirect3DDeviceImpl_1_GetCaps,
6943 IDirect3DDeviceImpl_1_SwapTextureHandles,
6944 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6945 IDirect3DDeviceImpl_1_GetStats,
6946 IDirect3DDeviceImpl_1_Execute,
6947 IDirect3DDeviceImpl_1_AddViewport,
6948 IDirect3DDeviceImpl_1_DeleteViewport,
6949 IDirect3DDeviceImpl_1_NextViewport,
6950 IDirect3DDeviceImpl_1_Pick,
6951 IDirect3DDeviceImpl_1_GetPickRecords,
6952 IDirect3DDeviceImpl_1_EnumTextureFormats,
6953 IDirect3DDeviceImpl_1_CreateMatrix,
6954 IDirect3DDeviceImpl_1_SetMatrix,
6955 IDirect3DDeviceImpl_1_GetMatrix,
6956 IDirect3DDeviceImpl_1_DeleteMatrix,
6957 IDirect3DDeviceImpl_1_BeginScene,
6958 IDirect3DDeviceImpl_1_EndScene,
6959 IDirect3DDeviceImpl_1_GetDirect3D
6962 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6964 if (!iface) return NULL;
6965 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6966 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice7_iface);
6969 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6971 if (!iface) return NULL;
6972 assert(iface->lpVtbl == &d3d_device3_vtbl);
6973 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice3_iface);
6976 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6978 if (!iface) return NULL;
6979 assert(iface->lpVtbl == &d3d_device2_vtbl);
6980 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice2_iface);
6983 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6985 if (!iface) return NULL;
6986 assert(iface->lpVtbl == &d3d_device1_vtbl);
6987 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice_iface);
6990 /*****************************************************************************
6991 * IDirect3DDeviceImpl_UpdateDepthStencil
6993 * Checks the current render target for attached depth stencils and sets the
6994 * WineD3D depth stencil accordingly.
6996 * Returns:
6997 * The depth stencil state to set if creating the device
6999 *****************************************************************************/
7000 enum wined3d_depth_buffer_type IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
7002 IDirectDrawSurface7 *depthStencil = NULL;
7003 IDirectDrawSurfaceImpl *dsi;
7004 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
7006 IDirectDrawSurface7_GetAttachedSurface(&This->target->IDirectDrawSurface7_iface, &depthcaps, &depthStencil);
7007 if(!depthStencil)
7009 TRACE("Setting wined3d depth stencil to NULL\n");
7010 wined3d_device_set_depth_stencil(This->wined3d_device, NULL);
7011 return WINED3D_ZB_FALSE;
7014 dsi = impl_from_IDirectDrawSurface7(depthStencil);
7015 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
7016 wined3d_device_set_depth_stencil(This->wined3d_device, dsi->wined3d_surface);
7018 IDirectDrawSurface7_Release(depthStencil);
7019 return WINED3D_ZB_TRUE;
7022 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
7024 static const D3DMATRIX ident =
7026 1.0f, 0.0f, 0.0f, 0.0f,
7027 0.0f, 1.0f, 0.0f, 0.0f,
7028 0.0f, 0.0f, 1.0f, 0.0f,
7029 0.0f, 0.0f, 0.0f, 1.0f,
7031 HRESULT hr;
7033 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
7034 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
7035 else
7036 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
7038 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
7039 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
7040 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
7041 device->ref = 1;
7042 device->ddraw = ddraw;
7043 device->target = target;
7044 list_init(&device->viewport_list);
7046 if (!ddraw_handle_table_init(&device->handle_table, 64))
7048 ERR("Failed to initialize handle table.\n");
7049 return DDERR_OUTOFMEMORY;
7052 device->legacyTextureBlending = FALSE;
7053 device->legacy_projection = ident;
7054 device->legacy_clipspace = ident;
7056 /* Create an index buffer, it's needed for indexed drawing */
7057 hr = wined3d_buffer_create_ib(ddraw->wined3d_device, 0x40000 /* Length. Don't know how long it should be */,
7058 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3D_POOL_DEFAULT, NULL,
7059 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
7060 if (FAILED(hr))
7062 ERR("Failed to create an index buffer, hr %#x.\n", hr);
7063 ddraw_handle_table_destroy(&device->handle_table);
7064 return hr;
7067 /* This is for convenience. */
7068 device->wined3d_device = ddraw->wined3d_device;
7069 wined3d_device_incref(ddraw->wined3d_device);
7071 /* Render to the back buffer */
7072 hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
7073 if (FAILED(hr))
7075 ERR("Failed to set render target, hr %#x.\n", hr);
7076 wined3d_buffer_decref(device->indexbuffer);
7077 ddraw_handle_table_destroy(&device->handle_table);
7078 return hr;
7081 /* FIXME: This is broken. The target AddRef() makes some sense, because
7082 * we store a pointer during initialization, but then that's also where
7083 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
7084 /* AddRef the render target. Also AddRef the render target from ddraw,
7085 * because if it is released before the app releases the D3D device, the
7086 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
7088 * In most cases, those surfaces are the same anyway, but this will simply
7089 * add another ref which is released when the device is destroyed. */
7090 IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
7092 ddraw->d3ddevice = device;
7094 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE,
7095 IDirect3DDeviceImpl_UpdateDepthStencil(device));
7097 return D3D_OK;