ddraw: Keep track of the ddraw version used to create a device.
[wine/multimedia.git] / dlls / ddraw / device.c
blobb656ab00cbde7bee8c7b583824672c690b9bacf6
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);
36 WINE_DECLARE_DEBUG_CHANNEL(winediag);
38 /* The device ID */
39 const GUID IID_D3DDEVICE_WineD3D = {
40 0xaef72d43,
41 0xb09a,
42 0x4b7b,
43 { 0xb7,0x98,0xc6,0x8a,0x77,0x2d,0x72,0x2a }
46 static inline void set_fpu_control_word(WORD fpucw)
48 #if defined(__i386__) && defined(__GNUC__)
49 __asm__ volatile ("fldcw %0" : : "m" (fpucw));
50 #elif defined(__i386__) && defined(_MSC_VER)
51 __asm fldcw fpucw;
52 #endif
55 static inline WORD d3d_fpu_setup(void)
57 WORD oldcw;
59 #if defined(__i386__) && defined(__GNUC__)
60 __asm__ volatile ("fnstcw %0" : "=m" (oldcw));
61 #elif defined(__i386__) && defined(_MSC_VER)
62 __asm fnstcw oldcw;
63 #else
64 static BOOL warned = FALSE;
65 if(!warned)
67 FIXME("FPUPRESERVE not implemented for this platform / compiler\n");
68 warned = TRUE;
70 return 0;
71 #endif
73 set_fpu_control_word(0x37f);
75 return oldcw;
78 /*****************************************************************************
79 * IUnknown Methods. Common for Version 1, 2, 3 and 7
80 *****************************************************************************/
82 /*****************************************************************************
83 * IDirect3DDevice7::QueryInterface
85 * Used to query other interfaces from a Direct3DDevice interface.
86 * It can return interface pointers to all Direct3DDevice versions as well
87 * as IDirectDraw and IDirect3D. For a link to QueryInterface
88 * rules see ddraw.c, IDirectDraw7::QueryInterface
90 * Exists in Version 1, 2, 3 and 7
92 * Params:
93 * refiid: Interface ID queried for
94 * obj: Used to return the interface pointer
96 * Returns:
97 * D3D_OK or E_NOINTERFACE
99 *****************************************************************************/
100 static HRESULT WINAPI
101 IDirect3DDeviceImpl_7_QueryInterface(IDirect3DDevice7 *iface,
102 REFIID refiid,
103 void **obj)
105 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
107 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(refiid), obj);
109 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
110 *obj = NULL;
112 if(!refiid)
113 return DDERR_INVALIDPARAMS;
115 if ( IsEqualGUID( &IID_IUnknown, refiid ) )
117 *obj = iface;
120 /* Check DirectDraw Interfaces. */
121 else if( IsEqualGUID( &IID_IDirectDraw7, refiid ) )
123 *obj = &This->ddraw->IDirectDraw7_iface;
124 TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
126 else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
128 *obj = &This->ddraw->IDirectDraw4_iface;
129 TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
131 else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
133 *obj = &This->ddraw->IDirectDraw2_iface;
134 TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
136 else if( IsEqualGUID( &IID_IDirectDraw, refiid ) )
138 *obj = &This->ddraw->IDirectDraw_iface;
139 TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
142 /* Direct3D */
143 else if ( IsEqualGUID( &IID_IDirect3D , refiid ) )
145 *obj = &This->ddraw->IDirect3D_iface;
146 TRACE("(%p) Returning IDirect3D interface at %p\n", This, *obj);
148 else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) )
150 *obj = &This->ddraw->IDirect3D2_iface;
151 TRACE("(%p) Returning IDirect3D2 interface at %p\n", This, *obj);
153 else if ( IsEqualGUID( &IID_IDirect3D3 , refiid ) )
155 *obj = &This->ddraw->IDirect3D3_iface;
156 TRACE("(%p) Returning IDirect3D3 interface at %p\n", This, *obj);
158 else if ( IsEqualGUID( &IID_IDirect3D7 , refiid ) )
160 *obj = &This->ddraw->IDirect3D7_iface;
161 TRACE("(%p) Returning IDirect3D7 interface at %p\n", This, *obj);
164 /* Direct3DDevice */
165 else if ( IsEqualGUID( &IID_IDirect3DDevice , refiid ) )
167 *obj = &This->IDirect3DDevice_iface;
168 TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
170 else if ( IsEqualGUID( &IID_IDirect3DDevice2 , refiid ) ) {
171 *obj = &This->IDirect3DDevice2_iface;
172 TRACE("(%p) Returning IDirect3DDevice2 interface at %p\n", This, *obj);
174 else if ( IsEqualGUID( &IID_IDirect3DDevice3 , refiid ) ) {
175 *obj = &This->IDirect3DDevice3_iface;
176 TRACE("(%p) Returning IDirect3DDevice3 interface at %p\n", This, *obj);
178 else if ( IsEqualGUID( &IID_IDirect3DDevice7 , refiid ) ) {
179 *obj = &This->IDirect3DDevice7_iface;
180 TRACE("(%p) Returning IDirect3DDevice7 interface at %p\n", This, *obj);
183 /* DirectDrawSurface */
184 else if (IsEqualGUID(&IID_IDirectDrawSurface, refiid) && This->version == 1)
186 *obj = &This->target->IDirectDrawSurface_iface;
187 TRACE("Returning IDirectDrawSurface interface %p.\n", *obj);
190 /* Unknown interface */
191 else
193 ERR("(%p)->(%s, %p): No interface found\n", This, debugstr_guid(refiid), obj);
194 return E_NOINTERFACE;
197 /* AddRef the returned interface */
198 IUnknown_AddRef( (IUnknown *) *obj);
199 return D3D_OK;
202 static HRESULT WINAPI IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface, REFIID riid,
203 void **obj)
205 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
206 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
208 return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obj);
211 static HRESULT WINAPI IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface, REFIID riid,
212 void **obj)
214 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
215 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
217 return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obj);
220 static HRESULT WINAPI IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface, REFIID riid,
221 void **obp)
223 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
224 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
226 return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obp);
229 /*****************************************************************************
230 * IDirect3DDevice7::AddRef
232 * Increases the refcount....
233 * The most exciting Method, definitely
235 * Exists in Version 1, 2, 3 and 7
237 * Returns:
238 * The new refcount
240 *****************************************************************************/
241 static ULONG WINAPI
242 IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
244 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
245 ULONG ref = InterlockedIncrement(&This->ref);
247 TRACE("%p increasing refcount to %u.\n", This, ref);
249 return ref;
252 static ULONG WINAPI IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
254 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
255 TRACE("iface %p.\n", iface);
257 return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
260 static ULONG WINAPI IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
262 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
263 TRACE("iface %p.\n", iface);
265 return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
268 static ULONG WINAPI IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
270 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
271 TRACE("iface %p.\n", iface);
273 return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
276 /*****************************************************************************
277 * IDirect3DDevice7::Release
279 * Decreases the refcount of the interface
280 * When the refcount is reduced to 0, the object is destroyed.
282 * Exists in Version 1, 2, 3 and 7
284 * Returns:d
285 * The new refcount
287 *****************************************************************************/
288 static ULONG WINAPI
289 IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
291 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
292 ULONG ref = InterlockedDecrement(&This->ref);
294 TRACE("%p decreasing refcount to %u.\n", This, ref);
296 /* This method doesn't destroy the WineD3DDevice, because it's still in use for
297 * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
298 * when the render target is released
300 if (ref == 0)
302 DWORD i;
304 wined3d_mutex_lock();
306 /* There is no need to unset any resources here, wined3d will take
307 * care of that on Uninit3D(). */
309 /* Free the index buffer. */
310 wined3d_buffer_decref(This->indexbuffer);
312 /* Set the device up to render to the front buffer since the back
313 * buffer will vanish soon. */
314 wined3d_device_set_render_target(This->wined3d_device, 0,
315 This->ddraw->wined3d_frontbuffer, TRUE);
317 /* Release the WineD3DDevice. This won't destroy it. */
318 if (!wined3d_device_decref(This->wined3d_device))
319 ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This->wined3d_device);
321 /* The texture handles should be unset by now, but there might be some bits
322 * missing in our reference counting(needs test). Do a sanity check. */
323 for (i = 0; i < This->handle_table.entry_count; ++i)
325 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
327 switch (entry->type)
329 case DDRAW_HANDLE_FREE:
330 break;
332 case DDRAW_HANDLE_MATERIAL:
334 struct d3d_material *m = entry->object;
335 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
336 m->Handle = 0;
337 break;
340 case DDRAW_HANDLE_MATRIX:
342 /* No FIXME here because this might happen because of sloppy applications. */
343 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
344 IDirect3DDevice_DeleteMatrix(&This->IDirect3DDevice_iface, i + 1);
345 break;
348 case DDRAW_HANDLE_STATEBLOCK:
350 /* No FIXME here because this might happen because of sloppy applications. */
351 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
352 IDirect3DDevice7_DeleteStateBlock(iface, i + 1);
353 break;
356 case DDRAW_HANDLE_SURFACE:
358 struct ddraw_surface *surf = entry->object;
359 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
360 surf->Handle = 0;
361 break;
364 default:
365 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
366 break;
370 ddraw_handle_table_destroy(&This->handle_table);
372 TRACE("Releasing target %p.\n", This->target);
373 /* Release the render target and the WineD3D render target
374 * (See IDirect3D7::CreateDevice for more comments on this)
376 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
377 TRACE("Target release done\n");
379 This->ddraw->d3ddevice = NULL;
381 /* Now free the structure */
382 HeapFree(GetProcessHeap(), 0, This);
383 wined3d_mutex_unlock();
386 TRACE("Done\n");
387 return ref;
390 static ULONG WINAPI IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
392 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
393 TRACE("iface %p.\n", iface);
395 return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
398 static ULONG WINAPI IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
400 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
401 TRACE("iface %p.\n", iface);
403 return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
406 static ULONG WINAPI IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
408 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
409 TRACE("iface %p.\n", iface);
411 return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
414 /*****************************************************************************
415 * IDirect3DDevice Methods
416 *****************************************************************************/
418 /*****************************************************************************
419 * IDirect3DDevice::Initialize
421 * Initializes a Direct3DDevice. This implementation is a no-op, as all
422 * initialization is done at create time.
424 * Exists in Version 1
426 * Parameters:
427 * No idea what they mean, as the MSDN page is gone
429 * Returns: DD_OK
431 *****************************************************************************/
432 static HRESULT WINAPI
433 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
434 IDirect3D *Direct3D, GUID *guid,
435 D3DDEVICEDESC *Desc)
437 /* It shouldn't be crucial, but print a FIXME, I'm interested if
438 * any game calls it and when. */
439 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
440 iface, Direct3D, debugstr_guid(guid), Desc);
442 return D3D_OK;
445 /*****************************************************************************
446 * IDirect3DDevice7::GetCaps
448 * Retrieves the device's capabilities
450 * This implementation is used for Version 7 only, the older versions have
451 * their own implementation.
453 * Parameters:
454 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
456 * Returns:
457 * D3D_OK on success
458 * D3DERR_* if a problem occurs. See WineD3D
460 *****************************************************************************/
461 static HRESULT
462 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
463 D3DDEVICEDESC7 *Desc)
465 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
466 D3DDEVICEDESC OldDesc;
468 TRACE("iface %p, device_desc %p.\n", iface, Desc);
470 if (!Desc)
472 WARN("Desc is NULL, returning DDERR_INVALIDPARAMS.\n");
473 return DDERR_INVALIDPARAMS;
476 /* Call the same function used by IDirect3D, this saves code */
477 return IDirect3DImpl_GetCaps(This->ddraw->wined3d, &OldDesc, Desc);
480 static HRESULT WINAPI
481 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
482 D3DDEVICEDESC7 *Desc)
484 return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
487 static HRESULT WINAPI
488 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
489 D3DDEVICEDESC7 *Desc)
491 HRESULT hr;
492 WORD old_fpucw;
494 old_fpucw = d3d_fpu_setup();
495 hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
496 set_fpu_control_word(old_fpucw);
498 return hr;
500 /*****************************************************************************
501 * IDirect3DDevice3::GetCaps
503 * Retrieves the capabilities of the hardware device and the emulation
504 * device. For Wine, hardware and emulation are the same (it's all HW).
506 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
508 * Parameters:
509 * HWDesc: Structure to fill with the HW caps
510 * HelDesc: Structure to fill with the hardware emulation caps
512 * Returns:
513 * D3D_OK on success
514 * D3DERR_* if a problem occurs. See WineD3D
516 *****************************************************************************/
518 /* There are 3 versions of D3DDEVICEDESC. All 3 share the same name because
519 * Microsoft just expanded the existing structure without naming them
520 * D3DDEVICEDESC2 and D3DDEVICEDESC3. Which version is used have depends
521 * on the version of the DirectX SDK. DirectX 6+ and Wine use the latest
522 * one with 252 bytes.
524 * All 3 versions are allowed as parameters and only the specified amount of
525 * bytes is written.
527 * Note that Direct3D7 and earlier are not available in native Win64
528 * ddraw.dll builds, so possible size differences between 32 bit and
529 * 64 bit are a non-issue.
531 static inline BOOL check_d3ddevicedesc_size(DWORD size)
533 if (size == FIELD_OFFSET(D3DDEVICEDESC, dwMinTextureWidth) /* 172 */
534 || size == FIELD_OFFSET(D3DDEVICEDESC, dwMaxTextureRepeat) /* 204 */
535 || size == sizeof(D3DDEVICEDESC) /* 252 */) return TRUE;
536 return FALSE;
539 static HRESULT WINAPI
540 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
541 D3DDEVICEDESC *HWDesc,
542 D3DDEVICEDESC *HelDesc)
544 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
545 D3DDEVICEDESC oldDesc;
546 D3DDEVICEDESC7 newDesc;
547 HRESULT hr;
549 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
551 if (!HWDesc)
553 WARN("HWDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
554 return DDERR_INVALIDPARAMS;
556 if (!check_d3ddevicedesc_size(HWDesc->dwSize))
558 WARN("HWDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HWDesc->dwSize);
559 return DDERR_INVALIDPARAMS;
561 if (!HelDesc)
563 WARN("HelDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
564 return DDERR_INVALIDPARAMS;
566 if (!check_d3ddevicedesc_size(HelDesc->dwSize))
568 WARN("HelDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HelDesc->dwSize);
569 return DDERR_INVALIDPARAMS;
572 hr = IDirect3DImpl_GetCaps(This->ddraw->wined3d, &oldDesc, &newDesc);
573 if(hr != D3D_OK) return hr;
575 DD_STRUCT_COPY_BYSIZE(HWDesc, &oldDesc);
576 DD_STRUCT_COPY_BYSIZE(HelDesc, &oldDesc);
577 return D3D_OK;
580 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
581 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
583 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
584 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
585 return IDirect3DDevice3_GetCaps(&This->IDirect3DDevice3_iface, D3DHWDevDesc, D3DHELDevDesc);
588 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
589 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
591 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
592 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
593 return IDirect3DDevice3_GetCaps(&This->IDirect3DDevice3_iface, D3DHWDevDesc, D3DHELDevDesc);
596 /*****************************************************************************
597 * IDirect3DDevice2::SwapTextureHandles
599 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
601 * Parameters:
602 * Tex1, Tex2: The 2 Textures to swap
604 * Returns:
605 * D3D_OK
607 *****************************************************************************/
608 static HRESULT WINAPI
609 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
610 IDirect3DTexture2 *Tex1,
611 IDirect3DTexture2 *Tex2)
613 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
614 struct ddraw_surface *surf1 = unsafe_impl_from_IDirect3DTexture2(Tex1);
615 struct ddraw_surface *surf2 = unsafe_impl_from_IDirect3DTexture2(Tex2);
616 DWORD h1, h2;
618 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, Tex1, Tex2);
620 wined3d_mutex_lock();
622 h1 = surf1->Handle - 1;
623 h2 = surf2->Handle - 1;
624 This->handle_table.entries[h1].object = surf2;
625 This->handle_table.entries[h2].object = surf1;
626 surf2->Handle = h1 + 1;
627 surf1->Handle = h2 + 1;
629 wined3d_mutex_unlock();
631 return D3D_OK;
634 static HRESULT WINAPI IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
635 IDirect3DTexture *D3DTex1, IDirect3DTexture *D3DTex2)
637 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
638 struct ddraw_surface *surf1 = unsafe_impl_from_IDirect3DTexture(D3DTex1);
639 struct ddraw_surface *surf2 = unsafe_impl_from_IDirect3DTexture(D3DTex2);
640 IDirect3DTexture2 *t1 = surf1 ? &surf1->IDirect3DTexture2_iface : NULL;
641 IDirect3DTexture2 *t2 = surf2 ? &surf2->IDirect3DTexture2_iface : NULL;
643 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, D3DTex1, D3DTex2);
645 return IDirect3DDevice2_SwapTextureHandles(&This->IDirect3DDevice2_iface, t1, t2);
648 /*****************************************************************************
649 * IDirect3DDevice3::GetStats
651 * This method seems to retrieve some stats from the device.
652 * The MSDN documentation doesn't exist any more, but the D3DSTATS
653 * structure suggests that the amount of drawn primitives and processed
654 * vertices is returned.
656 * Exists in Version 1, 2 and 3
658 * Parameters:
659 * Stats: Pointer to a D3DSTATS structure to be filled
661 * Returns:
662 * D3D_OK on success
663 * DDERR_INVALIDPARAMS if Stats == NULL
665 *****************************************************************************/
666 static HRESULT WINAPI
667 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
668 D3DSTATS *Stats)
670 FIXME("iface %p, stats %p stub!\n", iface, Stats);
672 if(!Stats)
673 return DDERR_INVALIDPARAMS;
675 /* Fill the Stats with 0 */
676 Stats->dwTrianglesDrawn = 0;
677 Stats->dwLinesDrawn = 0;
678 Stats->dwPointsDrawn = 0;
679 Stats->dwSpansDrawn = 0;
680 Stats->dwVerticesProcessed = 0;
682 return D3D_OK;
685 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *Stats)
687 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
689 TRACE("iface %p, stats %p.\n", iface, Stats);
691 return IDirect3DDevice3_GetStats(&This->IDirect3DDevice3_iface, Stats);
694 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface, D3DSTATS *Stats)
696 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
698 TRACE("iface %p, stats %p.\n", iface, Stats);
700 return IDirect3DDevice3_GetStats(&This->IDirect3DDevice3_iface, Stats);
703 /*****************************************************************************
704 * IDirect3DDevice::CreateExecuteBuffer
706 * Creates an IDirect3DExecuteBuffer, used for rendering with a
707 * Direct3DDevice.
709 * Version 1 only.
711 * Params:
712 * Desc: Buffer description
713 * ExecuteBuffer: Address to return the Interface pointer at
714 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
715 * support
717 * Returns:
718 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
719 * DDERR_OUTOFMEMORY if we ran out of memory
720 * D3D_OK on success
722 *****************************************************************************/
723 static HRESULT WINAPI
724 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
725 D3DEXECUTEBUFFERDESC *Desc,
726 IDirect3DExecuteBuffer **ExecuteBuffer,
727 IUnknown *UnkOuter)
729 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
730 IDirect3DExecuteBufferImpl* object;
731 HRESULT hr;
733 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
734 iface, Desc, ExecuteBuffer, UnkOuter);
736 if(UnkOuter)
737 return CLASS_E_NOAGGREGATION;
739 /* Allocate the new Execute Buffer */
740 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
741 if(!object)
743 ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
744 return DDERR_OUTOFMEMORY;
747 hr = d3d_execute_buffer_init(object, This, Desc);
748 if (FAILED(hr))
750 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
751 HeapFree(GetProcessHeap(), 0, object);
752 return hr;
755 *ExecuteBuffer = &object->IDirect3DExecuteBuffer_iface;
757 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
759 return D3D_OK;
762 /*****************************************************************************
763 * IDirect3DDevice::Execute
765 * Executes all the stuff in an execute buffer.
767 * Params:
768 * ExecuteBuffer: The buffer to execute
769 * Viewport: The viewport used for rendering
770 * Flags: Some flags
772 * Returns:
773 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
774 * D3D_OK on success
776 *****************************************************************************/
777 static HRESULT WINAPI IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
778 IDirect3DExecuteBuffer *ExecuteBuffer, IDirect3DViewport *Viewport, DWORD Flags)
780 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
781 IDirect3DExecuteBufferImpl *buffer = unsafe_impl_from_IDirect3DExecuteBuffer(ExecuteBuffer);
782 struct d3d_viewport *viewport_impl = unsafe_impl_from_IDirect3DViewport(Viewport);
783 HRESULT hr;
785 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, Viewport, Flags);
787 if(!buffer)
788 return DDERR_INVALIDPARAMS;
790 /* Execute... */
791 wined3d_mutex_lock();
792 hr = d3d_execute_buffer_execute(buffer, This, viewport_impl);
793 wined3d_mutex_unlock();
795 return hr;
798 /*****************************************************************************
799 * IDirect3DDevice3::AddViewport
801 * Add a Direct3DViewport to the device's viewport list. These viewports
802 * are wrapped to IDirect3DDevice7 viewports in viewport.c
804 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
805 * are the same interfaces.
807 * Params:
808 * Viewport: The viewport to add
810 * Returns:
811 * DDERR_INVALIDPARAMS if Viewport == NULL
812 * D3D_OK on success
814 *****************************************************************************/
815 static HRESULT WINAPI
816 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
817 IDirect3DViewport3 *Viewport)
819 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
820 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Viewport);
822 TRACE("iface %p, viewport %p.\n", iface, Viewport);
824 /* Sanity check */
825 if(!vp)
826 return DDERR_INVALIDPARAMS;
828 wined3d_mutex_lock();
829 list_add_head(&This->viewport_list, &vp->entry);
830 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
831 so set active_device here. */
832 wined3d_mutex_unlock();
834 return D3D_OK;
837 static HRESULT WINAPI IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
838 IDirect3DViewport2 *Direct3DViewport2)
840 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
841 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
843 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
845 return IDirect3DDevice3_AddViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
848 static HRESULT WINAPI IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
849 IDirect3DViewport *Direct3DViewport)
851 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
852 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(Direct3DViewport);
854 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
856 return IDirect3DDevice3_AddViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
859 /*****************************************************************************
860 * IDirect3DDevice3::DeleteViewport
862 * Deletes a Direct3DViewport from the device's viewport list.
864 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
865 * are equal.
867 * Params:
868 * Viewport: The viewport to delete
870 * Returns:
871 * D3D_OK on success
872 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
874 *****************************************************************************/
875 static HRESULT WINAPI IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
877 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
878 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
880 TRACE("iface %p, viewport %p.\n", iface, viewport);
882 wined3d_mutex_lock();
884 if (vp->active_device != This)
886 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
887 wined3d_mutex_unlock();
888 return DDERR_INVALIDPARAMS;
891 vp->active_device = NULL;
892 list_remove(&vp->entry);
894 wined3d_mutex_unlock();
896 return D3D_OK;
899 static HRESULT WINAPI IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
900 IDirect3DViewport2 *Direct3DViewport2)
902 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
903 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
905 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
907 return IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
910 static HRESULT WINAPI IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
911 IDirect3DViewport *Direct3DViewport)
913 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
914 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(Direct3DViewport);
916 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
918 return IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
921 /*****************************************************************************
922 * IDirect3DDevice3::NextViewport
924 * Returns a viewport from the viewport list, depending on the
925 * passed viewport and the flags.
927 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
928 * are equal.
930 * Params:
931 * Viewport: Viewport to use for beginning the search
932 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
934 * Returns:
935 * D3D_OK on success
936 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
938 *****************************************************************************/
939 static HRESULT WINAPI
940 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
941 IDirect3DViewport3 *Viewport3,
942 IDirect3DViewport3 **lplpDirect3DViewport3,
943 DWORD Flags)
945 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
946 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Viewport3);
947 struct d3d_viewport *next;
948 struct list *entry;
950 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
951 iface, Viewport3, lplpDirect3DViewport3, Flags);
953 if(!vp)
955 *lplpDirect3DViewport3 = NULL;
956 return DDERR_INVALIDPARAMS;
960 wined3d_mutex_lock();
961 switch (Flags)
963 case D3DNEXT_NEXT:
964 entry = list_next(&This->viewport_list, &vp->entry);
965 break;
967 case D3DNEXT_HEAD:
968 entry = list_head(&This->viewport_list);
969 break;
971 case D3DNEXT_TAIL:
972 entry = list_tail(&This->viewport_list);
973 break;
975 default:
976 WARN("Invalid flags %#x.\n", Flags);
977 *lplpDirect3DViewport3 = NULL;
978 wined3d_mutex_unlock();
979 return DDERR_INVALIDPARAMS;
982 if (entry)
984 next = LIST_ENTRY(entry, struct d3d_viewport, entry);
985 *lplpDirect3DViewport3 = &next->IDirect3DViewport3_iface;
987 else
988 *lplpDirect3DViewport3 = NULL;
990 wined3d_mutex_unlock();
992 return D3D_OK;
995 static HRESULT WINAPI IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
996 IDirect3DViewport2 *Viewport2, IDirect3DViewport2 **lplpDirect3DViewport2, DWORD Flags)
998 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
999 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(Viewport2);
1000 IDirect3DViewport3 *res;
1001 HRESULT hr;
1003 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
1004 iface, Viewport2, lplpDirect3DViewport2, Flags);
1006 hr = IDirect3DDevice3_NextViewport(&This->IDirect3DDevice3_iface,
1007 &vp->IDirect3DViewport3_iface, &res, Flags);
1008 *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
1009 return hr;
1012 static HRESULT WINAPI IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
1013 IDirect3DViewport *Viewport, IDirect3DViewport **lplpDirect3DViewport, DWORD Flags)
1015 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1016 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(Viewport);
1017 IDirect3DViewport3 *res;
1018 HRESULT hr;
1020 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
1021 iface, Viewport, lplpDirect3DViewport, Flags);
1023 hr = IDirect3DDevice3_NextViewport(&This->IDirect3DDevice3_iface,
1024 &vp->IDirect3DViewport3_iface, &res, Flags);
1025 *lplpDirect3DViewport = (IDirect3DViewport *)res;
1026 return hr;
1029 /*****************************************************************************
1030 * IDirect3DDevice::Pick
1032 * Executes an execute buffer without performing rendering. Instead, a
1033 * list of primitives that intersect with (x1,y1) of the passed rectangle
1034 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
1035 * this list.
1037 * Version 1 only
1039 * Params:
1040 * ExecuteBuffer: Buffer to execute
1041 * Viewport: Viewport to use for execution
1042 * Flags: None are defined, according to the SDK
1043 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
1044 * x2 and y2 are ignored.
1046 * Returns:
1047 * D3D_OK because it's a stub
1049 *****************************************************************************/
1050 static HRESULT WINAPI
1051 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
1052 IDirect3DExecuteBuffer *ExecuteBuffer,
1053 IDirect3DViewport *Viewport,
1054 DWORD Flags,
1055 D3DRECT *Rect)
1057 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
1058 iface, ExecuteBuffer, Viewport, Flags, wine_dbgstr_rect((RECT *)Rect));
1060 return D3D_OK;
1063 /*****************************************************************************
1064 * IDirect3DDevice::GetPickRecords
1066 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1068 * Version 1 only
1070 * Params:
1071 * Count: Pointer to a DWORD containing the numbers of pick records to
1072 * retrieve
1073 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1075 * Returns:
1076 * D3D_OK, because it's a stub
1078 *****************************************************************************/
1079 static HRESULT WINAPI
1080 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1081 DWORD *Count,
1082 D3DPICKRECORD *D3DPickRec)
1084 FIXME("iface %p, count %p, records %p stub!\n", iface, Count, D3DPickRec);
1086 return D3D_OK;
1089 /*****************************************************************************
1090 * IDirect3DDevice7::EnumTextureformats
1092 * Enumerates the supported texture formats. It has a list of all possible
1093 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1094 * WineD3D supports it. If so, then it is passed to the app.
1096 * This is for Version 7 and 3, older versions have a different
1097 * callback function and their own implementation
1099 * Params:
1100 * Callback: Callback to call for each enumerated format
1101 * Arg: Argument to pass to the callback
1103 * Returns:
1104 * D3D_OK on success
1105 * DDERR_INVALIDPARAMS if Callback == NULL
1107 *****************************************************************************/
1108 static HRESULT
1109 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1110 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1111 void *Arg)
1113 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1114 struct wined3d_display_mode mode;
1115 HRESULT hr;
1116 unsigned int i;
1118 static const enum wined3d_format_id FormatList[] =
1120 /* 16 bit */
1121 WINED3DFMT_B5G5R5X1_UNORM,
1122 WINED3DFMT_B5G5R5A1_UNORM,
1123 WINED3DFMT_B4G4R4A4_UNORM,
1124 WINED3DFMT_B5G6R5_UNORM,
1125 /* 32 bit */
1126 WINED3DFMT_B8G8R8X8_UNORM,
1127 WINED3DFMT_B8G8R8A8_UNORM,
1128 /* 8 bit */
1129 WINED3DFMT_B2G3R3_UNORM,
1130 WINED3DFMT_P8_UINT,
1131 /* FOURCC codes */
1132 WINED3DFMT_DXT1,
1133 WINED3DFMT_DXT3,
1134 WINED3DFMT_DXT5,
1137 static const enum wined3d_format_id BumpFormatList[] =
1139 WINED3DFMT_R8G8_SNORM,
1140 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1141 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1142 WINED3DFMT_R16G16_SNORM,
1143 WINED3DFMT_R10G11B11_SNORM,
1144 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1147 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1149 if(!Callback)
1150 return DDERR_INVALIDPARAMS;
1152 wined3d_mutex_lock();
1154 memset(&mode, 0, sizeof(mode));
1155 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1156 if (FAILED(hr))
1158 wined3d_mutex_unlock();
1159 WARN("Cannot get the current adapter format\n");
1160 return hr;
1163 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1165 hr = wined3d_check_device_format(This->ddraw->wined3d, WINED3DADAPTER_DEFAULT, WINED3D_DEVICE_TYPE_HAL,
1166 mode.format_id, 0, WINED3D_RTYPE_TEXTURE, FormatList[i], WINED3D_SURFACE_TYPE_OPENGL);
1167 if (hr == D3D_OK)
1169 DDPIXELFORMAT pformat;
1171 memset(&pformat, 0, sizeof(pformat));
1172 pformat.dwSize = sizeof(pformat);
1173 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1175 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1176 hr = Callback(&pformat, Arg);
1177 if(hr != DDENUMRET_OK)
1179 TRACE("Format enumeration cancelled by application\n");
1180 wined3d_mutex_unlock();
1181 return D3D_OK;
1186 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1188 hr = wined3d_check_device_format(This->ddraw->wined3d, WINED3DADAPTER_DEFAULT,
1189 WINED3D_DEVICE_TYPE_HAL, mode.format_id, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1190 WINED3D_RTYPE_TEXTURE, BumpFormatList[i], WINED3D_SURFACE_TYPE_OPENGL);
1191 if (hr == D3D_OK)
1193 DDPIXELFORMAT pformat;
1195 memset(&pformat, 0, sizeof(pformat));
1196 pformat.dwSize = sizeof(pformat);
1197 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1199 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1200 hr = Callback(&pformat, Arg);
1201 if(hr != DDENUMRET_OK)
1203 TRACE("Format enumeration cancelled by application\n");
1204 wined3d_mutex_unlock();
1205 return D3D_OK;
1209 TRACE("End of enumeration\n");
1210 wined3d_mutex_unlock();
1212 return D3D_OK;
1215 static HRESULT WINAPI
1216 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1217 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1218 void *Arg)
1220 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1223 static HRESULT WINAPI
1224 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1225 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1226 void *Arg)
1228 HRESULT hr;
1229 WORD old_fpucw;
1231 old_fpucw = d3d_fpu_setup();
1232 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1233 set_fpu_control_word(old_fpucw);
1235 return hr;
1238 static HRESULT WINAPI IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1239 LPD3DENUMPIXELFORMATSCALLBACK Callback, void *Arg)
1241 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1243 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1245 return IDirect3DDevice7_EnumTextureFormats(&This->IDirect3DDevice7_iface, Callback, Arg);
1248 /*****************************************************************************
1249 * IDirect3DDevice2::EnumTextureformats
1251 * EnumTextureFormats for Version 1 and 2, see
1252 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1254 * This version has a different callback and does not enumerate FourCC
1255 * formats
1257 *****************************************************************************/
1258 static HRESULT WINAPI
1259 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1260 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1261 void *Arg)
1263 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1264 struct wined3d_display_mode mode;
1265 HRESULT hr;
1266 unsigned int i;
1268 static const enum wined3d_format_id FormatList[] =
1270 /* 16 bit */
1271 WINED3DFMT_B5G5R5X1_UNORM,
1272 WINED3DFMT_B5G5R5A1_UNORM,
1273 WINED3DFMT_B4G4R4A4_UNORM,
1274 WINED3DFMT_B5G6R5_UNORM,
1275 /* 32 bit */
1276 WINED3DFMT_B8G8R8X8_UNORM,
1277 WINED3DFMT_B8G8R8A8_UNORM,
1278 /* 8 bit */
1279 WINED3DFMT_B2G3R3_UNORM,
1280 WINED3DFMT_P8_UINT,
1281 /* FOURCC codes - Not in this version*/
1284 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1286 if(!Callback)
1287 return DDERR_INVALIDPARAMS;
1289 wined3d_mutex_lock();
1291 memset(&mode, 0, sizeof(mode));
1292 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1293 if (FAILED(hr))
1295 wined3d_mutex_unlock();
1296 WARN("Cannot get the current adapter format\n");
1297 return hr;
1300 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1302 hr = wined3d_check_device_format(This->ddraw->wined3d, 0, WINED3D_DEVICE_TYPE_HAL,
1303 mode.format_id, 0, WINED3D_RTYPE_TEXTURE, FormatList[i], WINED3D_SURFACE_TYPE_OPENGL);
1304 if (hr == D3D_OK)
1306 DDSURFACEDESC sdesc;
1308 memset(&sdesc, 0, sizeof(sdesc));
1309 sdesc.dwSize = sizeof(sdesc);
1310 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1311 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1312 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1313 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1315 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1316 hr = Callback(&sdesc, Arg);
1317 if(hr != DDENUMRET_OK)
1319 TRACE("Format enumeration cancelled by application\n");
1320 wined3d_mutex_unlock();
1321 return D3D_OK;
1325 TRACE("End of enumeration\n");
1326 wined3d_mutex_unlock();
1328 return D3D_OK;
1331 static HRESULT WINAPI IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1332 LPD3DENUMTEXTUREFORMATSCALLBACK Callback, void *Arg)
1334 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1336 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1338 return IDirect3DDevice2_EnumTextureFormats(&This->IDirect3DDevice2_iface, Callback, Arg);
1341 /*****************************************************************************
1342 * IDirect3DDevice::CreateMatrix
1344 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1345 * allocated for the handle.
1347 * Version 1 only
1349 * Params
1350 * D3DMatHandle: Address to return the handle at
1352 * Returns:
1353 * D3D_OK on success
1354 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1356 *****************************************************************************/
1357 static HRESULT WINAPI
1358 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1360 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1361 D3DMATRIX *Matrix;
1362 DWORD h;
1364 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1366 if(!D3DMatHandle)
1367 return DDERR_INVALIDPARAMS;
1369 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1370 if(!Matrix)
1372 ERR("Out of memory when allocating a D3DMATRIX\n");
1373 return DDERR_OUTOFMEMORY;
1376 wined3d_mutex_lock();
1378 h = ddraw_allocate_handle(&This->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1379 if (h == DDRAW_INVALID_HANDLE)
1381 ERR("Failed to allocate a matrix handle.\n");
1382 HeapFree(GetProcessHeap(), 0, Matrix);
1383 wined3d_mutex_unlock();
1384 return DDERR_OUTOFMEMORY;
1387 *D3DMatHandle = h + 1;
1389 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1391 wined3d_mutex_unlock();
1393 return D3D_OK;
1396 /*****************************************************************************
1397 * IDirect3DDevice::SetMatrix
1399 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1400 * allocated for the handle
1402 * Version 1 only
1404 * Params:
1405 * D3DMatHandle: Handle to set the matrix to
1406 * D3DMatrix: Matrix to set
1408 * Returns:
1409 * D3D_OK on success
1410 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1411 * to set is NULL
1413 *****************************************************************************/
1414 static HRESULT WINAPI
1415 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1416 D3DMATRIXHANDLE D3DMatHandle,
1417 D3DMATRIX *D3DMatrix)
1419 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1420 D3DMATRIX *m;
1422 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1424 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1426 wined3d_mutex_lock();
1428 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1429 if (!m)
1431 WARN("Invalid matrix handle.\n");
1432 wined3d_mutex_unlock();
1433 return DDERR_INVALIDPARAMS;
1436 if (TRACE_ON(ddraw))
1437 dump_D3DMATRIX(D3DMatrix);
1439 *m = *D3DMatrix;
1441 if (D3DMatHandle == This->world)
1442 wined3d_device_set_transform(This->wined3d_device,
1443 WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix *)D3DMatrix);
1445 if (D3DMatHandle == This->view)
1446 wined3d_device_set_transform(This->wined3d_device,
1447 WINED3D_TS_VIEW, (struct wined3d_matrix *)D3DMatrix);
1449 if (D3DMatHandle == This->proj)
1450 wined3d_device_set_transform(This->wined3d_device,
1451 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)D3DMatrix);
1453 wined3d_mutex_unlock();
1455 return D3D_OK;
1458 /*****************************************************************************
1459 * IDirect3DDevice::GetMatrix
1461 * Returns the content of a D3DMATRIX handle
1463 * Version 1 only
1465 * Params:
1466 * D3DMatHandle: Matrix handle to read the content from
1467 * D3DMatrix: Address to store the content at
1469 * Returns:
1470 * D3D_OK on success
1471 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1473 *****************************************************************************/
1474 static HRESULT WINAPI
1475 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1476 D3DMATRIXHANDLE D3DMatHandle,
1477 D3DMATRIX *D3DMatrix)
1479 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1480 D3DMATRIX *m;
1482 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1484 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1486 wined3d_mutex_lock();
1488 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1489 if (!m)
1491 WARN("Invalid matrix handle.\n");
1492 wined3d_mutex_unlock();
1493 return DDERR_INVALIDPARAMS;
1496 *D3DMatrix = *m;
1498 wined3d_mutex_unlock();
1500 return D3D_OK;
1503 /*****************************************************************************
1504 * IDirect3DDevice::DeleteMatrix
1506 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1508 * Version 1 only
1510 * Params:
1511 * D3DMatHandle: Handle to destroy
1513 * Returns:
1514 * D3D_OK on success
1515 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1517 *****************************************************************************/
1518 static HRESULT WINAPI
1519 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1520 D3DMATRIXHANDLE D3DMatHandle)
1522 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1523 D3DMATRIX *m;
1525 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1527 wined3d_mutex_lock();
1529 m = ddraw_free_handle(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1530 if (!m)
1532 WARN("Invalid matrix handle.\n");
1533 wined3d_mutex_unlock();
1534 return DDERR_INVALIDPARAMS;
1537 wined3d_mutex_unlock();
1539 HeapFree(GetProcessHeap(), 0, m);
1541 return D3D_OK;
1544 /*****************************************************************************
1545 * IDirect3DDevice7::BeginScene
1547 * This method must be called before any rendering is performed.
1548 * IDirect3DDevice::EndScene has to be called after the scene is complete
1550 * Version 1, 2, 3 and 7
1552 * Returns:
1553 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1554 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1555 * started scene).
1557 *****************************************************************************/
1558 static HRESULT
1559 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1561 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1562 HRESULT hr;
1564 TRACE("iface %p.\n", iface);
1566 wined3d_mutex_lock();
1567 hr = wined3d_device_begin_scene(This->wined3d_device);
1568 wined3d_mutex_unlock();
1570 if(hr == WINED3D_OK) return D3D_OK;
1571 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1574 static HRESULT WINAPI
1575 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1577 return IDirect3DDeviceImpl_7_BeginScene(iface);
1580 static HRESULT WINAPI
1581 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1583 HRESULT hr;
1584 WORD old_fpucw;
1586 old_fpucw = d3d_fpu_setup();
1587 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1588 set_fpu_control_word(old_fpucw);
1590 return hr;
1593 static HRESULT WINAPI IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1595 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1596 TRACE("iface %p.\n", iface);
1598 return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
1601 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1603 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1604 TRACE("iface %p.\n", iface);
1606 return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
1609 static HRESULT WINAPI IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1611 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1612 TRACE("iface %p.\n", iface);
1614 return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
1617 /*****************************************************************************
1618 * IDirect3DDevice7::EndScene
1620 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1621 * This method must be called after rendering is finished.
1623 * Version 1, 2, 3 and 7
1625 * Returns:
1626 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1627 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1628 * that only if the scene was already ended.
1630 *****************************************************************************/
1631 static HRESULT
1632 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1634 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1635 HRESULT hr;
1637 TRACE("iface %p.\n", iface);
1639 wined3d_mutex_lock();
1640 hr = wined3d_device_end_scene(This->wined3d_device);
1641 wined3d_mutex_unlock();
1643 if(hr == WINED3D_OK) return D3D_OK;
1644 else return D3DERR_SCENE_NOT_IN_SCENE;
1647 static HRESULT WINAPI DECLSPEC_HOTPATCH
1648 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1650 return IDirect3DDeviceImpl_7_EndScene(iface);
1653 static HRESULT WINAPI DECLSPEC_HOTPATCH
1654 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1656 HRESULT hr;
1657 WORD old_fpucw;
1659 old_fpucw = d3d_fpu_setup();
1660 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1661 set_fpu_control_word(old_fpucw);
1663 return hr;
1666 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1668 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1669 TRACE("iface %p.\n", iface);
1671 return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
1674 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1676 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1677 TRACE("iface %p.\n", iface);
1679 return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
1682 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1684 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1685 TRACE("iface %p.\n", iface);
1687 return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
1690 /*****************************************************************************
1691 * IDirect3DDevice7::GetDirect3D
1693 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1694 * this device.
1696 * Params:
1697 * Direct3D7: Address to store the interface pointer at
1699 * Returns:
1700 * D3D_OK on success
1701 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1703 *****************************************************************************/
1704 static HRESULT WINAPI
1705 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1706 IDirect3D7 **Direct3D7)
1708 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1710 TRACE("iface %p, d3d %p.\n", iface, Direct3D7);
1712 if(!Direct3D7)
1713 return DDERR_INVALIDPARAMS;
1715 *Direct3D7 = &This->ddraw->IDirect3D7_iface;
1716 IDirect3D7_AddRef(*Direct3D7);
1718 TRACE(" returning interface %p\n", *Direct3D7);
1719 return D3D_OK;
1722 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1723 IDirect3D3 **Direct3D3)
1725 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1727 TRACE("iface %p, d3d %p.\n", iface, Direct3D3);
1729 if(!Direct3D3)
1730 return DDERR_INVALIDPARAMS;
1732 IDirect3D3_AddRef(&This->ddraw->IDirect3D3_iface);
1733 *Direct3D3 = &This->ddraw->IDirect3D3_iface;
1734 TRACE(" returning interface %p\n", *Direct3D3);
1735 return D3D_OK;
1738 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1739 IDirect3D2 **Direct3D2)
1741 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1743 TRACE("iface %p, d3d %p.\n", iface, Direct3D2);
1745 if(!Direct3D2)
1746 return DDERR_INVALIDPARAMS;
1748 IDirect3D2_AddRef(&This->ddraw->IDirect3D2_iface);
1749 *Direct3D2 = &This->ddraw->IDirect3D2_iface;
1750 TRACE(" returning interface %p\n", *Direct3D2);
1751 return D3D_OK;
1754 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1755 IDirect3D **Direct3D)
1757 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1759 TRACE("iface %p, d3d %p.\n", iface, Direct3D);
1761 if(!Direct3D)
1762 return DDERR_INVALIDPARAMS;
1764 IDirect3D_AddRef(&This->ddraw->IDirect3D_iface);
1765 *Direct3D = &This->ddraw->IDirect3D_iface;
1766 TRACE(" returning interface %p\n", *Direct3D);
1767 return D3D_OK;
1770 /*****************************************************************************
1771 * IDirect3DDevice3::SetCurrentViewport
1773 * Sets a Direct3DViewport as the current viewport.
1774 * For the thunks note that all viewport interface versions are equal
1776 * Params:
1777 * Direct3DViewport3: The viewport to set
1779 * Version 2 and 3
1781 * Returns:
1782 * D3D_OK on success
1783 * (Is a NULL viewport valid?)
1785 *****************************************************************************/
1786 static HRESULT WINAPI
1787 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1788 IDirect3DViewport3 *Direct3DViewport3)
1790 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1791 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Direct3DViewport3);
1793 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1795 wined3d_mutex_lock();
1796 /* Do nothing if the specified viewport is the same as the current one */
1797 if (This->current_viewport == vp )
1799 wined3d_mutex_unlock();
1800 return D3D_OK;
1803 if (vp->active_device != This)
1805 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1806 wined3d_mutex_unlock();
1807 return DDERR_INVALIDPARAMS;
1810 /* Release previous viewport and AddRef the new one */
1811 if (This->current_viewport)
1813 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1814 &This->current_viewport->IDirect3DViewport3_iface);
1815 IDirect3DViewport3_Release(&This->current_viewport->IDirect3DViewport3_iface);
1817 IDirect3DViewport3_AddRef(Direct3DViewport3);
1819 /* Set this viewport as the current viewport */
1820 This->current_viewport = vp;
1822 /* Activate this viewport */
1823 viewport_activate(This->current_viewport, FALSE);
1825 wined3d_mutex_unlock();
1827 return D3D_OK;
1830 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1831 IDirect3DViewport2 *Direct3DViewport2)
1833 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1834 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
1836 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1838 return IDirect3DDevice3_SetCurrentViewport(&This->IDirect3DDevice3_iface,
1839 &vp->IDirect3DViewport3_iface);
1842 /*****************************************************************************
1843 * IDirect3DDevice3::GetCurrentViewport
1845 * Returns the currently active viewport.
1847 * Version 2 and 3
1849 * Params:
1850 * Direct3DViewport3: Address to return the interface pointer at
1852 * Returns:
1853 * D3D_OK on success
1854 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1856 *****************************************************************************/
1857 static HRESULT WINAPI
1858 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1859 IDirect3DViewport3 **Direct3DViewport3)
1861 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1863 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1865 if(!Direct3DViewport3)
1866 return DDERR_INVALIDPARAMS;
1868 wined3d_mutex_lock();
1869 *Direct3DViewport3 = &This->current_viewport->IDirect3DViewport3_iface;
1871 /* AddRef the returned viewport */
1872 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1874 TRACE(" returning interface %p\n", *Direct3DViewport3);
1876 wined3d_mutex_unlock();
1878 return D3D_OK;
1881 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1882 IDirect3DViewport2 **Direct3DViewport2)
1884 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1885 HRESULT hr;
1887 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1889 hr = IDirect3DDevice3_GetCurrentViewport(&This->IDirect3DDevice3_iface,
1890 (IDirect3DViewport3 **)Direct3DViewport2);
1891 if(hr != D3D_OK) return hr;
1892 return D3D_OK;
1895 /*****************************************************************************
1896 * IDirect3DDevice7::SetRenderTarget
1898 * Sets the render target for the Direct3DDevice.
1899 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1900 * IDirectDrawSurface3 == IDirectDrawSurface
1902 * Version 2, 3 and 7
1904 * Params:
1905 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1906 * render target
1907 * Flags: Some flags
1909 * Returns:
1910 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1912 *****************************************************************************/
1913 static HRESULT d3d_device_set_render_target(IDirect3DDeviceImpl *This, struct ddraw_surface *target)
1915 HRESULT hr;
1917 wined3d_mutex_lock();
1919 if (This->target == target)
1921 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1922 wined3d_mutex_unlock();
1923 return D3D_OK;
1925 This->target = target;
1926 hr = wined3d_device_set_render_target(This->wined3d_device, 0,
1927 target ? target->wined3d_surface : NULL, FALSE);
1928 if(hr != D3D_OK)
1930 wined3d_mutex_unlock();
1931 return hr;
1933 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1935 wined3d_mutex_unlock();
1937 return D3D_OK;
1940 static HRESULT
1941 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1942 IDirectDrawSurface7 *NewTarget,
1943 DWORD Flags)
1945 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1946 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface7(NewTarget);
1948 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, Flags);
1949 /* Flags: Not used */
1951 IDirectDrawSurface7_AddRef(NewTarget);
1952 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
1953 return d3d_device_set_render_target(This, target);
1956 static HRESULT WINAPI
1957 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1958 IDirectDrawSurface7 *NewTarget,
1959 DWORD Flags)
1961 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1964 static HRESULT WINAPI
1965 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1966 IDirectDrawSurface7 *NewTarget,
1967 DWORD Flags)
1969 HRESULT hr;
1970 WORD old_fpucw;
1972 old_fpucw = d3d_fpu_setup();
1973 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1974 set_fpu_control_word(old_fpucw);
1976 return hr;
1979 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
1980 IDirectDrawSurface4 *NewRenderTarget, DWORD Flags)
1982 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1983 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface4(NewRenderTarget);
1985 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1987 IDirectDrawSurface4_AddRef(NewRenderTarget);
1988 IDirectDrawSurface4_Release(&This->target->IDirectDrawSurface4_iface);
1989 return d3d_device_set_render_target(This, target);
1992 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
1993 IDirectDrawSurface *NewRenderTarget, DWORD Flags)
1995 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1996 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface(NewRenderTarget);
1998 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
2000 IDirectDrawSurface_AddRef(NewRenderTarget);
2001 IDirectDrawSurface_Release(&This->target->IDirectDrawSurface_iface);
2002 return d3d_device_set_render_target(This, target);
2005 /*****************************************************************************
2006 * IDirect3DDevice7::GetRenderTarget
2008 * Returns the current render target.
2009 * This is handled locally, because the WineD3D render target's parent
2010 * is an IParent
2012 * Version 2, 3 and 7
2014 * Params:
2015 * RenderTarget: Address to store the surface interface pointer
2017 * Returns:
2018 * D3D_OK on success
2019 * DDERR_INVALIDPARAMS if RenderTarget == NULL
2021 *****************************************************************************/
2022 static HRESULT WINAPI
2023 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
2024 IDirectDrawSurface7 **RenderTarget)
2026 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
2028 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2030 if(!RenderTarget)
2031 return DDERR_INVALIDPARAMS;
2033 wined3d_mutex_lock();
2034 *RenderTarget = &This->target->IDirectDrawSurface7_iface;
2035 IDirectDrawSurface7_AddRef(*RenderTarget);
2036 wined3d_mutex_unlock();
2038 return D3D_OK;
2041 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
2042 IDirectDrawSurface4 **RenderTarget)
2044 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2045 IDirectDrawSurface7 *RenderTarget7;
2046 struct ddraw_surface *RenderTargetImpl;
2047 HRESULT hr;
2049 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2051 if(!RenderTarget)
2052 return DDERR_INVALIDPARAMS;
2054 hr = IDirect3DDevice7_GetRenderTarget(&This->IDirect3DDevice7_iface, &RenderTarget7);
2055 if(hr != D3D_OK) return hr;
2056 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2057 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface;
2058 IDirectDrawSurface4_AddRef(*RenderTarget);
2059 IDirectDrawSurface7_Release(RenderTarget7);
2060 return D3D_OK;
2063 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
2064 IDirectDrawSurface **RenderTarget)
2066 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2067 IDirectDrawSurface7 *RenderTarget7;
2068 struct ddraw_surface *RenderTargetImpl;
2069 HRESULT hr;
2071 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2073 if(!RenderTarget)
2074 return DDERR_INVALIDPARAMS;
2076 hr = IDirect3DDevice7_GetRenderTarget(&This->IDirect3DDevice7_iface, &RenderTarget7);
2077 if(hr != D3D_OK) return hr;
2078 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2079 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
2080 IDirectDrawSurface_AddRef(*RenderTarget);
2081 IDirectDrawSurface7_Release(RenderTarget7);
2082 return D3D_OK;
2085 /*****************************************************************************
2086 * IDirect3DDevice3::Begin
2088 * Begins a description block of vertices. This is similar to glBegin()
2089 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2090 * described with IDirect3DDevice::Vertex are drawn.
2092 * Version 2 and 3
2094 * Params:
2095 * PrimitiveType: The type of primitives to draw
2096 * VertexTypeDesc: A flexible vertex format description of the vertices
2097 * Flags: Some flags..
2099 * Returns:
2100 * D3D_OK on success
2102 *****************************************************************************/
2103 static HRESULT WINAPI
2104 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2105 D3DPRIMITIVETYPE PrimitiveType,
2106 DWORD VertexTypeDesc,
2107 DWORD Flags)
2109 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2111 TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
2112 iface, PrimitiveType, VertexTypeDesc, Flags);
2114 wined3d_mutex_lock();
2115 This->primitive_type = PrimitiveType;
2116 This->vertex_type = VertexTypeDesc;
2117 This->render_flags = Flags;
2118 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2119 This->nb_vertices = 0;
2120 wined3d_mutex_unlock();
2122 return D3D_OK;
2125 static HRESULT WINAPI IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface, D3DPRIMITIVETYPE d3dpt,
2126 D3DVERTEXTYPE dwVertexTypeDesc, DWORD dwFlags)
2128 DWORD FVF;
2129 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2131 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2132 iface, d3dpt, dwVertexTypeDesc, dwFlags);
2134 switch(dwVertexTypeDesc)
2136 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2137 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2138 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2139 default:
2140 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2141 return DDERR_INVALIDPARAMS; /* Should never happen */
2144 return IDirect3DDevice3_Begin(&This->IDirect3DDevice3_iface, d3dpt, FVF, dwFlags);
2147 /*****************************************************************************
2148 * IDirect3DDevice3::BeginIndexed
2150 * Draws primitives based on vertices in a vertex array which are specified
2151 * by indices.
2153 * Version 2 and 3
2155 * Params:
2156 * PrimitiveType: Primitive type to draw
2157 * VertexType: A FVF description of the vertex format
2158 * Vertices: pointer to an array containing the vertices
2159 * NumVertices: The number of vertices in the vertex array
2160 * Flags: Some flags ...
2162 * Returns:
2163 * D3D_OK, because it's a stub
2165 *****************************************************************************/
2166 static HRESULT WINAPI
2167 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2168 D3DPRIMITIVETYPE PrimitiveType,
2169 DWORD VertexType,
2170 void *Vertices,
2171 DWORD NumVertices,
2172 DWORD Flags)
2174 FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2175 iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2177 return D3D_OK;
2181 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2182 D3DPRIMITIVETYPE d3dptPrimitiveType, D3DVERTEXTYPE d3dvtVertexType,
2183 void *lpvVertices, DWORD dwNumVertices, DWORD dwFlags)
2185 DWORD FVF;
2186 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2188 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2189 iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2191 switch(d3dvtVertexType)
2193 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2194 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2195 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2196 default:
2197 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2198 return DDERR_INVALIDPARAMS; /* Should never happen */
2201 return IDirect3DDevice3_BeginIndexed(&This->IDirect3DDevice3_iface,
2202 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2205 /*****************************************************************************
2206 * IDirect3DDevice3::Vertex
2208 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2209 * drawn vertices in a vertex buffer. If the buffer is too small, its
2210 * size is increased.
2212 * Version 2 and 3
2214 * Params:
2215 * Vertex: Pointer to the vertex
2217 * Returns:
2218 * D3D_OK, on success
2219 * DDERR_INVALIDPARAMS if Vertex is NULL
2221 *****************************************************************************/
2222 static HRESULT WINAPI
2223 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2224 void *Vertex)
2226 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2228 TRACE("iface %p, vertex %p.\n", iface, Vertex);
2230 if(!Vertex)
2231 return DDERR_INVALIDPARAMS;
2233 wined3d_mutex_lock();
2234 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2236 BYTE *old_buffer;
2237 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2238 old_buffer = This->vertex_buffer;
2239 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2240 if (old_buffer)
2242 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2243 HeapFree(GetProcessHeap(), 0, old_buffer);
2247 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2248 wined3d_mutex_unlock();
2250 return D3D_OK;
2253 static HRESULT WINAPI IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface, void *lpVertexType)
2255 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2257 TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
2259 return IDirect3DDevice3_Vertex(&This->IDirect3DDevice3_iface, lpVertexType);
2262 /*****************************************************************************
2263 * IDirect3DDevice3::Index
2265 * Specifies an index to a vertex to be drawn. The vertex array has to
2266 * be specified with BeginIndexed first.
2268 * Parameters:
2269 * VertexIndex: The index of the vertex to draw
2271 * Returns:
2272 * D3D_OK because it's a stub
2274 *****************************************************************************/
2275 static HRESULT WINAPI
2276 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2277 WORD VertexIndex)
2279 FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
2281 return D3D_OK;
2284 static HRESULT WINAPI IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface, WORD wVertexIndex)
2286 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2288 TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
2290 return IDirect3DDevice3_Index(&This->IDirect3DDevice3_iface, wVertexIndex);
2293 /*****************************************************************************
2294 * IDirect3DDevice3::End
2296 * Ends a draw begun with IDirect3DDevice3::Begin or
2297 * IDirect3DDevice::BeginIndexed. The vertices specified with
2298 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2299 * the IDirect3DDevice7::DrawPrimitive method. So far only
2300 * non-indexed mode is supported
2302 * Version 2 and 3
2304 * Params:
2305 * Flags: Some flags, as usual. Don't know which are defined
2307 * Returns:
2308 * The return value of IDirect3DDevice7::DrawPrimitive
2310 *****************************************************************************/
2311 static HRESULT WINAPI
2312 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2313 DWORD Flags)
2315 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2317 TRACE("iface %p, flags %#x.\n", iface, Flags);
2319 return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface, This->primitive_type,
2320 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2323 static HRESULT WINAPI IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface, DWORD dwFlags)
2325 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2327 TRACE("iface %p, flags %#x.\n", iface, dwFlags);
2329 return IDirect3DDevice3_End(&This->IDirect3DDevice3_iface, dwFlags);
2332 /*****************************************************************************
2333 * IDirect3DDevice7::GetRenderState
2335 * Returns the value of a render state. The possible render states are
2336 * defined in include/d3dtypes.h
2338 * Version 2, 3 and 7
2340 * Params:
2341 * RenderStateType: Render state to return the current setting of
2342 * Value: Address to store the value at
2344 * Returns:
2345 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2346 * DDERR_INVALIDPARAMS if Value == NULL
2348 *****************************************************************************/
2349 static HRESULT IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2350 D3DRENDERSTATETYPE RenderStateType, DWORD *Value)
2352 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
2353 HRESULT hr;
2355 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2357 if(!Value)
2358 return DDERR_INVALIDPARAMS;
2360 wined3d_mutex_lock();
2361 switch(RenderStateType)
2363 case D3DRENDERSTATE_TEXTUREMAG:
2365 enum wined3d_texture_filter_type tex_mag;
2367 hr = wined3d_device_get_sampler_state(This->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, &tex_mag);
2369 switch (tex_mag)
2371 case WINED3D_TEXF_POINT:
2372 *Value = D3DFILTER_NEAREST;
2373 break;
2374 case WINED3D_TEXF_LINEAR:
2375 *Value = D3DFILTER_LINEAR;
2376 break;
2377 default:
2378 ERR("Unhandled texture mag %d !\n",tex_mag);
2379 *Value = 0;
2381 break;
2384 case D3DRENDERSTATE_TEXTUREMIN:
2386 enum wined3d_texture_filter_type tex_min;
2387 enum wined3d_texture_filter_type tex_mip;
2389 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2390 0, WINED3D_SAMP_MIN_FILTER, &tex_min);
2391 if (FAILED(hr))
2393 wined3d_mutex_unlock();
2394 return hr;
2396 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2397 0, WINED3D_SAMP_MIP_FILTER, &tex_mip);
2399 switch (tex_min)
2401 case WINED3D_TEXF_POINT:
2402 switch (tex_mip)
2404 case WINED3D_TEXF_NONE:
2405 *Value = D3DFILTER_NEAREST;
2406 break;
2407 case WINED3D_TEXF_POINT:
2408 *Value = D3DFILTER_MIPNEAREST;
2409 break;
2410 case WINED3D_TEXF_LINEAR:
2411 *Value = D3DFILTER_LINEARMIPNEAREST;
2412 break;
2413 default:
2414 ERR("Unhandled mip filter %#x.\n", tex_mip);
2415 *Value = D3DFILTER_NEAREST;
2416 break;
2418 break;
2419 case WINED3D_TEXF_LINEAR:
2420 switch (tex_mip)
2422 case WINED3D_TEXF_NONE:
2423 *Value = D3DFILTER_LINEAR;
2424 break;
2425 case WINED3D_TEXF_POINT:
2426 *Value = D3DFILTER_MIPLINEAR;
2427 break;
2428 case WINED3D_TEXF_LINEAR:
2429 *Value = D3DFILTER_LINEARMIPLINEAR;
2430 break;
2431 default:
2432 ERR("Unhandled mip filter %#x.\n", tex_mip);
2433 *Value = D3DFILTER_LINEAR;
2434 break;
2436 break;
2437 default:
2438 ERR("Unhandled texture min filter %#x.\n",tex_min);
2439 *Value = D3DFILTER_NEAREST;
2440 break;
2442 break;
2445 case D3DRENDERSTATE_TEXTUREADDRESS:
2446 case D3DRENDERSTATE_TEXTUREADDRESSU:
2447 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2448 0, WINED3D_SAMP_ADDRESS_U, Value);
2449 break;
2450 case D3DRENDERSTATE_TEXTUREADDRESSV:
2451 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2452 0, WINED3D_SAMP_ADDRESS_V, Value);
2453 break;
2455 case D3DRENDERSTATE_BORDERCOLOR:
2456 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2457 hr = E_NOTIMPL;
2458 break;
2460 case D3DRENDERSTATE_TEXTUREHANDLE:
2461 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2462 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2463 hr = DDERR_INVALIDPARAMS;
2464 break;
2466 case D3DRENDERSTATE_ZBIAS:
2467 hr = wined3d_device_get_render_state(This->wined3d_device, WINED3D_RS_DEPTHBIAS, Value);
2468 break;
2470 default:
2471 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2472 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2474 FIXME("Unhandled stipple pattern render state (%#x).\n",
2475 RenderStateType);
2476 hr = E_NOTIMPL;
2477 break;
2479 hr = wined3d_device_get_render_state(This->wined3d_device, RenderStateType, Value);
2481 wined3d_mutex_unlock();
2483 return hr;
2486 static HRESULT WINAPI
2487 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2488 D3DRENDERSTATETYPE RenderStateType,
2489 DWORD *Value)
2491 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2494 static HRESULT WINAPI
2495 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2496 D3DRENDERSTATETYPE RenderStateType,
2497 DWORD *Value)
2499 HRESULT hr;
2500 WORD old_fpucw;
2502 old_fpucw = d3d_fpu_setup();
2503 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2504 set_fpu_control_word(old_fpucw);
2506 return hr;
2509 static HRESULT WINAPI
2510 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2511 D3DRENDERSTATETYPE dwRenderStateType,
2512 DWORD *lpdwRenderState)
2514 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2515 HRESULT hr;
2517 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2519 switch(dwRenderStateType)
2521 case D3DRENDERSTATE_TEXTUREHANDLE:
2523 /* This state is wrapped to SetTexture in SetRenderState, so
2524 * it has to be wrapped to GetTexture here. */
2525 struct wined3d_texture *tex = NULL;
2526 *lpdwRenderState = 0;
2528 wined3d_mutex_lock();
2529 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2530 if (SUCCEEDED(hr) && tex)
2532 /* The parent of the texture is the IDirectDrawSurface7
2533 * interface of the ddraw surface. */
2534 struct ddraw_surface *parent = wined3d_texture_get_parent(tex);
2535 if (parent) *lpdwRenderState = parent->Handle;
2536 wined3d_texture_decref(tex);
2538 wined3d_mutex_unlock();
2540 return hr;
2543 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2545 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2546 the mapping to get the value. */
2547 DWORD colorop, colorarg1, colorarg2;
2548 DWORD alphaop, alphaarg1, alphaarg2;
2550 wined3d_mutex_lock();
2552 This->legacyTextureBlending = TRUE;
2554 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_COLOR_OP, &colorop);
2555 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_COLOR_ARG1, &colorarg1);
2556 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_COLOR_ARG2, &colorarg2);
2557 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_ALPHA_OP, &alphaop);
2558 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG1, &alphaarg1);
2559 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG2, &alphaarg2);
2561 if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2562 && alphaop == WINED3D_TOP_SELECT_ARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2563 *lpdwRenderState = D3DTBLEND_DECAL;
2564 else if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2565 && alphaop == WINED3D_TOP_MODULATE
2566 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2567 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2568 else if (colorop == WINED3D_TOP_MODULATE
2569 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2570 && alphaop == WINED3D_TOP_MODULATE
2571 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2572 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2573 else
2575 struct wined3d_texture *tex = NULL;
2576 HRESULT hr;
2577 BOOL tex_alpha = FALSE;
2578 DDPIXELFORMAT ddfmt;
2580 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2582 if(hr == WINED3D_OK && tex)
2584 struct wined3d_resource *sub_resource;
2586 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2588 struct wined3d_resource_desc desc;
2590 wined3d_resource_get_desc(sub_resource, &desc);
2591 ddfmt.dwSize = sizeof(ddfmt);
2592 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2593 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2596 wined3d_texture_decref(tex);
2599 if (!(colorop == WINED3D_TOP_MODULATE
2600 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2601 && alphaop == (tex_alpha ? WINED3D_TOP_SELECT_ARG1 : WINED3D_TOP_SELECT_ARG2)
2602 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2603 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous.\n");
2605 *lpdwRenderState = D3DTBLEND_MODULATE;
2608 wined3d_mutex_unlock();
2610 return D3D_OK;
2613 default:
2614 return IDirect3DDevice7_GetRenderState(&This->IDirect3DDevice7_iface, dwRenderStateType, lpdwRenderState);
2618 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2619 D3DRENDERSTATETYPE dwRenderStateType, DWORD *lpdwRenderState)
2621 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2623 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2625 return IDirect3DDevice3_GetRenderState(&This->IDirect3DDevice3_iface,
2626 dwRenderStateType, lpdwRenderState);
2629 /*****************************************************************************
2630 * IDirect3DDevice7::SetRenderState
2632 * Sets a render state. The possible render states are defined in
2633 * include/d3dtypes.h
2635 * Version 2, 3 and 7
2637 * Params:
2638 * RenderStateType: State to set
2639 * Value: Value to assign to that state
2641 * Returns:
2642 * D3D_OK on success,
2643 * for details see IWineD3DDevice::SetRenderState
2645 *****************************************************************************/
2646 static HRESULT
2647 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2648 D3DRENDERSTATETYPE RenderStateType,
2649 DWORD Value)
2651 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
2652 HRESULT hr;
2654 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2656 wined3d_mutex_lock();
2657 /* Some render states need special care */
2658 switch(RenderStateType)
2661 * The ddraw texture filter mapping works like this:
2662 * D3DFILTER_NEAREST Point min/mag, no mip
2663 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2664 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2666 * D3DFILTER_LINEAR Linear min/mag, no mip
2667 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2668 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2670 * This is the opposite of the GL naming convention,
2671 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2673 case D3DRENDERSTATE_TEXTUREMAG:
2675 enum wined3d_texture_filter_type tex_mag;
2677 switch (Value)
2679 case D3DFILTER_NEAREST:
2680 case D3DFILTER_MIPNEAREST:
2681 case D3DFILTER_LINEARMIPNEAREST:
2682 tex_mag = WINED3D_TEXF_POINT;
2683 break;
2684 case D3DFILTER_LINEAR:
2685 case D3DFILTER_MIPLINEAR:
2686 case D3DFILTER_LINEARMIPLINEAR:
2687 tex_mag = WINED3D_TEXF_LINEAR;
2688 break;
2689 default:
2690 tex_mag = WINED3D_TEXF_POINT;
2691 ERR("Unhandled texture mag %d !\n",Value);
2692 break;
2695 hr = wined3d_device_set_sampler_state(This->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, tex_mag);
2696 break;
2699 case D3DRENDERSTATE_TEXTUREMIN:
2701 enum wined3d_texture_filter_type tex_min;
2702 enum wined3d_texture_filter_type tex_mip;
2704 switch ((D3DTEXTUREFILTER)Value)
2706 case D3DFILTER_NEAREST:
2707 tex_min = WINED3D_TEXF_POINT;
2708 tex_mip = WINED3D_TEXF_NONE;
2709 break;
2710 case D3DFILTER_LINEAR:
2711 tex_min = WINED3D_TEXF_LINEAR;
2712 tex_mip = WINED3D_TEXF_NONE;
2713 break;
2714 case D3DFILTER_MIPNEAREST:
2715 tex_min = WINED3D_TEXF_POINT;
2716 tex_mip = WINED3D_TEXF_POINT;
2717 break;
2718 case D3DFILTER_MIPLINEAR:
2719 tex_min = WINED3D_TEXF_LINEAR;
2720 tex_mip = WINED3D_TEXF_POINT;
2721 break;
2722 case D3DFILTER_LINEARMIPNEAREST:
2723 tex_min = WINED3D_TEXF_POINT;
2724 tex_mip = WINED3D_TEXF_LINEAR;
2725 break;
2726 case D3DFILTER_LINEARMIPLINEAR:
2727 tex_min = WINED3D_TEXF_LINEAR;
2728 tex_mip = WINED3D_TEXF_LINEAR;
2729 break;
2731 default:
2732 ERR("Unhandled texture min %d !\n",Value);
2733 tex_min = WINED3D_TEXF_POINT;
2734 tex_mip = WINED3D_TEXF_NONE;
2735 break;
2738 wined3d_device_set_sampler_state(This->wined3d_device,
2739 0, WINED3D_SAMP_MIP_FILTER, tex_mip);
2740 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2741 0, WINED3D_SAMP_MIN_FILTER, tex_min);
2742 break;
2745 case D3DRENDERSTATE_TEXTUREADDRESS:
2746 wined3d_device_set_sampler_state(This->wined3d_device,
2747 0, WINED3D_SAMP_ADDRESS_V, Value);
2748 /* Drop through */
2749 case D3DRENDERSTATE_TEXTUREADDRESSU:
2750 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2751 0, WINED3D_SAMP_ADDRESS_U, Value);
2752 break;
2753 case D3DRENDERSTATE_TEXTUREADDRESSV:
2754 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2755 0, WINED3D_SAMP_ADDRESS_V, Value);
2756 break;
2758 case D3DRENDERSTATE_BORDERCOLOR:
2759 /* This should probably just forward to the corresponding sampler
2760 * state. Needs tests. */
2761 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2762 hr = E_NOTIMPL;
2763 break;
2765 case D3DRENDERSTATE_TEXTUREHANDLE:
2766 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2767 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2768 hr = DDERR_INVALIDPARAMS;
2769 break;
2771 case D3DRENDERSTATE_ZBIAS:
2772 hr = wined3d_device_set_render_state(This->wined3d_device, WINED3D_RS_DEPTHBIAS, Value);
2773 break;
2775 default:
2776 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2777 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2779 FIXME("Unhandled stipple pattern render state (%#x).\n",
2780 RenderStateType);
2781 hr = E_NOTIMPL;
2782 break;
2785 hr = wined3d_device_set_render_state(This->wined3d_device, RenderStateType, Value);
2786 break;
2788 wined3d_mutex_unlock();
2790 return hr;
2793 static HRESULT WINAPI
2794 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2795 D3DRENDERSTATETYPE RenderStateType,
2796 DWORD Value)
2798 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2801 static HRESULT WINAPI
2802 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2803 D3DRENDERSTATETYPE RenderStateType,
2804 DWORD Value)
2806 HRESULT hr;
2807 WORD old_fpucw;
2809 old_fpucw = d3d_fpu_setup();
2810 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2811 set_fpu_control_word(old_fpucw);
2813 return hr;
2816 static HRESULT WINAPI
2817 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2818 D3DRENDERSTATETYPE RenderStateType,
2819 DWORD Value)
2821 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2822 for this state can be directly mapped to texture stage colorop and alphaop, but
2823 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2824 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2825 alphaarg when needed.
2827 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2829 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2830 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2831 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2832 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2833 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2834 in device - TRUE if the app is using TEXTUREMAPBLEND.
2836 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2837 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2838 unless some broken game will be found that cares. */
2840 HRESULT hr;
2841 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2843 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2845 wined3d_mutex_lock();
2847 switch(RenderStateType)
2849 case D3DRENDERSTATE_TEXTUREHANDLE:
2851 struct ddraw_surface *surf;
2853 if(Value == 0)
2855 hr = wined3d_device_set_texture(This->wined3d_device, 0, NULL);
2856 break;
2859 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2860 if (!surf)
2862 WARN("Invalid texture handle.\n");
2863 hr = DDERR_INVALIDPARAMS;
2864 break;
2867 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2868 break;
2871 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2873 This->legacyTextureBlending = TRUE;
2875 switch ( (D3DTEXTUREBLEND) Value)
2877 case D3DTBLEND_MODULATE:
2879 struct wined3d_texture *tex = NULL;
2880 BOOL tex_alpha = FALSE;
2881 DDPIXELFORMAT ddfmt;
2883 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2885 if(hr == WINED3D_OK && tex)
2887 struct wined3d_resource *sub_resource;
2889 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2891 struct wined3d_resource_desc desc;
2893 wined3d_resource_get_desc(sub_resource, &desc);
2894 ddfmt.dwSize = sizeof(ddfmt);
2895 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2896 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2899 wined3d_texture_decref(tex);
2902 if (tex_alpha)
2903 wined3d_device_set_texture_stage_state(This->wined3d_device,
2904 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2905 else
2906 wined3d_device_set_texture_stage_state(This->wined3d_device,
2907 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2908 wined3d_device_set_texture_stage_state(This->wined3d_device,
2909 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2910 wined3d_device_set_texture_stage_state(This->wined3d_device,
2911 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2912 wined3d_device_set_texture_stage_state(This->wined3d_device,
2913 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2914 wined3d_device_set_texture_stage_state(This->wined3d_device,
2915 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2916 wined3d_device_set_texture_stage_state(This->wined3d_device,
2917 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2918 break;
2921 case D3DTBLEND_ADD:
2922 wined3d_device_set_texture_stage_state(This->wined3d_device,
2923 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_ADD);
2924 wined3d_device_set_texture_stage_state(This->wined3d_device,
2925 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2926 wined3d_device_set_texture_stage_state(This->wined3d_device,
2927 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2928 wined3d_device_set_texture_stage_state(This->wined3d_device,
2929 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2930 wined3d_device_set_texture_stage_state(This->wined3d_device,
2931 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2932 break;
2934 case D3DTBLEND_MODULATEALPHA:
2935 wined3d_device_set_texture_stage_state(This->wined3d_device,
2936 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2937 wined3d_device_set_texture_stage_state(This->wined3d_device,
2938 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2939 wined3d_device_set_texture_stage_state(This->wined3d_device,
2940 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2941 wined3d_device_set_texture_stage_state(This->wined3d_device,
2942 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2943 wined3d_device_set_texture_stage_state(This->wined3d_device,
2944 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2945 wined3d_device_set_texture_stage_state(This->wined3d_device,
2946 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_MODULATE);
2947 break;
2949 case D3DTBLEND_COPY:
2950 case D3DTBLEND_DECAL:
2951 wined3d_device_set_texture_stage_state(This->wined3d_device,
2952 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2953 wined3d_device_set_texture_stage_state(This->wined3d_device,
2954 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2955 wined3d_device_set_texture_stage_state(This->wined3d_device,
2956 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_SELECT_ARG1);
2957 wined3d_device_set_texture_stage_state(This->wined3d_device,
2958 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2959 break;
2961 case D3DTBLEND_DECALALPHA:
2962 wined3d_device_set_texture_stage_state(This->wined3d_device,
2963 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_BLEND_TEXTURE_ALPHA);
2964 wined3d_device_set_texture_stage_state(This->wined3d_device,
2965 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2966 wined3d_device_set_texture_stage_state(This->wined3d_device,
2967 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2968 wined3d_device_set_texture_stage_state(This->wined3d_device,
2969 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2970 wined3d_device_set_texture_stage_state(This->wined3d_device,
2971 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2972 break;
2974 default:
2975 ERR("Unhandled texture environment %d !\n",Value);
2978 hr = D3D_OK;
2979 break;
2982 default:
2983 hr = IDirect3DDevice7_SetRenderState(&This->IDirect3DDevice7_iface, RenderStateType, Value);
2984 break;
2986 wined3d_mutex_unlock();
2988 return hr;
2991 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2992 D3DRENDERSTATETYPE RenderStateType, DWORD Value)
2994 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2996 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2998 return IDirect3DDevice3_SetRenderState(&This->IDirect3DDevice3_iface, RenderStateType, Value);
3001 /*****************************************************************************
3002 * Direct3DDevice3::SetLightState
3004 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
3005 * light states are forwarded to Direct3DDevice7 render states
3007 * Version 2 and 3
3009 * Params:
3010 * LightStateType: The light state to change
3011 * Value: The value to assign to that light state
3013 * Returns:
3014 * D3D_OK on success
3015 * DDERR_INVALIDPARAMS if the parameters were incorrect
3016 * Also check IDirect3DDevice7::SetRenderState
3018 *****************************************************************************/
3019 static HRESULT WINAPI
3020 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
3021 D3DLIGHTSTATETYPE LightStateType,
3022 DWORD Value)
3024 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3025 HRESULT hr;
3027 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3029 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3031 TRACE("Unexpected Light State Type\n");
3032 return DDERR_INVALIDPARAMS;
3035 wined3d_mutex_lock();
3036 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3038 struct d3d_material *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
3039 if (!m)
3041 WARN("Invalid material handle.\n");
3042 wined3d_mutex_unlock();
3043 return DDERR_INVALIDPARAMS;
3046 TRACE(" activating material %p.\n", m);
3047 material_activate(m);
3049 This->material = Value;
3051 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3053 switch (Value)
3055 case D3DCOLOR_MONO:
3056 ERR("DDCOLOR_MONO should not happen!\n");
3057 break;
3058 case D3DCOLOR_RGB:
3059 /* We are already in this mode */
3060 TRACE("Setting color model to RGB (no-op).\n");
3061 break;
3062 default:
3063 ERR("Unknown color model!\n");
3064 wined3d_mutex_unlock();
3065 return DDERR_INVALIDPARAMS;
3068 else
3070 D3DRENDERSTATETYPE rs;
3071 switch (LightStateType)
3073 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3074 rs = D3DRENDERSTATE_AMBIENT;
3075 break;
3076 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3077 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3078 break;
3079 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3080 rs = D3DRENDERSTATE_FOGSTART;
3081 break;
3082 case D3DLIGHTSTATE_FOGEND: /* 6 */
3083 rs = D3DRENDERSTATE_FOGEND;
3084 break;
3085 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3086 rs = D3DRENDERSTATE_FOGDENSITY;
3087 break;
3088 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3089 rs = D3DRENDERSTATE_COLORVERTEX;
3090 break;
3091 default:
3092 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3093 wined3d_mutex_unlock();
3094 return DDERR_INVALIDPARAMS;
3097 hr = IDirect3DDevice7_SetRenderState(&This->IDirect3DDevice7_iface, rs, Value);
3098 wined3d_mutex_unlock();
3099 return hr;
3101 wined3d_mutex_unlock();
3103 return D3D_OK;
3106 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3107 D3DLIGHTSTATETYPE LightStateType, DWORD Value)
3109 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3111 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3113 return IDirect3DDevice3_SetLightState(&This->IDirect3DDevice3_iface, LightStateType, Value);
3116 /*****************************************************************************
3117 * IDirect3DDevice3::GetLightState
3119 * Returns the current setting of a light state. The state is read from
3120 * the Direct3DDevice7 render state.
3122 * Version 2 and 3
3124 * Params:
3125 * LightStateType: The light state to return
3126 * Value: The address to store the light state setting at
3128 * Returns:
3129 * D3D_OK on success
3130 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3131 * Also see IDirect3DDevice7::GetRenderState
3133 *****************************************************************************/
3134 static HRESULT WINAPI
3135 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3136 D3DLIGHTSTATETYPE LightStateType,
3137 DWORD *Value)
3139 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3140 HRESULT hr;
3142 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3144 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3146 TRACE("Unexpected Light State Type\n");
3147 return DDERR_INVALIDPARAMS;
3150 if(!Value)
3151 return DDERR_INVALIDPARAMS;
3153 wined3d_mutex_lock();
3154 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3156 *Value = This->material;
3158 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3160 *Value = D3DCOLOR_RGB;
3162 else
3164 D3DRENDERSTATETYPE rs;
3165 switch (LightStateType)
3167 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3168 rs = D3DRENDERSTATE_AMBIENT;
3169 break;
3170 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3171 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3172 break;
3173 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3174 rs = D3DRENDERSTATE_FOGSTART;
3175 break;
3176 case D3DLIGHTSTATE_FOGEND: /* 6 */
3177 rs = D3DRENDERSTATE_FOGEND;
3178 break;
3179 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3180 rs = D3DRENDERSTATE_FOGDENSITY;
3181 break;
3182 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3183 rs = D3DRENDERSTATE_COLORVERTEX;
3184 break;
3185 default:
3186 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3187 wined3d_mutex_unlock();
3188 return DDERR_INVALIDPARAMS;
3191 hr = IDirect3DDevice7_GetRenderState(&This->IDirect3DDevice7_iface, rs, Value);
3192 wined3d_mutex_unlock();
3193 return hr;
3195 wined3d_mutex_unlock();
3197 return D3D_OK;
3200 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3201 D3DLIGHTSTATETYPE LightStateType, DWORD *Value)
3203 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3205 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3207 return IDirect3DDevice3_GetLightState(&This->IDirect3DDevice3_iface, LightStateType, Value);
3210 /*****************************************************************************
3211 * IDirect3DDevice7::SetTransform
3213 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3214 * in include/d3dtypes.h.
3215 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3216 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3217 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3219 * Version 2, 3 and 7
3221 * Params:
3222 * TransformStateType: transform state to set
3223 * Matrix: Matrix to assign to the state
3225 * Returns:
3226 * D3D_OK on success
3227 * DDERR_INVALIDPARAMS if Matrix == NULL
3228 * For details see IWineD3DDevice::SetTransform
3230 *****************************************************************************/
3231 static HRESULT
3232 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3233 D3DTRANSFORMSTATETYPE TransformStateType,
3234 D3DMATRIX *Matrix)
3236 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3237 D3DTRANSFORMSTATETYPE type;
3238 HRESULT hr;
3240 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3242 switch (TransformStateType)
3244 case D3DTRANSFORMSTATE_WORLD:
3245 type = WINED3D_TS_WORLD_MATRIX(0);
3246 break;
3247 case D3DTRANSFORMSTATE_WORLD1:
3248 type = WINED3D_TS_WORLD_MATRIX(1);
3249 break;
3250 case D3DTRANSFORMSTATE_WORLD2:
3251 type = WINED3D_TS_WORLD_MATRIX(2);
3252 break;
3253 case D3DTRANSFORMSTATE_WORLD3:
3254 type = WINED3D_TS_WORLD_MATRIX(3);
3255 break;
3256 default:
3257 type = TransformStateType;
3260 if (!Matrix)
3261 return DDERR_INVALIDPARAMS;
3263 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3264 wined3d_mutex_lock();
3265 hr = wined3d_device_set_transform(This->wined3d_device, type, (struct wined3d_matrix *)Matrix);
3266 wined3d_mutex_unlock();
3268 return hr;
3271 static HRESULT WINAPI
3272 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3273 D3DTRANSFORMSTATETYPE TransformStateType,
3274 D3DMATRIX *Matrix)
3276 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3279 static HRESULT WINAPI
3280 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3281 D3DTRANSFORMSTATETYPE TransformStateType,
3282 D3DMATRIX *Matrix)
3284 HRESULT hr;
3285 WORD old_fpucw;
3287 old_fpucw = d3d_fpu_setup();
3288 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3289 set_fpu_control_word(old_fpucw);
3291 return hr;
3294 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3295 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3297 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3299 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3301 if (!matrix)
3302 return DDERR_INVALIDPARAMS;
3304 if (state == D3DTRANSFORMSTATE_PROJECTION)
3306 D3DMATRIX projection;
3307 HRESULT hr;
3309 wined3d_mutex_lock();
3310 multiply_matrix(&projection, &This->legacy_clipspace, matrix);
3311 hr = wined3d_device_set_transform(This->wined3d_device,
3312 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3313 if (SUCCEEDED(hr))
3314 This->legacy_projection = *matrix;
3315 wined3d_mutex_unlock();
3317 return hr;
3320 return IDirect3DDevice7_SetTransform(&This->IDirect3DDevice7_iface, state, matrix);
3323 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3324 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3326 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3328 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3330 return IDirect3DDevice7_SetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3333 /*****************************************************************************
3334 * IDirect3DDevice7::GetTransform
3336 * Returns the matrix assigned to a transform state
3337 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3338 * SetTransform
3340 * Params:
3341 * TransformStateType: State to read the matrix from
3342 * Matrix: Address to store the matrix at
3344 * Returns:
3345 * D3D_OK on success
3346 * DDERR_INVALIDPARAMS if Matrix == NULL
3347 * For details, see IWineD3DDevice::GetTransform
3349 *****************************************************************************/
3350 static HRESULT
3351 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3352 D3DTRANSFORMSTATETYPE TransformStateType,
3353 D3DMATRIX *Matrix)
3355 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3356 D3DTRANSFORMSTATETYPE type;
3357 HRESULT hr;
3359 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3361 switch(TransformStateType)
3363 case D3DTRANSFORMSTATE_WORLD:
3364 type = WINED3D_TS_WORLD_MATRIX(0);
3365 break;
3366 case D3DTRANSFORMSTATE_WORLD1:
3367 type = WINED3D_TS_WORLD_MATRIX(1);
3368 break;
3369 case D3DTRANSFORMSTATE_WORLD2:
3370 type = WINED3D_TS_WORLD_MATRIX(2);
3371 break;
3372 case D3DTRANSFORMSTATE_WORLD3:
3373 type = WINED3D_TS_WORLD_MATRIX(3);
3374 break;
3375 default:
3376 type = TransformStateType;
3379 if(!Matrix)
3380 return DDERR_INVALIDPARAMS;
3382 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3383 wined3d_mutex_lock();
3384 hr = wined3d_device_get_transform(This->wined3d_device, type, (struct wined3d_matrix *)Matrix);
3385 wined3d_mutex_unlock();
3387 return hr;
3390 static HRESULT WINAPI
3391 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3392 D3DTRANSFORMSTATETYPE TransformStateType,
3393 D3DMATRIX *Matrix)
3395 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3398 static HRESULT WINAPI
3399 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3400 D3DTRANSFORMSTATETYPE TransformStateType,
3401 D3DMATRIX *Matrix)
3403 HRESULT hr;
3404 WORD old_fpucw;
3406 old_fpucw = d3d_fpu_setup();
3407 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3408 set_fpu_control_word(old_fpucw);
3410 return hr;
3413 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3414 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3416 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3418 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3420 if (!matrix)
3421 return DDERR_INVALIDPARAMS;
3423 if (state == D3DTRANSFORMSTATE_PROJECTION)
3425 wined3d_mutex_lock();
3426 *matrix = This->legacy_projection;
3427 wined3d_mutex_unlock();
3428 return DD_OK;
3431 return IDirect3DDevice7_GetTransform(&This->IDirect3DDevice7_iface, state, matrix);
3434 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3435 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3437 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3439 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3441 return IDirect3DDevice7_GetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3444 /*****************************************************************************
3445 * IDirect3DDevice7::MultiplyTransform
3447 * Multiplies the already-set transform matrix of a transform state
3448 * with another matrix. For the world matrix, see SetTransform
3450 * Version 2, 3 and 7
3452 * Params:
3453 * TransformStateType: Transform state to multiply
3454 * D3DMatrix Matrix to multiply with.
3456 * Returns
3457 * D3D_OK on success
3458 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3459 * For details, see IWineD3DDevice::MultiplyTransform
3461 *****************************************************************************/
3462 static HRESULT
3463 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3464 D3DTRANSFORMSTATETYPE TransformStateType,
3465 D3DMATRIX *D3DMatrix)
3467 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3468 HRESULT hr;
3469 D3DTRANSFORMSTATETYPE type;
3471 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3473 switch(TransformStateType)
3475 case D3DTRANSFORMSTATE_WORLD:
3476 type = WINED3D_TS_WORLD_MATRIX(0);
3477 break;
3478 case D3DTRANSFORMSTATE_WORLD1:
3479 type = WINED3D_TS_WORLD_MATRIX(1);
3480 break;
3481 case D3DTRANSFORMSTATE_WORLD2:
3482 type = WINED3D_TS_WORLD_MATRIX(2);
3483 break;
3484 case D3DTRANSFORMSTATE_WORLD3:
3485 type = WINED3D_TS_WORLD_MATRIX(3);
3486 break;
3487 default:
3488 type = TransformStateType;
3491 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3492 wined3d_mutex_lock();
3493 hr = wined3d_device_multiply_transform(This->wined3d_device,
3494 type, (struct wined3d_matrix *)D3DMatrix);
3495 wined3d_mutex_unlock();
3497 return hr;
3500 static HRESULT WINAPI
3501 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3502 D3DTRANSFORMSTATETYPE TransformStateType,
3503 D3DMATRIX *D3DMatrix)
3505 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3508 static HRESULT WINAPI
3509 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3510 D3DTRANSFORMSTATETYPE TransformStateType,
3511 D3DMATRIX *D3DMatrix)
3513 HRESULT hr;
3514 WORD old_fpucw;
3516 old_fpucw = d3d_fpu_setup();
3517 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3518 set_fpu_control_word(old_fpucw);
3520 return hr;
3523 static HRESULT WINAPI IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3524 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3526 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3528 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3530 if (state == D3DTRANSFORMSTATE_PROJECTION)
3532 D3DMATRIX projection, tmp;
3533 HRESULT hr;
3535 wined3d_mutex_lock();
3536 multiply_matrix(&tmp, &This->legacy_projection, matrix);
3537 multiply_matrix(&projection, &This->legacy_clipspace, &tmp);
3538 hr = wined3d_device_set_transform(This->wined3d_device,
3539 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3540 if (SUCCEEDED(hr))
3541 This->legacy_projection = tmp;
3542 wined3d_mutex_unlock();
3544 return hr;
3547 return IDirect3DDevice7_MultiplyTransform(&This->IDirect3DDevice7_iface, state, matrix);
3550 static HRESULT WINAPI IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3551 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3553 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3555 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3557 return IDirect3DDevice7_MultiplyTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3560 /*****************************************************************************
3561 * IDirect3DDevice7::DrawPrimitive
3563 * Draws primitives based on vertices in an application-provided pointer
3565 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3566 * an FVF format for D3D7
3568 * Params:
3569 * PrimitiveType: The type of the primitives to draw
3570 * Vertex type: Flexible vertex format vertex description
3571 * Vertices: Pointer to the vertex array
3572 * VertexCount: The number of vertices to draw
3573 * Flags: As usual a few flags
3575 * Returns:
3576 * D3D_OK on success
3577 * DDERR_INVALIDPARAMS if Vertices is NULL
3578 * For details, see IWineD3DDevice::DrawPrimitiveUP
3580 *****************************************************************************/
3581 static HRESULT
3582 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3583 D3DPRIMITIVETYPE PrimitiveType,
3584 DWORD VertexType,
3585 void *Vertices,
3586 DWORD VertexCount,
3587 DWORD Flags)
3589 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3590 UINT stride;
3591 HRESULT hr;
3593 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3594 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3596 if(!Vertices)
3597 return DDERR_INVALIDPARAMS;
3599 /* Get the stride */
3600 stride = get_flexible_vertex_size(VertexType);
3602 /* Set the FVF */
3603 wined3d_mutex_lock();
3604 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3605 if(hr != D3D_OK)
3607 wined3d_mutex_unlock();
3608 return hr;
3611 /* This method translates to the user pointer draw of WineD3D */
3612 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3613 hr = wined3d_device_draw_primitive_up(This->wined3d_device, VertexCount, Vertices, stride);
3614 wined3d_mutex_unlock();
3616 return hr;
3619 static HRESULT WINAPI
3620 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3621 D3DPRIMITIVETYPE PrimitiveType,
3622 DWORD VertexType,
3623 void *Vertices,
3624 DWORD VertexCount,
3625 DWORD Flags)
3627 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3630 static HRESULT WINAPI
3631 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3632 D3DPRIMITIVETYPE PrimitiveType,
3633 DWORD VertexType,
3634 void *Vertices,
3635 DWORD VertexCount,
3636 DWORD Flags)
3638 HRESULT hr;
3639 WORD old_fpucw;
3641 old_fpucw = d3d_fpu_setup();
3642 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3643 set_fpu_control_word(old_fpucw);
3645 return hr;
3648 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3649 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3650 DWORD Flags)
3652 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3653 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3654 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3656 return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface,
3657 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3660 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3661 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3662 DWORD VertexCount, DWORD Flags)
3664 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3665 DWORD FVF;
3667 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3668 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3670 switch(VertexType)
3672 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3673 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3674 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3675 default:
3676 ERR("Unexpected vertex type %d\n", VertexType);
3677 return DDERR_INVALIDPARAMS; /* Should never happen */
3680 return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface,
3681 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3684 /*****************************************************************************
3685 * IDirect3DDevice7::DrawIndexedPrimitive
3687 * Draws vertices from an application-provided pointer, based on the index
3688 * numbers in a WORD array.
3690 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3691 * an FVF format for D3D7
3693 * Params:
3694 * PrimitiveType: The primitive type to draw
3695 * VertexType: The FVF vertex description
3696 * Vertices: Pointer to the vertex array
3697 * VertexCount: ?
3698 * Indices: Pointer to the index array
3699 * IndexCount: Number of indices = Number of vertices to draw
3700 * Flags: As usual, some flags
3702 * Returns:
3703 * D3D_OK on success
3704 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3705 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3707 *****************************************************************************/
3708 static HRESULT
3709 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3710 D3DPRIMITIVETYPE PrimitiveType,
3711 DWORD VertexType,
3712 void *Vertices,
3713 DWORD VertexCount,
3714 WORD *Indices,
3715 DWORD IndexCount,
3716 DWORD Flags)
3718 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3719 HRESULT hr;
3721 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3722 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3724 /* Set the D3DDevice's FVF */
3725 wined3d_mutex_lock();
3726 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3727 if(FAILED(hr))
3729 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3730 wined3d_mutex_unlock();
3731 return hr;
3734 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3735 hr = wined3d_device_draw_indexed_primitive_up(This->wined3d_device, IndexCount, Indices,
3736 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3737 wined3d_mutex_unlock();
3739 return hr;
3742 static HRESULT WINAPI
3743 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3744 D3DPRIMITIVETYPE PrimitiveType,
3745 DWORD VertexType,
3746 void *Vertices,
3747 DWORD VertexCount,
3748 WORD *Indices,
3749 DWORD IndexCount,
3750 DWORD Flags)
3752 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3755 static HRESULT WINAPI
3756 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3757 D3DPRIMITIVETYPE PrimitiveType,
3758 DWORD VertexType,
3759 void *Vertices,
3760 DWORD VertexCount,
3761 WORD *Indices,
3762 DWORD IndexCount,
3763 DWORD Flags)
3765 HRESULT hr;
3766 WORD old_fpucw;
3768 old_fpucw = d3d_fpu_setup();
3769 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3770 set_fpu_control_word(old_fpucw);
3772 return hr;
3775 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3776 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3777 WORD *Indices, DWORD IndexCount, DWORD Flags)
3779 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3780 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3781 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3783 return IDirect3DDevice7_DrawIndexedPrimitive(&This->IDirect3DDevice7_iface,
3784 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3787 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3788 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3789 DWORD VertexCount, WORD *Indices, DWORD IndexCount, DWORD Flags)
3791 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3792 DWORD FVF;
3794 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3795 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3797 switch(VertexType)
3799 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3800 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3801 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3802 default:
3803 ERR("Unexpected vertex type %d\n", VertexType);
3804 return DDERR_INVALIDPARAMS; /* Should never happen */
3807 return IDirect3DDevice7_DrawIndexedPrimitive(&This->IDirect3DDevice7_iface,
3808 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3811 /*****************************************************************************
3812 * IDirect3DDevice7::SetClipStatus
3814 * Sets the clip status. This defines things as clipping conditions and
3815 * the extents of the clipping region.
3817 * Version 2, 3 and 7
3819 * Params:
3820 * ClipStatus:
3822 * Returns:
3823 * D3D_OK because it's a stub
3824 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3826 *****************************************************************************/
3827 static HRESULT WINAPI
3828 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3829 D3DCLIPSTATUS *ClipStatus)
3831 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3833 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3834 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3836 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3837 return D3D_OK;
3840 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3841 D3DCLIPSTATUS *ClipStatus)
3843 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3844 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3846 return IDirect3DDevice7_SetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3849 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3850 D3DCLIPSTATUS *ClipStatus)
3852 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3853 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3855 return IDirect3DDevice7_SetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3858 /*****************************************************************************
3859 * IDirect3DDevice7::GetClipStatus
3861 * Returns the clip status
3863 * Params:
3864 * ClipStatus: Address to write the clip status to
3866 * Returns:
3867 * D3D_OK because it's a stub
3869 *****************************************************************************/
3870 static HRESULT WINAPI
3871 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3872 D3DCLIPSTATUS *ClipStatus)
3874 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3876 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3877 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3878 return D3D_OK;
3881 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3882 D3DCLIPSTATUS *ClipStatus)
3884 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3885 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3887 return IDirect3DDevice7_GetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3890 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3891 D3DCLIPSTATUS *ClipStatus)
3893 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3894 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3896 return IDirect3DDevice7_GetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3899 /*****************************************************************************
3900 * IDirect3DDevice::DrawPrimitiveStrided
3902 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3904 * Version 3 and 7
3906 * Params:
3907 * PrimitiveType: The primitive type to draw
3908 * VertexType: The FVF description of the vertices to draw (for the stride??)
3909 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3910 * the vertex data locations
3911 * VertexCount: The number of vertices to draw
3912 * Flags: Some flags
3914 * Returns:
3915 * D3D_OK, because it's a stub
3916 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3917 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3919 *****************************************************************************/
3920 static HRESULT
3921 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3922 D3DPRIMITIVETYPE PrimitiveType,
3923 DWORD VertexType,
3924 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3925 DWORD VertexCount,
3926 DWORD Flags)
3928 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3929 struct wined3d_strided_data wined3d_strided;
3930 DWORD i;
3931 HRESULT hr;
3933 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3934 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3936 memset(&wined3d_strided, 0, sizeof(wined3d_strided));
3937 /* Get the strided data right. the wined3d structure is a bit bigger
3938 * Watch out: The contents of the strided data are determined by the fvf,
3939 * not by the members set in D3DDrawPrimStrideData. So it's valid
3940 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3941 * not set in the fvf.
3943 if(VertexType & D3DFVF_POSITION_MASK)
3945 wined3d_strided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3946 wined3d_strided.position.data = D3DDrawPrimStrideData->position.lpvData;
3947 wined3d_strided.position.stride = D3DDrawPrimStrideData->position.dwStride;
3948 if (VertexType & D3DFVF_XYZRHW)
3950 wined3d_strided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3951 wined3d_strided.position_transformed = TRUE;
3953 else
3955 wined3d_strided.position_transformed = FALSE;
3959 if (VertexType & D3DFVF_NORMAL)
3961 wined3d_strided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3962 wined3d_strided.normal.data = D3DDrawPrimStrideData->normal.lpvData;
3963 wined3d_strided.normal.stride = D3DDrawPrimStrideData->normal.dwStride;
3966 if (VertexType & D3DFVF_DIFFUSE)
3968 wined3d_strided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3969 wined3d_strided.diffuse.data = D3DDrawPrimStrideData->diffuse.lpvData;
3970 wined3d_strided.diffuse.stride = D3DDrawPrimStrideData->diffuse.dwStride;
3973 if (VertexType & D3DFVF_SPECULAR)
3975 wined3d_strided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3976 wined3d_strided.specular.data = D3DDrawPrimStrideData->specular.lpvData;
3977 wined3d_strided.specular.stride = D3DDrawPrimStrideData->specular.dwStride;
3980 for (i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); ++i)
3982 switch (GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3984 case 1: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32_FLOAT; break;
3985 case 2: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3986 case 3: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3987 case 4: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3988 default: ERR("Unexpected texture coordinate size %d\n",
3989 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3991 wined3d_strided.tex_coords[i].data = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3992 wined3d_strided.tex_coords[i].stride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3995 /* WineD3D doesn't need the FVF here */
3996 wined3d_mutex_lock();
3997 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3998 hr = wined3d_device_draw_primitive_strided(This->wined3d_device, VertexCount, &wined3d_strided);
3999 wined3d_mutex_unlock();
4001 return hr;
4004 static HRESULT WINAPI
4005 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4006 D3DPRIMITIVETYPE PrimitiveType,
4007 DWORD VertexType,
4008 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4009 DWORD VertexCount,
4010 DWORD Flags)
4012 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4015 static HRESULT WINAPI
4016 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4017 D3DPRIMITIVETYPE PrimitiveType,
4018 DWORD VertexType,
4019 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4020 DWORD VertexCount,
4021 DWORD Flags)
4023 HRESULT hr;
4024 WORD old_fpucw;
4026 old_fpucw = d3d_fpu_setup();
4027 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4028 set_fpu_control_word(old_fpucw);
4030 return hr;
4033 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
4034 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4035 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4037 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4039 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
4040 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4042 return IDirect3DDevice7_DrawPrimitiveStrided(&This->IDirect3DDevice7_iface,
4043 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4046 /*****************************************************************************
4047 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
4049 * Draws primitives specified by strided data locations based on indices
4051 * Version 3 and 7
4053 * Params:
4054 * PrimitiveType:
4056 * Returns:
4057 * D3D_OK, because it's a stub
4058 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
4059 * (DDERR_INVALIDPARAMS if Indices is NULL)
4060 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
4062 *****************************************************************************/
4063 static HRESULT
4064 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
4065 D3DPRIMITIVETYPE PrimitiveType,
4066 DWORD VertexType,
4067 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4068 DWORD VertexCount,
4069 WORD *Indices,
4070 DWORD IndexCount,
4071 DWORD Flags)
4073 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4074 struct wined3d_strided_data wined3d_strided;
4075 DWORD i;
4076 HRESULT hr;
4078 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4079 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4081 memset(&wined3d_strided, 0, sizeof(wined3d_strided));
4082 /* Get the strided data right. the wined3d structure is a bit bigger
4083 * Watch out: The contents of the strided data are determined by the fvf,
4084 * not by the members set in D3DDrawPrimStrideData. So it's valid
4085 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
4086 * not set in the fvf. */
4087 if (VertexType & D3DFVF_POSITION_MASK)
4089 wined3d_strided.position.format = WINED3DFMT_R32G32B32_FLOAT;
4090 wined3d_strided.position.data = D3DDrawPrimStrideData->position.lpvData;
4091 wined3d_strided.position.stride = D3DDrawPrimStrideData->position.dwStride;
4092 if (VertexType & D3DFVF_XYZRHW)
4094 wined3d_strided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
4095 wined3d_strided.position_transformed = TRUE;
4097 else
4099 wined3d_strided.position_transformed = FALSE;
4103 if (VertexType & D3DFVF_NORMAL)
4105 wined3d_strided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
4106 wined3d_strided.normal.data = D3DDrawPrimStrideData->normal.lpvData;
4107 wined3d_strided.normal.stride = D3DDrawPrimStrideData->normal.dwStride;
4110 if (VertexType & D3DFVF_DIFFUSE)
4112 wined3d_strided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
4113 wined3d_strided.diffuse.data = D3DDrawPrimStrideData->diffuse.lpvData;
4114 wined3d_strided.diffuse.stride = D3DDrawPrimStrideData->diffuse.dwStride;
4117 if (VertexType & D3DFVF_SPECULAR)
4119 wined3d_strided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
4120 wined3d_strided.specular.data = D3DDrawPrimStrideData->specular.lpvData;
4121 wined3d_strided.specular.stride = D3DDrawPrimStrideData->specular.dwStride;
4124 for (i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); ++i)
4126 switch (GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
4128 case 1: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32_FLOAT; break;
4129 case 2: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32_FLOAT; break;
4130 case 3: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
4131 case 4: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
4132 default: ERR("Unexpected texture coordinate size %d\n",
4133 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4135 wined3d_strided.tex_coords[i].data = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4136 wined3d_strided.tex_coords[i].stride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4139 /* WineD3D doesn't need the FVF here */
4140 wined3d_mutex_lock();
4141 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4142 hr = wined3d_device_draw_indexed_primitive_strided(This->wined3d_device,
4143 IndexCount, &wined3d_strided, VertexCount, Indices, WINED3DFMT_R16_UINT);
4144 wined3d_mutex_unlock();
4146 return hr;
4149 static HRESULT WINAPI
4150 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4151 D3DPRIMITIVETYPE PrimitiveType,
4152 DWORD VertexType,
4153 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4154 DWORD VertexCount,
4155 WORD *Indices,
4156 DWORD IndexCount,
4157 DWORD Flags)
4159 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4162 static HRESULT WINAPI
4163 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4164 D3DPRIMITIVETYPE PrimitiveType,
4165 DWORD VertexType,
4166 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4167 DWORD VertexCount,
4168 WORD *Indices,
4169 DWORD IndexCount,
4170 DWORD Flags)
4172 HRESULT hr;
4173 WORD old_fpucw;
4175 old_fpucw = d3d_fpu_setup();
4176 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4177 set_fpu_control_word(old_fpucw);
4179 return hr;
4182 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4183 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4184 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4185 DWORD IndexCount, DWORD Flags)
4187 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4189 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4190 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4192 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&This->IDirect3DDevice7_iface,
4193 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4196 /*****************************************************************************
4197 * IDirect3DDevice7::DrawPrimitiveVB
4199 * Draws primitives from a vertex buffer to the screen.
4201 * Version 3 and 7
4203 * Params:
4204 * PrimitiveType: Type of primitive to be rendered.
4205 * D3DVertexBuf: Source Vertex Buffer
4206 * StartVertex: Index of the first vertex from the buffer to be rendered
4207 * NumVertices: Number of vertices to be rendered
4208 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4210 * Return values
4211 * D3D_OK on success
4212 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4214 *****************************************************************************/
4215 static HRESULT
4216 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4217 D3DPRIMITIVETYPE PrimitiveType,
4218 IDirect3DVertexBuffer7 *D3DVertexBuf,
4219 DWORD StartVertex,
4220 DWORD NumVertices,
4221 DWORD Flags)
4223 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4224 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4225 HRESULT hr;
4226 DWORD stride;
4228 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4229 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4231 /* Sanity checks */
4232 if(!vb)
4234 ERR("(%p) No Vertex buffer specified\n", This);
4235 return DDERR_INVALIDPARAMS;
4237 stride = get_flexible_vertex_size(vb->fvf);
4239 wined3d_mutex_lock();
4240 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4241 if (FAILED(hr))
4243 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4244 wined3d_mutex_unlock();
4245 return hr;
4248 /* Set the vertex stream source */
4249 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4250 if(hr != D3D_OK)
4252 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4253 wined3d_mutex_unlock();
4254 return hr;
4257 /* Now draw the primitives */
4258 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4259 hr = wined3d_device_draw_primitive(This->wined3d_device, StartVertex, NumVertices);
4260 wined3d_mutex_unlock();
4262 return hr;
4265 static HRESULT WINAPI
4266 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4267 D3DPRIMITIVETYPE PrimitiveType,
4268 IDirect3DVertexBuffer7 *D3DVertexBuf,
4269 DWORD StartVertex,
4270 DWORD NumVertices,
4271 DWORD Flags)
4273 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4276 static HRESULT WINAPI
4277 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4278 D3DPRIMITIVETYPE PrimitiveType,
4279 IDirect3DVertexBuffer7 *D3DVertexBuf,
4280 DWORD StartVertex,
4281 DWORD NumVertices,
4282 DWORD Flags)
4284 HRESULT hr;
4285 WORD old_fpucw;
4287 old_fpucw = d3d_fpu_setup();
4288 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4289 set_fpu_control_word(old_fpucw);
4291 return hr;
4294 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4295 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex,
4296 DWORD NumVertices, DWORD Flags)
4298 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4299 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4301 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4302 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4304 return IDirect3DDevice7_DrawPrimitiveVB(&This->IDirect3DDevice7_iface,
4305 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4309 /*****************************************************************************
4310 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4312 * Draws primitives from a vertex buffer to the screen
4314 * Params:
4315 * PrimitiveType: Type of primitive to be rendered.
4316 * D3DVertexBuf: Source Vertex Buffer
4317 * StartVertex: Index of the first vertex from the buffer to be rendered
4318 * NumVertices: Number of vertices to be rendered
4319 * Indices: Array of DWORDs used to index into the Vertices
4320 * IndexCount: Number of indices in Indices
4321 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4323 * Return values
4325 *****************************************************************************/
4326 static HRESULT
4327 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4328 D3DPRIMITIVETYPE PrimitiveType,
4329 IDirect3DVertexBuffer7 *D3DVertexBuf,
4330 DWORD StartVertex,
4331 DWORD NumVertices,
4332 WORD *Indices,
4333 DWORD IndexCount,
4334 DWORD Flags)
4336 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4337 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4338 DWORD stride = get_flexible_vertex_size(vb->fvf);
4339 struct wined3d_resource *wined3d_resource;
4340 struct wined3d_resource_desc desc;
4341 WORD *LockedIndices;
4342 HRESULT hr;
4344 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4345 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4347 /* Steps:
4348 * 1) Upload the Indices to the index buffer
4349 * 2) Set the index source
4350 * 3) Set the Vertex Buffer as the Stream source
4351 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4354 wined3d_mutex_lock();
4356 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4357 if (FAILED(hr))
4359 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4360 wined3d_mutex_unlock();
4361 return hr;
4364 /* check that the buffer is large enough to hold the indices,
4365 * reallocate if necessary. */
4366 wined3d_resource = wined3d_buffer_get_resource(This->indexbuffer);
4367 wined3d_resource_get_desc(wined3d_resource, &desc);
4368 if (desc.size < IndexCount * sizeof(WORD))
4370 UINT size = max(desc.size * 2, IndexCount * sizeof(WORD));
4371 struct wined3d_buffer *buffer;
4373 TRACE("Growing index buffer to %u bytes\n", size);
4375 hr = wined3d_buffer_create_ib(This->wined3d_device, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4376 WINED3D_POOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
4377 if (FAILED(hr))
4379 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4380 wined3d_mutex_unlock();
4381 return hr;
4384 wined3d_buffer_decref(This->indexbuffer);
4385 This->indexbuffer = buffer;
4388 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4389 * method could be created which takes an user pointer containing the
4390 * indices or a SetData-Method for the index buffer, which overrides the
4391 * index buffer data with our pointer. */
4392 hr = wined3d_buffer_map(This->indexbuffer, 0, IndexCount * sizeof(WORD),
4393 (BYTE **)&LockedIndices, 0);
4394 if (FAILED(hr))
4396 ERR("Failed to map buffer, hr %#x.\n", hr);
4397 wined3d_mutex_unlock();
4398 return hr;
4400 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4401 wined3d_buffer_unmap(This->indexbuffer);
4403 /* Set the index stream */
4404 wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4405 hr = wined3d_device_set_index_buffer(This->wined3d_device, This->indexbuffer, WINED3DFMT_R16_UINT);
4407 /* Set the vertex stream source */
4408 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4409 if (FAILED(hr))
4411 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4412 wined3d_mutex_unlock();
4413 return hr;
4417 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4418 hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, 0, IndexCount);
4420 wined3d_mutex_unlock();
4422 return hr;
4425 static HRESULT WINAPI
4426 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4427 D3DPRIMITIVETYPE PrimitiveType,
4428 IDirect3DVertexBuffer7 *D3DVertexBuf,
4429 DWORD StartVertex,
4430 DWORD NumVertices,
4431 WORD *Indices,
4432 DWORD IndexCount,
4433 DWORD Flags)
4435 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4438 static HRESULT WINAPI
4439 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4440 D3DPRIMITIVETYPE PrimitiveType,
4441 IDirect3DVertexBuffer7 *D3DVertexBuf,
4442 DWORD StartVertex,
4443 DWORD NumVertices,
4444 WORD *Indices,
4445 DWORD IndexCount,
4446 DWORD Flags)
4448 HRESULT hr;
4449 WORD old_fpucw;
4451 old_fpucw = d3d_fpu_setup();
4452 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4453 set_fpu_control_word(old_fpucw);
4455 return hr;
4458 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4459 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4460 DWORD IndexCount, DWORD Flags)
4462 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4463 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4465 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4466 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4468 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&This->IDirect3DDevice7_iface,
4469 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount,
4470 Flags);
4473 /*****************************************************************************
4474 * IDirect3DDevice7::ComputeSphereVisibility
4476 * Calculates the visibility of spheres in the current viewport. The spheres
4477 * are passed in the Centers and Radii arrays, the results are passed back
4478 * in the ReturnValues array. Return values are either completely visible,
4479 * partially visible or completely invisible.
4480 * The return value consist of a combination of D3DCLIP_* flags, or it's
4481 * 0 if the sphere is completely visible(according to the SDK, not checked)
4483 * Version 3 and 7
4485 * Params:
4486 * Centers: Array containing the sphere centers
4487 * Radii: Array containing the sphere radii
4488 * NumSpheres: The number of centers and radii in the arrays
4489 * Flags: Some flags
4490 * ReturnValues: Array to write the results to
4492 * Returns:
4493 * D3D_OK
4494 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4495 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4496 * is singular)
4498 *****************************************************************************/
4500 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4502 float distance, norm;
4504 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4505 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4507 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4508 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4509 return 0;
4512 static HRESULT WINAPI
4513 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4514 D3DVECTOR *Centers,
4515 D3DVALUE *Radii,
4516 DWORD NumSpheres,
4517 DWORD Flags,
4518 DWORD *ReturnValues)
4520 D3DMATRIX m, temp;
4521 D3DVALUE origin_plane[6];
4522 D3DVECTOR vec[6];
4523 HRESULT hr;
4524 UINT i, j;
4526 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4527 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4529 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4530 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4531 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4532 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4533 multiply_matrix(&m, &temp, &m);
4535 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4536 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4537 multiply_matrix(&m, &temp, &m);
4539 /* Left plane */
4540 vec[0].u1.x = m._14 + m._11;
4541 vec[0].u2.y = m._24 + m._21;
4542 vec[0].u3.z = m._34 + m._31;
4543 origin_plane[0] = m._44 + m._41;
4545 /* Right plane */
4546 vec[1].u1.x = m._14 - m._11;
4547 vec[1].u2.y = m._24 - m._21;
4548 vec[1].u3.z = m._34 - m._31;
4549 origin_plane[1] = m._44 - m._41;
4551 /* Top plane */
4552 vec[2].u1.x = m._14 - m._12;
4553 vec[2].u2.y = m._24 - m._22;
4554 vec[2].u3.z = m._34 - m._32;
4555 origin_plane[2] = m._44 - m._42;
4557 /* Bottom plane */
4558 vec[3].u1.x = m._14 + m._12;
4559 vec[3].u2.y = m._24 + m._22;
4560 vec[3].u3.z = m._34 + m._32;
4561 origin_plane[3] = m._44 + m._42;
4563 /* Front plane */
4564 vec[4].u1.x = m._13;
4565 vec[4].u2.y = m._23;
4566 vec[4].u3.z = m._33;
4567 origin_plane[4] = m._43;
4569 /* Back plane*/
4570 vec[5].u1.x = m._14 - m._13;
4571 vec[5].u2.y = m._24 - m._23;
4572 vec[5].u3.z = m._34 - m._33;
4573 origin_plane[5] = m._44 - m._43;
4575 for(i=0; i<NumSpheres; i++)
4577 ReturnValues[i] = 0;
4578 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4581 return D3D_OK;
4584 static HRESULT WINAPI IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4585 D3DVECTOR *Centers, D3DVALUE *Radii, DWORD NumSpheres, DWORD Flags, DWORD *ReturnValues)
4587 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4589 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4590 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4592 return IDirect3DDevice7_ComputeSphereVisibility(&This->IDirect3DDevice7_iface,
4593 Centers, Radii, NumSpheres, Flags, ReturnValues);
4596 /*****************************************************************************
4597 * IDirect3DDevice7::GetTexture
4599 * Returns the texture interface handle assigned to a texture stage.
4600 * The returned texture is AddRefed. This is taken from old ddraw,
4601 * not checked in Windows.
4603 * Version 3 and 7
4605 * Params:
4606 * Stage: Texture stage to read the texture from
4607 * Texture: Address to store the interface pointer at
4609 * Returns:
4610 * D3D_OK on success
4611 * DDERR_INVALIDPARAMS if Texture is NULL
4612 * For details, see IWineD3DDevice::GetTexture
4614 *****************************************************************************/
4615 static HRESULT
4616 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4617 DWORD Stage,
4618 IDirectDrawSurface7 **Texture)
4620 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4621 struct wined3d_texture *wined3d_texture;
4622 HRESULT hr;
4624 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4626 if(!Texture)
4628 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4629 return DDERR_INVALIDPARAMS;
4632 wined3d_mutex_lock();
4633 hr = wined3d_device_get_texture(This->wined3d_device, Stage, &wined3d_texture);
4634 if (FAILED(hr) || !wined3d_texture)
4636 *Texture = NULL;
4637 wined3d_mutex_unlock();
4638 return hr;
4641 *Texture = wined3d_texture_get_parent(wined3d_texture);
4642 IDirectDrawSurface7_AddRef(*Texture);
4643 wined3d_texture_decref(wined3d_texture);
4644 wined3d_mutex_unlock();
4646 return hr;
4649 static HRESULT WINAPI
4650 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4651 DWORD Stage,
4652 IDirectDrawSurface7 **Texture)
4654 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4657 static HRESULT WINAPI
4658 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4659 DWORD Stage,
4660 IDirectDrawSurface7 **Texture)
4662 HRESULT hr;
4663 WORD old_fpucw;
4665 old_fpucw = d3d_fpu_setup();
4666 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4667 set_fpu_control_word(old_fpucw);
4669 return hr;
4672 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface, DWORD Stage,
4673 IDirect3DTexture2 **Texture2)
4675 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4676 struct ddraw_surface *ret_val_impl;
4677 HRESULT ret;
4678 IDirectDrawSurface7 *ret_val;
4680 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4682 ret = IDirect3DDevice7_GetTexture(&This->IDirect3DDevice7_iface, Stage, &ret_val);
4684 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4685 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4687 TRACE("Returning texture %p.\n", *Texture2);
4689 return ret;
4692 /*****************************************************************************
4693 * IDirect3DDevice7::SetTexture
4695 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4697 * Version 3 and 7
4699 * Params:
4700 * Stage: The stage to assign the texture to
4701 * Texture: Interface pointer to the texture surface
4703 * Returns
4704 * D3D_OK on success
4705 * For details, see IWineD3DDevice::SetTexture
4707 *****************************************************************************/
4708 static HRESULT
4709 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4710 DWORD Stage,
4711 IDirectDrawSurface7 *Texture)
4713 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4714 struct ddraw_surface *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
4715 HRESULT hr;
4717 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4719 /* Texture may be NULL here */
4720 wined3d_mutex_lock();
4721 hr = wined3d_device_set_texture(This->wined3d_device,
4722 Stage, surf ? surf->wined3d_texture : NULL);
4723 wined3d_mutex_unlock();
4725 return hr;
4728 static HRESULT WINAPI
4729 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4730 DWORD Stage,
4731 IDirectDrawSurface7 *Texture)
4733 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4736 static HRESULT WINAPI
4737 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4738 DWORD Stage,
4739 IDirectDrawSurface7 *Texture)
4741 HRESULT hr;
4742 WORD old_fpucw;
4744 old_fpucw = d3d_fpu_setup();
4745 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4746 set_fpu_control_word(old_fpucw);
4748 return hr;
4751 static HRESULT WINAPI
4752 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4753 DWORD Stage,
4754 IDirect3DTexture2 *Texture2)
4756 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4757 struct ddraw_surface *tex = unsafe_impl_from_IDirect3DTexture2(Texture2);
4758 DWORD texmapblend;
4759 HRESULT hr;
4761 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4763 wined3d_mutex_lock();
4765 if (This->legacyTextureBlending)
4766 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4768 hr = IDirect3DDevice7_SetTexture(&This->IDirect3DDevice7_iface, Stage, &tex->IDirectDrawSurface7_iface);
4770 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4772 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4773 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4774 struct wined3d_texture *tex = NULL;
4775 BOOL tex_alpha = FALSE;
4776 DDPIXELFORMAT ddfmt;
4777 HRESULT result;
4779 result = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
4780 if (result == WINED3D_OK && tex)
4782 struct wined3d_resource *sub_resource;
4784 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4786 struct wined3d_resource_desc desc;
4788 wined3d_resource_get_desc(sub_resource, &desc);
4789 ddfmt.dwSize = sizeof(ddfmt);
4790 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4791 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4794 wined3d_texture_decref(tex);
4797 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4798 if (tex_alpha)
4799 wined3d_device_set_texture_stage_state(This->wined3d_device,
4800 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
4801 else
4802 wined3d_device_set_texture_stage_state(This->wined3d_device,
4803 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
4806 wined3d_mutex_unlock();
4808 return hr;
4811 static const struct tss_lookup
4813 BOOL sampler_state;
4814 enum wined3d_texture_stage_state state;
4816 tss_lookup[] =
4818 {FALSE, WINED3D_TSS_INVALID}, /* 0, unused */
4819 {FALSE, WINED3D_TSS_COLOR_OP}, /* 1, D3DTSS_COLOROP */
4820 {FALSE, WINED3D_TSS_COLOR_ARG1}, /* 2, D3DTSS_COLORARG1 */
4821 {FALSE, WINED3D_TSS_COLOR_ARG2}, /* 3, D3DTSS_COLORARG2 */
4822 {FALSE, WINED3D_TSS_ALPHA_OP}, /* 4, D3DTSS_ALPHAOP */
4823 {FALSE, WINED3D_TSS_ALPHA_ARG1}, /* 5, D3DTSS_ALPHAARG1 */
4824 {FALSE, WINED3D_TSS_ALPHA_ARG2}, /* 6, D3DTSS_ALPHAARG2 */
4825 {FALSE, WINED3D_TSS_BUMPENV_MAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4826 {FALSE, WINED3D_TSS_BUMPENV_MAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4827 {FALSE, WINED3D_TSS_BUMPENV_MAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4828 {FALSE, WINED3D_TSS_BUMPENV_MAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4829 {FALSE, WINED3D_TSS_TEXCOORD_INDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4830 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 12, D3DTSS_ADDRESS */
4831 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 13, D3DTSS_ADDRESSU */
4832 {TRUE, WINED3D_SAMP_ADDRESS_V}, /* 14, D3DTSS_ADDRESSV */
4833 {TRUE, WINED3D_SAMP_BORDER_COLOR}, /* 15, D3DTSS_BORDERCOLOR */
4834 {TRUE, WINED3D_SAMP_MAG_FILTER}, /* 16, D3DTSS_MAGFILTER */
4835 {TRUE, WINED3D_SAMP_MIN_FILTER}, /* 17, D3DTSS_MINFILTER */
4836 {TRUE, WINED3D_SAMP_MIP_FILTER}, /* 18, D3DTSS_MIPFILTER */
4837 {TRUE, WINED3D_SAMP_MIPMAP_LOD_BIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4838 {TRUE, WINED3D_SAMP_MAX_MIP_LEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4839 {TRUE, WINED3D_SAMP_MAX_ANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4840 {FALSE, WINED3D_TSS_BUMPENV_LSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4841 {FALSE, WINED3D_TSS_BUMPENV_LOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4842 {FALSE, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4845 /*****************************************************************************
4846 * IDirect3DDevice7::GetTextureStageState
4848 * Retrieves a state from a texture stage.
4850 * Version 3 and 7
4852 * Params:
4853 * Stage: The stage to retrieve the state from
4854 * TexStageStateType: The state type to retrieve
4855 * State: Address to store the state's value at
4857 * Returns:
4858 * D3D_OK on success
4859 * DDERR_INVALIDPARAMS if State is NULL
4860 * For details, see IWineD3DDevice::GetTextureStageState
4862 *****************************************************************************/
4863 static HRESULT
4864 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4865 DWORD Stage,
4866 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4867 DWORD *State)
4869 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4870 HRESULT hr;
4871 const struct tss_lookup *l;
4873 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4874 iface, Stage, TexStageStateType, State);
4876 if(!State)
4877 return DDERR_INVALIDPARAMS;
4879 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4881 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4882 return DD_OK;
4885 l = &tss_lookup[TexStageStateType];
4887 wined3d_mutex_lock();
4889 if (l->sampler_state)
4891 hr = wined3d_device_get_sampler_state(This->wined3d_device, Stage, l->state, State);
4893 switch(TexStageStateType)
4895 /* Mipfilter is a sampler state with different values */
4896 case D3DTSS_MIPFILTER:
4898 switch(*State)
4900 case WINED3D_TEXF_NONE:
4901 *State = D3DTFP_NONE;
4902 break;
4903 case WINED3D_TEXF_POINT:
4904 *State = D3DTFP_POINT;
4905 break;
4906 case WINED3D_TEXF_LINEAR:
4907 *State = D3DTFP_LINEAR;
4908 break;
4909 default:
4910 ERR("Unexpected mipfilter value %#x\n", *State);
4911 *State = D3DTFP_NONE;
4912 break;
4914 break;
4917 /* Magfilter has slightly different values */
4918 case D3DTSS_MAGFILTER:
4920 switch(*State)
4922 case WINED3D_TEXF_POINT:
4923 *State = D3DTFG_POINT;
4924 break;
4925 case WINED3D_TEXF_LINEAR:
4926 *State = D3DTFG_LINEAR;
4927 break;
4928 case WINED3D_TEXF_ANISOTROPIC:
4929 *State = D3DTFG_ANISOTROPIC;
4930 break;
4931 case WINED3D_TEXF_FLAT_CUBIC:
4932 *State = D3DTFG_FLATCUBIC;
4933 break;
4934 case WINED3D_TEXF_GAUSSIAN_CUBIC:
4935 *State = D3DTFG_GAUSSIANCUBIC;
4936 break;
4937 default:
4938 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4939 *State = D3DTFG_POINT;
4940 break;
4942 break;
4945 default:
4946 break;
4949 else
4951 hr = wined3d_device_get_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4954 wined3d_mutex_unlock();
4956 return hr;
4959 static HRESULT WINAPI
4960 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4961 DWORD Stage,
4962 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4963 DWORD *State)
4965 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4968 static HRESULT WINAPI
4969 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4970 DWORD Stage,
4971 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4972 DWORD *State)
4974 HRESULT hr;
4975 WORD old_fpucw;
4977 old_fpucw = d3d_fpu_setup();
4978 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4979 set_fpu_control_word(old_fpucw);
4981 return hr;
4984 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4985 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD *State)
4987 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4989 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4990 iface, Stage, TexStageStateType, State);
4992 return IDirect3DDevice7_GetTextureStageState(&This->IDirect3DDevice7_iface,
4993 Stage, TexStageStateType, State);
4996 /*****************************************************************************
4997 * IDirect3DDevice7::SetTextureStageState
4999 * Sets a texture stage state. Some stage types need to be handled specially,
5000 * because they do not exist in WineD3D and were moved to another place
5002 * Version 3 and 7
5004 * Params:
5005 * Stage: The stage to modify
5006 * TexStageStateType: The state to change
5007 * State: The new value for the state
5009 * Returns:
5010 * D3D_OK on success
5011 * For details, see IWineD3DDevice::SetTextureStageState
5013 *****************************************************************************/
5014 static HRESULT
5015 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
5016 DWORD Stage,
5017 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5018 DWORD State)
5020 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5021 const struct tss_lookup *l;
5022 HRESULT hr;
5024 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5025 iface, Stage, TexStageStateType, State);
5027 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
5029 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
5030 return DD_OK;
5033 l = &tss_lookup[TexStageStateType];
5035 wined3d_mutex_lock();
5037 if (l->sampler_state)
5039 switch(TexStageStateType)
5041 /* Mipfilter is a sampler state with different values */
5042 case D3DTSS_MIPFILTER:
5044 switch(State)
5046 case D3DTFP_NONE:
5047 State = WINED3D_TEXF_NONE;
5048 break;
5049 case D3DTFP_POINT:
5050 State = WINED3D_TEXF_POINT;
5051 break;
5052 case 0: /* Unchecked */
5053 case D3DTFP_LINEAR:
5054 State = WINED3D_TEXF_LINEAR;
5055 break;
5056 default:
5057 ERR("Unexpected mipfilter value %d\n", State);
5058 State = WINED3D_TEXF_NONE;
5059 break;
5061 break;
5064 /* Magfilter has slightly different values */
5065 case D3DTSS_MAGFILTER:
5067 switch(State)
5069 case D3DTFG_POINT:
5070 State = WINED3D_TEXF_POINT;
5071 break;
5072 case D3DTFG_LINEAR:
5073 State = WINED3D_TEXF_LINEAR;
5074 break;
5075 case D3DTFG_FLATCUBIC:
5076 State = WINED3D_TEXF_FLAT_CUBIC;
5077 break;
5078 case D3DTFG_GAUSSIANCUBIC:
5079 State = WINED3D_TEXF_GAUSSIAN_CUBIC;
5080 break;
5081 case D3DTFG_ANISOTROPIC:
5082 State = WINED3D_TEXF_ANISOTROPIC;
5083 break;
5084 default:
5085 ERR("Unexpected d3d7 mag filter type %d\n", State);
5086 State = WINED3D_TEXF_POINT;
5087 break;
5089 break;
5092 case D3DTSS_ADDRESS:
5093 wined3d_device_set_sampler_state(This->wined3d_device, Stage, WINED3D_SAMP_ADDRESS_V, State);
5094 break;
5096 default:
5097 break;
5100 hr = wined3d_device_set_sampler_state(This->wined3d_device, Stage, l->state, State);
5102 else
5104 hr = wined3d_device_set_texture_stage_state(This->wined3d_device, Stage, l->state, State);
5107 wined3d_mutex_unlock();
5109 return hr;
5112 static HRESULT WINAPI
5113 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5114 DWORD Stage,
5115 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5116 DWORD State)
5118 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5121 static HRESULT WINAPI
5122 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5123 DWORD Stage,
5124 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5125 DWORD State)
5127 HRESULT hr;
5128 WORD old_fpucw;
5130 old_fpucw = d3d_fpu_setup();
5131 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5132 set_fpu_control_word(old_fpucw);
5134 return hr;
5137 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
5138 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD State)
5140 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
5142 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5143 iface, Stage, TexStageStateType, State);
5145 return IDirect3DDevice7_SetTextureStageState(&This->IDirect3DDevice7_iface,
5146 Stage, TexStageStateType, State);
5149 /*****************************************************************************
5150 * IDirect3DDevice7::ValidateDevice
5152 * SDK: "Reports the device's ability to render the currently set
5153 * texture-blending operations in a single pass". Whatever that means
5154 * exactly...
5156 * Version 3 and 7
5158 * Params:
5159 * NumPasses: Address to write the number of necessary passes for the
5160 * desired effect to.
5162 * Returns:
5163 * D3D_OK on success
5164 * See IWineD3DDevice::ValidateDevice for more details
5166 *****************************************************************************/
5167 static HRESULT
5168 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
5169 DWORD *NumPasses)
5171 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5172 HRESULT hr;
5174 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
5176 wined3d_mutex_lock();
5177 hr = wined3d_device_validate_device(This->wined3d_device, NumPasses);
5178 wined3d_mutex_unlock();
5180 return hr;
5183 static HRESULT WINAPI
5184 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
5185 DWORD *NumPasses)
5187 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5190 static HRESULT WINAPI
5191 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
5192 DWORD *NumPasses)
5194 HRESULT hr;
5195 WORD old_fpucw;
5197 old_fpucw = d3d_fpu_setup();
5198 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5199 set_fpu_control_word(old_fpucw);
5201 return hr;
5204 static HRESULT WINAPI IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *Passes)
5206 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
5208 TRACE("iface %p, pass_count %p.\n", iface, Passes);
5210 return IDirect3DDevice7_ValidateDevice(&This->IDirect3DDevice7_iface, Passes);
5213 /*****************************************************************************
5214 * IDirect3DDevice7::Clear
5216 * Fills the render target, the z buffer and the stencil buffer with a
5217 * clear color / value
5219 * Version 7 only
5221 * Params:
5222 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5223 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5224 * Flags: Some flags, as usual
5225 * Color: Clear color for the render target
5226 * Z: Clear value for the Z buffer
5227 * Stencil: Clear value to store in each stencil buffer entry
5229 * Returns:
5230 * D3D_OK on success
5231 * For details, see IWineD3DDevice::Clear
5233 *****************************************************************************/
5234 static HRESULT IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface, DWORD count,
5235 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5237 const struct wined3d_color c =
5239 ((color >> 16) & 0xff) / 255.0f,
5240 ((color >> 8) & 0xff) / 255.0f,
5241 (color & 0xff) / 255.0f,
5242 ((color >> 24) & 0xff) / 255.0f,
5244 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5245 HRESULT hr;
5247 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5248 iface, count, rects, flags, color, z, stencil);
5250 wined3d_mutex_lock();
5251 hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
5252 wined3d_mutex_unlock();
5254 return hr;
5257 static HRESULT WINAPI
5258 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5259 DWORD Count,
5260 D3DRECT *Rects,
5261 DWORD Flags,
5262 D3DCOLOR Color,
5263 D3DVALUE Z,
5264 DWORD Stencil)
5266 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5269 static HRESULT WINAPI
5270 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5271 DWORD Count,
5272 D3DRECT *Rects,
5273 DWORD Flags,
5274 D3DCOLOR Color,
5275 D3DVALUE Z,
5276 DWORD Stencil)
5278 HRESULT hr;
5279 WORD old_fpucw;
5281 old_fpucw = d3d_fpu_setup();
5282 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5283 set_fpu_control_word(old_fpucw);
5285 return hr;
5288 /*****************************************************************************
5289 * IDirect3DDevice7::SetViewport
5291 * Sets the current viewport.
5293 * Version 7 only, but IDirect3DViewport uses this call for older
5294 * versions
5296 * Params:
5297 * Data: The new viewport to set
5299 * Returns:
5300 * D3D_OK on success
5301 * DDERR_INVALIDPARAMS if Data is NULL
5302 * For more details, see IWineDDDevice::SetViewport
5304 *****************************************************************************/
5305 static HRESULT
5306 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5307 D3DVIEWPORT7 *Data)
5309 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5310 HRESULT hr;
5312 TRACE("iface %p, viewport %p.\n", iface, Data);
5314 if(!Data)
5315 return DDERR_INVALIDPARAMS;
5317 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5318 wined3d_mutex_lock();
5319 hr = wined3d_device_set_viewport(This->wined3d_device, (struct wined3d_viewport *)Data);
5320 wined3d_mutex_unlock();
5322 return hr;
5325 static HRESULT WINAPI
5326 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5327 D3DVIEWPORT7 *Data)
5329 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5332 static HRESULT WINAPI
5333 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5334 D3DVIEWPORT7 *Data)
5336 HRESULT hr;
5337 WORD old_fpucw;
5339 old_fpucw = d3d_fpu_setup();
5340 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5341 set_fpu_control_word(old_fpucw);
5343 return hr;
5346 /*****************************************************************************
5347 * IDirect3DDevice::GetViewport
5349 * Returns the current viewport
5351 * Version 7
5353 * Params:
5354 * Data: D3D7Viewport structure to write the viewport information to
5356 * Returns:
5357 * D3D_OK on success
5358 * DDERR_INVALIDPARAMS if Data is NULL
5359 * For more details, see IWineD3DDevice::GetViewport
5361 *****************************************************************************/
5362 static HRESULT
5363 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5364 D3DVIEWPORT7 *Data)
5366 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5367 HRESULT hr;
5369 TRACE("iface %p, viewport %p.\n", iface, Data);
5371 if(!Data)
5372 return DDERR_INVALIDPARAMS;
5374 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5375 wined3d_mutex_lock();
5376 hr = wined3d_device_get_viewport(This->wined3d_device, (struct wined3d_viewport *)Data);
5377 wined3d_mutex_unlock();
5379 return hr_ddraw_from_wined3d(hr);
5382 static HRESULT WINAPI
5383 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5384 D3DVIEWPORT7 *Data)
5386 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5389 static HRESULT WINAPI
5390 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5391 D3DVIEWPORT7 *Data)
5393 HRESULT hr;
5394 WORD old_fpucw;
5396 old_fpucw = d3d_fpu_setup();
5397 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5398 set_fpu_control_word(old_fpucw);
5400 return hr;
5403 /*****************************************************************************
5404 * IDirect3DDevice7::SetMaterial
5406 * Sets the Material
5408 * Version 7
5410 * Params:
5411 * Mat: The material to set
5413 * Returns:
5414 * D3D_OK on success
5415 * DDERR_INVALIDPARAMS if Mat is NULL.
5416 * For more details, see IWineD3DDevice::SetMaterial
5418 *****************************************************************************/
5419 static HRESULT
5420 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5421 D3DMATERIAL7 *Mat)
5423 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5424 HRESULT hr;
5426 TRACE("iface %p, material %p.\n", iface, Mat);
5428 if (!Mat) return DDERR_INVALIDPARAMS;
5430 wined3d_mutex_lock();
5431 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5432 hr = wined3d_device_set_material(This->wined3d_device, (struct wined3d_material *)Mat);
5433 wined3d_mutex_unlock();
5435 return hr_ddraw_from_wined3d(hr);
5438 static HRESULT WINAPI
5439 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5440 D3DMATERIAL7 *Mat)
5442 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5445 static HRESULT WINAPI
5446 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5447 D3DMATERIAL7 *Mat)
5449 HRESULT hr;
5450 WORD old_fpucw;
5452 old_fpucw = d3d_fpu_setup();
5453 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5454 set_fpu_control_word(old_fpucw);
5456 return hr;
5459 /*****************************************************************************
5460 * IDirect3DDevice7::GetMaterial
5462 * Returns the current material
5464 * Version 7
5466 * Params:
5467 * Mat: D3DMATERIAL7 structure to write the material parameters to
5469 * Returns:
5470 * D3D_OK on success
5471 * DDERR_INVALIDPARAMS if Mat is NULL
5472 * For more details, see IWineD3DDevice::GetMaterial
5474 *****************************************************************************/
5475 static HRESULT
5476 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5477 D3DMATERIAL7 *Mat)
5479 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5480 HRESULT hr;
5482 TRACE("iface %p, material %p.\n", iface, Mat);
5484 wined3d_mutex_lock();
5485 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5486 hr = wined3d_device_get_material(This->wined3d_device, (struct wined3d_material *)Mat);
5487 wined3d_mutex_unlock();
5489 return hr_ddraw_from_wined3d(hr);
5492 static HRESULT WINAPI
5493 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5494 D3DMATERIAL7 *Mat)
5496 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5499 static HRESULT WINAPI
5500 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5501 D3DMATERIAL7 *Mat)
5503 HRESULT hr;
5504 WORD old_fpucw;
5506 old_fpucw = d3d_fpu_setup();
5507 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5508 set_fpu_control_word(old_fpucw);
5510 return hr;
5513 /*****************************************************************************
5514 * IDirect3DDevice7::SetLight
5516 * Assigns a light to a light index, but doesn't activate it yet.
5518 * Version 7, IDirect3DLight uses this method for older versions
5520 * Params:
5521 * LightIndex: The index of the new light
5522 * Light: A D3DLIGHT7 structure describing the light
5524 * Returns:
5525 * D3D_OK on success
5526 * For more details, see IWineD3DDevice::SetLight
5528 *****************************************************************************/
5529 static HRESULT
5530 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5531 DWORD LightIndex,
5532 D3DLIGHT7 *Light)
5534 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5535 HRESULT hr;
5537 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5539 wined3d_mutex_lock();
5540 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5541 hr = wined3d_device_set_light(This->wined3d_device, LightIndex, (struct wined3d_light *)Light);
5542 wined3d_mutex_unlock();
5544 return hr_ddraw_from_wined3d(hr);
5547 static HRESULT WINAPI
5548 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5549 DWORD LightIndex,
5550 D3DLIGHT7 *Light)
5552 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5555 static HRESULT WINAPI
5556 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5557 DWORD LightIndex,
5558 D3DLIGHT7 *Light)
5560 HRESULT hr;
5561 WORD old_fpucw;
5563 old_fpucw = d3d_fpu_setup();
5564 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5565 set_fpu_control_word(old_fpucw);
5567 return hr;
5570 /*****************************************************************************
5571 * IDirect3DDevice7::GetLight
5573 * Returns the light assigned to a light index
5575 * Params:
5576 * Light: Structure to write the light information to
5578 * Returns:
5579 * D3D_OK on success
5580 * DDERR_INVALIDPARAMS if Light is NULL
5581 * For details, see IWineD3DDevice::GetLight
5583 *****************************************************************************/
5584 static HRESULT
5585 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5586 DWORD LightIndex,
5587 D3DLIGHT7 *Light)
5589 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5590 HRESULT rc;
5592 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5594 wined3d_mutex_lock();
5595 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5596 rc = wined3d_device_get_light(This->wined3d_device, LightIndex, (struct wined3d_light *)Light);
5597 wined3d_mutex_unlock();
5599 /* Translate the result. WineD3D returns other values than D3D7 */
5600 return hr_ddraw_from_wined3d(rc);
5603 static HRESULT WINAPI
5604 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5605 DWORD LightIndex,
5606 D3DLIGHT7 *Light)
5608 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5611 static HRESULT WINAPI
5612 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5613 DWORD LightIndex,
5614 D3DLIGHT7 *Light)
5616 HRESULT hr;
5617 WORD old_fpucw;
5619 old_fpucw = d3d_fpu_setup();
5620 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5621 set_fpu_control_word(old_fpucw);
5623 return hr;
5626 /*****************************************************************************
5627 * IDirect3DDevice7::BeginStateBlock
5629 * Begins recording to a stateblock
5631 * Version 7
5633 * Returns:
5634 * D3D_OK on success
5635 * For details see IWineD3DDevice::BeginStateBlock
5637 *****************************************************************************/
5638 static HRESULT
5639 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5641 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5642 HRESULT hr;
5644 TRACE("iface %p.\n", iface);
5646 wined3d_mutex_lock();
5647 hr = wined3d_device_begin_stateblock(This->wined3d_device);
5648 wined3d_mutex_unlock();
5650 return hr_ddraw_from_wined3d(hr);
5653 static HRESULT WINAPI
5654 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5656 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5659 static HRESULT WINAPI
5660 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5662 HRESULT hr;
5663 WORD old_fpucw;
5665 old_fpucw = d3d_fpu_setup();
5666 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5667 set_fpu_control_word(old_fpucw);
5669 return hr;
5672 /*****************************************************************************
5673 * IDirect3DDevice7::EndStateBlock
5675 * Stops recording to a state block and returns the created stateblock
5676 * handle.
5678 * Version 7
5680 * Params:
5681 * BlockHandle: Address to store the stateblock's handle to
5683 * Returns:
5684 * D3D_OK on success
5685 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5686 * See IWineD3DDevice::EndStateBlock for more details
5688 *****************************************************************************/
5689 static HRESULT
5690 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5691 DWORD *BlockHandle)
5693 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5694 struct wined3d_stateblock *wined3d_sb;
5695 HRESULT hr;
5696 DWORD h;
5698 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5700 if(!BlockHandle)
5702 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5703 return DDERR_INVALIDPARAMS;
5706 wined3d_mutex_lock();
5708 hr = wined3d_device_end_stateblock(This->wined3d_device, &wined3d_sb);
5709 if (FAILED(hr))
5711 WARN("Failed to end stateblock, hr %#x.\n", hr);
5712 wined3d_mutex_unlock();
5713 *BlockHandle = 0;
5714 return hr_ddraw_from_wined3d(hr);
5717 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5718 if (h == DDRAW_INVALID_HANDLE)
5720 ERR("Failed to allocate a stateblock handle.\n");
5721 wined3d_stateblock_decref(wined3d_sb);
5722 wined3d_mutex_unlock();
5723 *BlockHandle = 0;
5724 return DDERR_OUTOFMEMORY;
5727 wined3d_mutex_unlock();
5728 *BlockHandle = h + 1;
5730 return hr_ddraw_from_wined3d(hr);
5733 static HRESULT WINAPI
5734 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5735 DWORD *BlockHandle)
5737 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5740 static HRESULT WINAPI
5741 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5742 DWORD *BlockHandle)
5744 HRESULT hr;
5745 WORD old_fpucw;
5747 old_fpucw = d3d_fpu_setup();
5748 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5749 set_fpu_control_word(old_fpucw);
5751 return hr;
5754 /*****************************************************************************
5755 * IDirect3DDevice7::PreLoad
5757 * Allows the app to signal that a texture will be used soon, to allow
5758 * the Direct3DDevice to load it to the video card in the meantime.
5760 * Version 7
5762 * Params:
5763 * Texture: The texture to preload
5765 * Returns:
5766 * D3D_OK on success
5767 * DDERR_INVALIDPARAMS if Texture is NULL
5768 * See IWineD3DSurface::PreLoad for details
5770 *****************************************************************************/
5771 static HRESULT
5772 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5773 IDirectDrawSurface7 *Texture)
5775 struct ddraw_surface *surface = unsafe_impl_from_IDirectDrawSurface7(Texture);
5777 TRACE("iface %p, texture %p.\n", iface, Texture);
5779 if(!Texture)
5780 return DDERR_INVALIDPARAMS;
5782 wined3d_mutex_lock();
5783 wined3d_surface_preload(surface->wined3d_surface);
5784 wined3d_mutex_unlock();
5786 return D3D_OK;
5789 static HRESULT WINAPI
5790 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5791 IDirectDrawSurface7 *Texture)
5793 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5796 static HRESULT WINAPI
5797 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5798 IDirectDrawSurface7 *Texture)
5800 HRESULT hr;
5801 WORD old_fpucw;
5803 old_fpucw = d3d_fpu_setup();
5804 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5805 set_fpu_control_word(old_fpucw);
5807 return hr;
5810 /*****************************************************************************
5811 * IDirect3DDevice7::ApplyStateBlock
5813 * Activates the state stored in a state block handle.
5815 * Params:
5816 * BlockHandle: The stateblock handle to activate
5818 * Returns:
5819 * D3D_OK on success
5820 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5822 *****************************************************************************/
5823 static HRESULT
5824 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5825 DWORD BlockHandle)
5827 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5828 struct wined3d_stateblock *wined3d_sb;
5829 HRESULT hr;
5831 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5833 wined3d_mutex_lock();
5834 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5835 if (!wined3d_sb)
5837 WARN("Invalid stateblock handle.\n");
5838 wined3d_mutex_unlock();
5839 return D3DERR_INVALIDSTATEBLOCK;
5842 hr = wined3d_stateblock_apply(wined3d_sb);
5843 wined3d_mutex_unlock();
5845 return hr_ddraw_from_wined3d(hr);
5848 static HRESULT WINAPI
5849 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5850 DWORD BlockHandle)
5852 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5855 static HRESULT WINAPI
5856 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5857 DWORD BlockHandle)
5859 HRESULT hr;
5860 WORD old_fpucw;
5862 old_fpucw = d3d_fpu_setup();
5863 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5864 set_fpu_control_word(old_fpucw);
5866 return hr;
5869 /*****************************************************************************
5870 * IDirect3DDevice7::CaptureStateBlock
5872 * Updates a stateblock's values to the values currently set for the device
5874 * Version 7
5876 * Params:
5877 * BlockHandle: Stateblock to update
5879 * Returns:
5880 * D3D_OK on success
5881 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5882 * See IWineD3DDevice::CaptureStateBlock for more details
5884 *****************************************************************************/
5885 static HRESULT
5886 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5887 DWORD BlockHandle)
5889 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5890 struct wined3d_stateblock *wined3d_sb;
5891 HRESULT hr;
5893 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5895 wined3d_mutex_lock();
5896 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5897 if (!wined3d_sb)
5899 WARN("Invalid stateblock handle.\n");
5900 wined3d_mutex_unlock();
5901 return D3DERR_INVALIDSTATEBLOCK;
5904 hr = wined3d_stateblock_capture(wined3d_sb);
5905 wined3d_mutex_unlock();
5907 return hr_ddraw_from_wined3d(hr);
5910 static HRESULT WINAPI
5911 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5912 DWORD BlockHandle)
5914 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5917 static HRESULT WINAPI
5918 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5919 DWORD BlockHandle)
5921 HRESULT hr;
5922 WORD old_fpucw;
5924 old_fpucw = d3d_fpu_setup();
5925 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5926 set_fpu_control_word(old_fpucw);
5928 return hr;
5931 /*****************************************************************************
5932 * IDirect3DDevice7::DeleteStateBlock
5934 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5936 * Version 7
5938 * Params:
5939 * BlockHandle: Stateblock handle to delete
5941 * Returns:
5942 * D3D_OK on success
5943 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5945 *****************************************************************************/
5946 static HRESULT
5947 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5948 DWORD BlockHandle)
5950 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5951 struct wined3d_stateblock *wined3d_sb;
5952 ULONG ref;
5954 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5956 wined3d_mutex_lock();
5958 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5959 if (!wined3d_sb)
5961 WARN("Invalid stateblock handle.\n");
5962 wined3d_mutex_unlock();
5963 return D3DERR_INVALIDSTATEBLOCK;
5966 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5968 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5971 wined3d_mutex_unlock();
5973 return D3D_OK;
5976 static HRESULT WINAPI
5977 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5978 DWORD BlockHandle)
5980 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5983 static HRESULT WINAPI
5984 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5985 DWORD BlockHandle)
5987 HRESULT hr;
5988 WORD old_fpucw;
5990 old_fpucw = d3d_fpu_setup();
5991 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5992 set_fpu_control_word(old_fpucw);
5994 return hr;
5997 /*****************************************************************************
5998 * IDirect3DDevice7::CreateStateBlock
6000 * Creates a new state block handle.
6002 * Version 7
6004 * Params:
6005 * Type: The state block type
6006 * BlockHandle: Address to write the created handle to
6008 * Returns:
6009 * D3D_OK on success
6010 * DDERR_INVALIDPARAMS if BlockHandle is NULL
6012 *****************************************************************************/
6013 static HRESULT
6014 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
6015 D3DSTATEBLOCKTYPE Type,
6016 DWORD *BlockHandle)
6018 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6019 struct wined3d_stateblock *wined3d_sb;
6020 HRESULT hr;
6021 DWORD h;
6023 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
6025 if(!BlockHandle)
6027 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
6028 return DDERR_INVALIDPARAMS;
6030 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
6031 Type != D3DSBT_VERTEXSTATE ) {
6032 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
6033 return DDERR_INVALIDPARAMS;
6036 wined3d_mutex_lock();
6038 /* The D3DSTATEBLOCKTYPE enum is fine here. */
6039 hr = wined3d_stateblock_create(This->wined3d_device, Type, &wined3d_sb);
6040 if (FAILED(hr))
6042 WARN("Failed to create stateblock, hr %#x.\n", hr);
6043 wined3d_mutex_unlock();
6044 return hr_ddraw_from_wined3d(hr);
6047 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
6048 if (h == DDRAW_INVALID_HANDLE)
6050 ERR("Failed to allocate stateblock handle.\n");
6051 wined3d_stateblock_decref(wined3d_sb);
6052 wined3d_mutex_unlock();
6053 return DDERR_OUTOFMEMORY;
6056 *BlockHandle = h + 1;
6057 wined3d_mutex_unlock();
6059 return hr_ddraw_from_wined3d(hr);
6062 static HRESULT WINAPI
6063 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
6064 D3DSTATEBLOCKTYPE Type,
6065 DWORD *BlockHandle)
6067 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6070 static HRESULT WINAPI
6071 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
6072 D3DSTATEBLOCKTYPE Type,
6073 DWORD *BlockHandle)
6075 HRESULT hr;
6076 WORD old_fpucw;
6078 old_fpucw = d3d_fpu_setup();
6079 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6080 set_fpu_control_word(old_fpucw);
6082 return hr;
6085 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6086 static BOOL is_mip_level_subset(struct ddraw_surface *dest, struct ddraw_surface *src)
6088 struct ddraw_surface *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, struct ddraw_surface *dest,
6135 struct ddraw_surface *src, const POINT *DestPoint, const RECT *SrcRect)
6137 struct ddraw_surface *src_level, *dest_level;
6138 IDirectDrawSurface7 *temp;
6139 DDSURFACEDESC2 ddsd;
6140 POINT point;
6141 RECT src_rect;
6142 HRESULT hr;
6143 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
6144 DWORD ckeyflag;
6145 DDCOLORKEY ddckey;
6147 /* Copy palette, if possible. */
6148 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
6149 IDirectDrawSurface7_GetPalette(&dest->IDirectDrawSurface7_iface, &pal);
6151 if (pal_src != NULL && pal != NULL)
6153 PALETTEENTRY palent[256];
6155 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
6156 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
6159 if (pal) IDirectDrawPalette_Release(pal);
6160 if (pal_src) IDirectDrawPalette_Release(pal_src);
6162 /* Copy colorkeys, if present. */
6163 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6165 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6167 if (SUCCEEDED(hr))
6169 IDirectDrawSurface7_SetColorKey(&dest->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6173 src_level = src;
6174 dest_level = dest;
6176 point = *DestPoint;
6177 src_rect = *SrcRect;
6179 for (;src_level && dest_level;)
6181 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6182 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6184 UINT src_w = src_rect.right - src_rect.left;
6185 UINT src_h = src_rect.bottom - src_rect.top;
6186 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
6188 if (FAILED(hr = wined3d_surface_blt(dest_level->wined3d_surface, &dst_rect,
6189 src_level->wined3d_surface, &src_rect, 0, NULL, WINED3D_TEXF_POINT)))
6190 ERR("Blit failed, hr %#x.\n", hr);
6192 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6193 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6194 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6196 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6198 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6201 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6202 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6203 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6205 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6207 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6209 point.x /= 2;
6210 point.y /= 2;
6212 src_rect.top /= 2;
6213 src_rect.left /= 2;
6214 src_rect.right = (src_rect.right + 1) / 2;
6215 src_rect.bottom = (src_rect.bottom + 1) / 2;
6218 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6219 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6222 /*****************************************************************************
6223 * IDirect3DDevice7::Load
6225 * Loads a rectangular area from the source into the destination texture.
6226 * It can also copy the source to the faces of a cubic environment map
6228 * Version 7
6230 * Params:
6231 * DestTex: Destination texture
6232 * DestPoint: Point in the destination where the source image should be
6233 * written to
6234 * SrcTex: Source texture
6235 * SrcRect: Source rectangle
6236 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6237 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6238 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6240 * Returns:
6241 * D3D_OK on success
6242 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6245 *****************************************************************************/
6247 static HRESULT
6248 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6249 IDirectDrawSurface7 *DestTex,
6250 POINT *DestPoint,
6251 IDirectDrawSurface7 *SrcTex,
6252 RECT *SrcRect,
6253 DWORD Flags)
6255 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6256 struct ddraw_surface *dest = unsafe_impl_from_IDirectDrawSurface7(DestTex);
6257 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface7(SrcTex);
6258 POINT destpoint;
6259 RECT srcrect;
6261 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6262 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6264 if( (!src) || (!dest) )
6265 return DDERR_INVALIDPARAMS;
6267 wined3d_mutex_lock();
6269 if (SrcRect) srcrect = *SrcRect;
6270 else
6272 srcrect.left = srcrect.top = 0;
6273 srcrect.right = src->surface_desc.dwWidth;
6274 srcrect.bottom = src->surface_desc.dwHeight;
6277 if (DestPoint) destpoint = *DestPoint;
6278 else
6280 destpoint.x = destpoint.y = 0;
6282 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6283 * destination can be a subset of mip levels, in which case actual coordinates used
6284 * for it may be divided. If any dimension of dest is larger than source, it can't be
6285 * mip level subset, so an error can be returned early.
6287 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6288 srcrect.right > src->surface_desc.dwWidth ||
6289 srcrect.bottom > src->surface_desc.dwHeight ||
6290 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6291 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6292 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6293 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6295 wined3d_mutex_unlock();
6296 return DDERR_INVALIDPARAMS;
6299 /* Must be top level surfaces. */
6300 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6301 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6303 wined3d_mutex_unlock();
6304 return DDERR_INVALIDPARAMS;
6307 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6309 struct ddraw_surface *src_face, *dest_face;
6310 DWORD src_face_flag, dest_face_flag;
6311 IDirectDrawSurface7 *temp;
6312 DDSURFACEDESC2 ddsd;
6313 int i;
6315 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6317 wined3d_mutex_unlock();
6318 return DDERR_INVALIDPARAMS;
6321 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6322 * time it's actual surface loading. */
6323 for (i = 0; i < 2; i++)
6325 dest_face = dest;
6326 src_face = src;
6328 for (;dest_face && src_face;)
6330 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6331 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6333 if (src_face_flag == dest_face_flag)
6335 if (i == 0)
6337 /* Destination mip levels must be subset of source mip levels. */
6338 if (!is_mip_level_subset(dest_face, src_face))
6340 wined3d_mutex_unlock();
6341 return DDERR_INVALIDPARAMS;
6344 else if (Flags & dest_face_flag)
6346 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6349 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6351 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6352 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6353 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6355 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6357 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6359 else
6361 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6363 src_face = NULL;
6367 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6369 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6370 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6371 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6373 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6375 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6377 else
6379 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6381 dest_face = NULL;
6385 if (i == 0)
6387 /* Native returns error if src faces are not subset of dest faces. */
6388 if (src_face)
6390 wined3d_mutex_unlock();
6391 return DDERR_INVALIDPARAMS;
6396 wined3d_mutex_unlock();
6397 return D3D_OK;
6399 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6401 wined3d_mutex_unlock();
6402 return DDERR_INVALIDPARAMS;
6405 /* Handle non cube map textures. */
6407 /* Destination mip levels must be subset of source mip levels. */
6408 if (!is_mip_level_subset(dest, src))
6410 wined3d_mutex_unlock();
6411 return DDERR_INVALIDPARAMS;
6414 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6416 wined3d_mutex_unlock();
6418 return D3D_OK;
6421 static HRESULT WINAPI
6422 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6423 IDirectDrawSurface7 *DestTex,
6424 POINT *DestPoint,
6425 IDirectDrawSurface7 *SrcTex,
6426 RECT *SrcRect,
6427 DWORD Flags)
6429 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6432 static HRESULT WINAPI
6433 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6434 IDirectDrawSurface7 *DestTex,
6435 POINT *DestPoint,
6436 IDirectDrawSurface7 *SrcTex,
6437 RECT *SrcRect,
6438 DWORD Flags)
6440 HRESULT hr;
6441 WORD old_fpucw;
6443 old_fpucw = d3d_fpu_setup();
6444 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6445 set_fpu_control_word(old_fpucw);
6447 return hr;
6450 /*****************************************************************************
6451 * IDirect3DDevice7::LightEnable
6453 * Enables or disables a light
6455 * Version 7, IDirect3DLight uses this method too.
6457 * Params:
6458 * LightIndex: The index of the light to enable / disable
6459 * Enable: Enable or disable the light
6461 * Returns:
6462 * D3D_OK on success
6463 * For more details, see IWineD3DDevice::SetLightEnable
6465 *****************************************************************************/
6466 static HRESULT
6467 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6468 DWORD LightIndex,
6469 BOOL Enable)
6471 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6472 HRESULT hr;
6474 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6476 wined3d_mutex_lock();
6477 hr = wined3d_device_set_light_enable(This->wined3d_device, LightIndex, Enable);
6478 wined3d_mutex_unlock();
6480 return hr_ddraw_from_wined3d(hr);
6483 static HRESULT WINAPI
6484 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6485 DWORD LightIndex,
6486 BOOL Enable)
6488 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6491 static HRESULT WINAPI
6492 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6493 DWORD LightIndex,
6494 BOOL Enable)
6496 HRESULT hr;
6497 WORD old_fpucw;
6499 old_fpucw = d3d_fpu_setup();
6500 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6501 set_fpu_control_word(old_fpucw);
6503 return hr;
6506 /*****************************************************************************
6507 * IDirect3DDevice7::GetLightEnable
6509 * Retrieves if the light with the given index is enabled or not
6511 * Version 7
6513 * Params:
6514 * LightIndex: Index of desired light
6515 * Enable: Pointer to a BOOL which contains the result
6517 * Returns:
6518 * D3D_OK on success
6519 * DDERR_INVALIDPARAMS if Enable is NULL
6520 * See IWineD3DDevice::GetLightEnable for more details
6522 *****************************************************************************/
6523 static HRESULT
6524 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6525 DWORD LightIndex,
6526 BOOL* Enable)
6528 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6529 HRESULT hr;
6531 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6533 if(!Enable)
6534 return DDERR_INVALIDPARAMS;
6536 wined3d_mutex_lock();
6537 hr = wined3d_device_get_light_enable(This->wined3d_device, LightIndex, Enable);
6538 wined3d_mutex_unlock();
6540 return hr_ddraw_from_wined3d(hr);
6543 static HRESULT WINAPI
6544 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6545 DWORD LightIndex,
6546 BOOL* Enable)
6548 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6551 static HRESULT WINAPI
6552 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6553 DWORD LightIndex,
6554 BOOL* Enable)
6556 HRESULT hr;
6557 WORD old_fpucw;
6559 old_fpucw = d3d_fpu_setup();
6560 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6561 set_fpu_control_word(old_fpucw);
6563 return hr;
6566 /*****************************************************************************
6567 * IDirect3DDevice7::SetClipPlane
6569 * Sets custom clipping plane
6571 * Version 7
6573 * Params:
6574 * Index: The index of the clipping plane
6575 * PlaneEquation: An equation defining the clipping plane
6577 * Returns:
6578 * D3D_OK on success
6579 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6580 * See IWineD3DDevice::SetClipPlane for more details
6582 *****************************************************************************/
6583 static HRESULT
6584 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6585 DWORD Index,
6586 D3DVALUE* PlaneEquation)
6588 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6589 HRESULT hr;
6591 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6593 if(!PlaneEquation)
6594 return DDERR_INVALIDPARAMS;
6596 wined3d_mutex_lock();
6597 hr = wined3d_device_set_clip_plane(This->wined3d_device, Index, PlaneEquation);
6598 wined3d_mutex_unlock();
6600 return hr;
6603 static HRESULT WINAPI
6604 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6605 DWORD Index,
6606 D3DVALUE* PlaneEquation)
6608 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6611 static HRESULT WINAPI
6612 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6613 DWORD Index,
6614 D3DVALUE* PlaneEquation)
6616 HRESULT hr;
6617 WORD old_fpucw;
6619 old_fpucw = d3d_fpu_setup();
6620 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6621 set_fpu_control_word(old_fpucw);
6623 return hr;
6626 /*****************************************************************************
6627 * IDirect3DDevice7::GetClipPlane
6629 * Returns the clipping plane with a specific index
6631 * Params:
6632 * Index: The index of the desired plane
6633 * PlaneEquation: Address to store the plane equation to
6635 * Returns:
6636 * D3D_OK on success
6637 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6638 * See IWineD3DDevice::GetClipPlane for more details
6640 *****************************************************************************/
6641 static HRESULT
6642 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6643 DWORD Index,
6644 D3DVALUE* PlaneEquation)
6646 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6647 HRESULT hr;
6649 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6651 if(!PlaneEquation)
6652 return DDERR_INVALIDPARAMS;
6654 wined3d_mutex_lock();
6655 hr = wined3d_device_get_clip_plane(This->wined3d_device, Index, PlaneEquation);
6656 wined3d_mutex_unlock();
6658 return hr;
6661 static HRESULT WINAPI
6662 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6663 DWORD Index,
6664 D3DVALUE* PlaneEquation)
6666 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6669 static HRESULT WINAPI
6670 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6671 DWORD Index,
6672 D3DVALUE* PlaneEquation)
6674 HRESULT hr;
6675 WORD old_fpucw;
6677 old_fpucw = d3d_fpu_setup();
6678 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6679 set_fpu_control_word(old_fpucw);
6681 return hr;
6684 /*****************************************************************************
6685 * IDirect3DDevice7::GetInfo
6687 * Retrieves some information about the device. The DirectX sdk says that
6688 * this version returns S_FALSE for all retail builds of DirectX, that's what
6689 * this implementation does.
6691 * Params:
6692 * DevInfoID: Information type requested
6693 * DevInfoStruct: Pointer to a structure to store the info to
6694 * Size: Size of the structure
6696 * Returns:
6697 * S_FALSE, because it's a non-debug driver
6699 *****************************************************************************/
6700 static HRESULT WINAPI
6701 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6702 DWORD DevInfoID,
6703 void *DevInfoStruct,
6704 DWORD Size)
6706 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6707 iface, DevInfoID, DevInfoStruct, Size);
6709 if (TRACE_ON(ddraw))
6711 TRACE(" info requested : ");
6712 switch (DevInfoID)
6714 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6715 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6716 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6717 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6721 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6724 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6725 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6726 * are not duplicated.
6728 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6729 * has already been setup for optimal d3d operation.
6731 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6732 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6733 * by Sacrifice (game). */
6734 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6736 /*** IUnknown Methods ***/
6737 IDirect3DDeviceImpl_7_QueryInterface,
6738 IDirect3DDeviceImpl_7_AddRef,
6739 IDirect3DDeviceImpl_7_Release,
6740 /*** IDirect3DDevice7 ***/
6741 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6742 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6743 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6744 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6745 IDirect3DDeviceImpl_7_GetDirect3D,
6746 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6747 IDirect3DDeviceImpl_7_GetRenderTarget,
6748 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6749 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6750 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6751 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6752 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6753 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6754 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6755 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6756 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6757 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6758 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6759 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6760 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6761 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6762 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6763 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6764 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6765 IDirect3DDeviceImpl_7_SetClipStatus,
6766 IDirect3DDeviceImpl_7_GetClipStatus,
6767 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6768 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6769 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6770 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6771 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6772 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6773 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6774 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6775 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6776 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6777 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6778 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6779 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6780 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6781 IDirect3DDeviceImpl_7_Load_FPUSetup,
6782 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6783 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6784 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6785 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6786 IDirect3DDeviceImpl_7_GetInfo
6789 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6791 /*** IUnknown Methods ***/
6792 IDirect3DDeviceImpl_7_QueryInterface,
6793 IDirect3DDeviceImpl_7_AddRef,
6794 IDirect3DDeviceImpl_7_Release,
6795 /*** IDirect3DDevice7 ***/
6796 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6797 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6798 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6799 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6800 IDirect3DDeviceImpl_7_GetDirect3D,
6801 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6802 IDirect3DDeviceImpl_7_GetRenderTarget,
6803 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6804 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6805 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6806 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6807 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6808 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6809 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6810 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6811 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6812 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6813 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6814 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6815 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6816 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6817 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6818 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6819 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6820 IDirect3DDeviceImpl_7_SetClipStatus,
6821 IDirect3DDeviceImpl_7_GetClipStatus,
6822 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6823 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6824 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6825 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6826 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6827 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6828 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6829 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6830 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6831 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6832 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6833 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6834 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6835 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6836 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6837 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6838 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6839 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6840 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6841 IDirect3DDeviceImpl_7_GetInfo
6844 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6846 /*** IUnknown Methods ***/
6847 IDirect3DDeviceImpl_3_QueryInterface,
6848 IDirect3DDeviceImpl_3_AddRef,
6849 IDirect3DDeviceImpl_3_Release,
6850 /*** IDirect3DDevice3 ***/
6851 IDirect3DDeviceImpl_3_GetCaps,
6852 IDirect3DDeviceImpl_3_GetStats,
6853 IDirect3DDeviceImpl_3_AddViewport,
6854 IDirect3DDeviceImpl_3_DeleteViewport,
6855 IDirect3DDeviceImpl_3_NextViewport,
6856 IDirect3DDeviceImpl_3_EnumTextureFormats,
6857 IDirect3DDeviceImpl_3_BeginScene,
6858 IDirect3DDeviceImpl_3_EndScene,
6859 IDirect3DDeviceImpl_3_GetDirect3D,
6860 IDirect3DDeviceImpl_3_SetCurrentViewport,
6861 IDirect3DDeviceImpl_3_GetCurrentViewport,
6862 IDirect3DDeviceImpl_3_SetRenderTarget,
6863 IDirect3DDeviceImpl_3_GetRenderTarget,
6864 IDirect3DDeviceImpl_3_Begin,
6865 IDirect3DDeviceImpl_3_BeginIndexed,
6866 IDirect3DDeviceImpl_3_Vertex,
6867 IDirect3DDeviceImpl_3_Index,
6868 IDirect3DDeviceImpl_3_End,
6869 IDirect3DDeviceImpl_3_GetRenderState,
6870 IDirect3DDeviceImpl_3_SetRenderState,
6871 IDirect3DDeviceImpl_3_GetLightState,
6872 IDirect3DDeviceImpl_3_SetLightState,
6873 IDirect3DDeviceImpl_3_SetTransform,
6874 IDirect3DDeviceImpl_3_GetTransform,
6875 IDirect3DDeviceImpl_3_MultiplyTransform,
6876 IDirect3DDeviceImpl_3_DrawPrimitive,
6877 IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6878 IDirect3DDeviceImpl_3_SetClipStatus,
6879 IDirect3DDeviceImpl_3_GetClipStatus,
6880 IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6881 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6882 IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6883 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6884 IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6885 IDirect3DDeviceImpl_3_GetTexture,
6886 IDirect3DDeviceImpl_3_SetTexture,
6887 IDirect3DDeviceImpl_3_GetTextureStageState,
6888 IDirect3DDeviceImpl_3_SetTextureStageState,
6889 IDirect3DDeviceImpl_3_ValidateDevice
6892 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6894 /*** IUnknown Methods ***/
6895 IDirect3DDeviceImpl_2_QueryInterface,
6896 IDirect3DDeviceImpl_2_AddRef,
6897 IDirect3DDeviceImpl_2_Release,
6898 /*** IDirect3DDevice2 ***/
6899 IDirect3DDeviceImpl_2_GetCaps,
6900 IDirect3DDeviceImpl_2_SwapTextureHandles,
6901 IDirect3DDeviceImpl_2_GetStats,
6902 IDirect3DDeviceImpl_2_AddViewport,
6903 IDirect3DDeviceImpl_2_DeleteViewport,
6904 IDirect3DDeviceImpl_2_NextViewport,
6905 IDirect3DDeviceImpl_2_EnumTextureFormats,
6906 IDirect3DDeviceImpl_2_BeginScene,
6907 IDirect3DDeviceImpl_2_EndScene,
6908 IDirect3DDeviceImpl_2_GetDirect3D,
6909 IDirect3DDeviceImpl_2_SetCurrentViewport,
6910 IDirect3DDeviceImpl_2_GetCurrentViewport,
6911 IDirect3DDeviceImpl_2_SetRenderTarget,
6912 IDirect3DDeviceImpl_2_GetRenderTarget,
6913 IDirect3DDeviceImpl_2_Begin,
6914 IDirect3DDeviceImpl_2_BeginIndexed,
6915 IDirect3DDeviceImpl_2_Vertex,
6916 IDirect3DDeviceImpl_2_Index,
6917 IDirect3DDeviceImpl_2_End,
6918 IDirect3DDeviceImpl_2_GetRenderState,
6919 IDirect3DDeviceImpl_2_SetRenderState,
6920 IDirect3DDeviceImpl_2_GetLightState,
6921 IDirect3DDeviceImpl_2_SetLightState,
6922 IDirect3DDeviceImpl_2_SetTransform,
6923 IDirect3DDeviceImpl_2_GetTransform,
6924 IDirect3DDeviceImpl_2_MultiplyTransform,
6925 IDirect3DDeviceImpl_2_DrawPrimitive,
6926 IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6927 IDirect3DDeviceImpl_2_SetClipStatus,
6928 IDirect3DDeviceImpl_2_GetClipStatus
6931 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6933 /*** IUnknown Methods ***/
6934 IDirect3DDeviceImpl_1_QueryInterface,
6935 IDirect3DDeviceImpl_1_AddRef,
6936 IDirect3DDeviceImpl_1_Release,
6937 /*** IDirect3DDevice1 ***/
6938 IDirect3DDeviceImpl_1_Initialize,
6939 IDirect3DDeviceImpl_1_GetCaps,
6940 IDirect3DDeviceImpl_1_SwapTextureHandles,
6941 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6942 IDirect3DDeviceImpl_1_GetStats,
6943 IDirect3DDeviceImpl_1_Execute,
6944 IDirect3DDeviceImpl_1_AddViewport,
6945 IDirect3DDeviceImpl_1_DeleteViewport,
6946 IDirect3DDeviceImpl_1_NextViewport,
6947 IDirect3DDeviceImpl_1_Pick,
6948 IDirect3DDeviceImpl_1_GetPickRecords,
6949 IDirect3DDeviceImpl_1_EnumTextureFormats,
6950 IDirect3DDeviceImpl_1_CreateMatrix,
6951 IDirect3DDeviceImpl_1_SetMatrix,
6952 IDirect3DDeviceImpl_1_GetMatrix,
6953 IDirect3DDeviceImpl_1_DeleteMatrix,
6954 IDirect3DDeviceImpl_1_BeginScene,
6955 IDirect3DDeviceImpl_1_EndScene,
6956 IDirect3DDeviceImpl_1_GetDirect3D
6959 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6961 if (!iface) return NULL;
6962 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6963 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice7_iface);
6966 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6968 if (!iface) return NULL;
6969 assert(iface->lpVtbl == &d3d_device3_vtbl);
6970 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice3_iface);
6973 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6975 if (!iface) return NULL;
6976 assert(iface->lpVtbl == &d3d_device2_vtbl);
6977 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice2_iface);
6980 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6982 if (!iface) return NULL;
6983 assert(iface->lpVtbl == &d3d_device1_vtbl);
6984 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice_iface);
6987 /*****************************************************************************
6988 * IDirect3DDeviceImpl_UpdateDepthStencil
6990 * Checks the current render target for attached depth stencils and sets the
6991 * WineD3D depth stencil accordingly.
6993 * Returns:
6994 * The depth stencil state to set if creating the device
6996 *****************************************************************************/
6997 enum wined3d_depth_buffer_type IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6999 IDirectDrawSurface7 *depthStencil = NULL;
7000 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
7001 struct ddraw_surface *dsi;
7003 IDirectDrawSurface7_GetAttachedSurface(&This->target->IDirectDrawSurface7_iface, &depthcaps, &depthStencil);
7004 if(!depthStencil)
7006 TRACE("Setting wined3d depth stencil to NULL\n");
7007 wined3d_device_set_depth_stencil(This->wined3d_device, NULL);
7008 return WINED3D_ZB_FALSE;
7011 dsi = impl_from_IDirectDrawSurface7(depthStencil);
7012 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
7013 wined3d_device_set_depth_stencil(This->wined3d_device, dsi->wined3d_surface);
7015 IDirectDrawSurface7_Release(depthStencil);
7016 return WINED3D_ZB_TRUE;
7019 static HRESULT d3d_device_init(IDirect3DDeviceImpl *device, struct ddraw *ddraw,
7020 struct ddraw_surface *target, UINT version)
7022 static const D3DMATRIX ident =
7024 1.0f, 0.0f, 0.0f, 0.0f,
7025 0.0f, 1.0f, 0.0f, 0.0f,
7026 0.0f, 0.0f, 1.0f, 0.0f,
7027 0.0f, 0.0f, 0.0f, 1.0f,
7029 HRESULT hr;
7031 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
7032 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
7033 else
7034 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
7036 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
7037 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
7038 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
7039 device->ref = 1;
7040 device->version = version;
7041 device->ddraw = ddraw;
7042 device->target = target;
7043 list_init(&device->viewport_list);
7045 if (!ddraw_handle_table_init(&device->handle_table, 64))
7047 ERR("Failed to initialize handle table.\n");
7048 return DDERR_OUTOFMEMORY;
7051 device->legacyTextureBlending = FALSE;
7052 device->legacy_projection = ident;
7053 device->legacy_clipspace = ident;
7055 /* Create an index buffer, it's needed for indexed drawing */
7056 hr = wined3d_buffer_create_ib(ddraw->wined3d_device, 0x40000 /* Length. Don't know how long it should be */,
7057 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3D_POOL_DEFAULT, NULL,
7058 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
7059 if (FAILED(hr))
7061 ERR("Failed to create an index buffer, hr %#x.\n", hr);
7062 ddraw_handle_table_destroy(&device->handle_table);
7063 return hr;
7066 /* This is for convenience. */
7067 device->wined3d_device = ddraw->wined3d_device;
7068 wined3d_device_incref(ddraw->wined3d_device);
7070 /* Render to the back buffer */
7071 hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
7072 if (FAILED(hr))
7074 ERR("Failed to set render target, hr %#x.\n", hr);
7075 wined3d_buffer_decref(device->indexbuffer);
7076 ddraw_handle_table_destroy(&device->handle_table);
7077 return hr;
7080 /* FIXME: This is broken. The target AddRef() makes some sense, because
7081 * we store a pointer during initialization, but then that's also where
7082 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
7083 /* AddRef the render target. Also AddRef the render target from ddraw,
7084 * because if it is released before the app releases the D3D device, the
7085 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
7087 * In most cases, those surfaces are the same anyway, but this will simply
7088 * add another ref which is released when the device is destroyed. */
7089 IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
7091 ddraw->d3ddevice = device;
7093 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE,
7094 IDirect3DDeviceImpl_UpdateDepthStencil(device));
7096 return D3D_OK;
7099 HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target,
7100 UINT version, IDirect3DDeviceImpl **device)
7102 IDirect3DDeviceImpl *object;
7103 HRESULT hr;
7105 TRACE("ddraw %p, target %p, version %u, device %p.\n", ddraw, target, version, device);
7107 if (DefaultSurfaceType != WINED3D_SURFACE_TYPE_OPENGL)
7109 ERR_(winediag)("The application wants to create a Direct3D device, "
7110 "but the current DirectDrawRenderer does not support this.\n");
7112 return DDERR_NO3D;
7115 if (ddraw->d3ddevice)
7117 FIXME("Only one Direct3D device per DirectDraw object supported.\n");
7118 return DDERR_INVALIDPARAMS;
7121 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
7122 if (!object)
7124 ERR("Failed to allocate device memory.\n");
7125 return DDERR_OUTOFMEMORY;
7128 hr = d3d_device_init(object, ddraw, target, version);
7129 if (FAILED(hr))
7131 WARN("Failed to initialize device, hr %#x.\n", hr);
7132 HeapFree(GetProcessHeap(), 0, object);
7133 return hr;
7136 TRACE("Created device %p.\n", object);
7137 *device = object;
7139 return D3D_OK;