wined3d: Get rid of the WineDirect3DStridedData typedef.
[wine/multimedia.git] / dlls / ddraw / device.c
blob15ad7e487b3050ffc2cce6d70690fddd09fb165f
1 /*
2 * Copyright (c) 1998-2004 Lionel Ulmer
3 * Copyright (c) 2002-2005 Christian Costa
4 * Copyright (c) 2006 Stefan Dösinger
5 * Copyright (c) 2008 Alexander Dorofeyev
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * IDirect3DDevice implementation, version 1, 2, 3 and 7. Rendering is relayed
22 * to WineD3D, some minimal DirectDraw specific management is handled here.
23 * The Direct3DDevice is NOT the parent of the WineD3DDevice, because d3d
24 * is initialized when DirectDraw creates the primary surface.
25 * Some type management is necessary, because some D3D types changed between
26 * D3D7 and D3D9.
30 #include "config.h"
31 #include "wine/port.h"
33 #include "ddraw_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
37 /* The device ID */
38 const GUID IID_D3DDEVICE_WineD3D = {
39 0xaef72d43,
40 0xb09a,
41 0x4b7b,
42 { 0xb7,0x98,0xc6,0x8a,0x77,0x2d,0x72,0x2a }
45 static inline void set_fpu_control_word(WORD fpucw)
47 #if defined(__i386__) && defined(__GNUC__)
48 __asm__ volatile ("fldcw %0" : : "m" (fpucw));
49 #elif defined(__i386__) && defined(_MSC_VER)
50 __asm fldcw fpucw;
51 #endif
54 static inline WORD d3d_fpu_setup(void)
56 WORD oldcw;
58 #if defined(__i386__) && defined(__GNUC__)
59 __asm__ volatile ("fnstcw %0" : "=m" (oldcw));
60 #elif defined(__i386__) && defined(_MSC_VER)
61 __asm fnstcw oldcw;
62 #else
63 static BOOL warned = FALSE;
64 if(!warned)
66 FIXME("FPUPRESERVE not implemented for this platform / compiler\n");
67 warned = TRUE;
69 return 0;
70 #endif
72 set_fpu_control_word(0x37f);
74 return oldcw;
77 /*****************************************************************************
78 * IUnknown Methods. Common for Version 1, 2, 3 and 7
79 *****************************************************************************/
81 /*****************************************************************************
82 * IDirect3DDevice7::QueryInterface
84 * Used to query other interfaces from a Direct3DDevice interface.
85 * It can return interface pointers to all Direct3DDevice versions as well
86 * as IDirectDraw and IDirect3D. For a link to QueryInterface
87 * rules see ddraw.c, IDirectDraw7::QueryInterface
89 * Exists in Version 1, 2, 3 and 7
91 * Params:
92 * refiid: Interface ID queried for
93 * obj: Used to return the interface pointer
95 * Returns:
96 * D3D_OK or E_NOINTERFACE
98 *****************************************************************************/
99 static HRESULT WINAPI
100 IDirect3DDeviceImpl_7_QueryInterface(IDirect3DDevice7 *iface,
101 REFIID refiid,
102 void **obj)
104 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
106 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(refiid), obj);
108 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
109 *obj = NULL;
111 if(!refiid)
112 return DDERR_INVALIDPARAMS;
114 if ( IsEqualGUID( &IID_IUnknown, refiid ) )
116 *obj = iface;
119 /* Check DirectDraw Interfaces. */
120 else if( IsEqualGUID( &IID_IDirectDraw7, refiid ) )
122 *obj = &This->ddraw->IDirectDraw7_iface;
123 TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
125 else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
127 *obj = &This->ddraw->IDirectDraw4_iface;
128 TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
130 else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
132 *obj = &This->ddraw->IDirectDraw2_iface;
133 TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
135 else if( IsEqualGUID( &IID_IDirectDraw, refiid ) )
137 *obj = &This->ddraw->IDirectDraw_iface;
138 TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
141 /* Direct3D */
142 else if ( IsEqualGUID( &IID_IDirect3D , refiid ) )
144 *obj = &This->ddraw->IDirect3D_iface;
145 TRACE("(%p) Returning IDirect3D interface at %p\n", This, *obj);
147 else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) )
149 *obj = &This->ddraw->IDirect3D2_iface;
150 TRACE("(%p) Returning IDirect3D2 interface at %p\n", This, *obj);
152 else if ( IsEqualGUID( &IID_IDirect3D3 , refiid ) )
154 *obj = &This->ddraw->IDirect3D3_iface;
155 TRACE("(%p) Returning IDirect3D3 interface at %p\n", This, *obj);
157 else if ( IsEqualGUID( &IID_IDirect3D7 , refiid ) )
159 *obj = &This->ddraw->IDirect3D7_iface;
160 TRACE("(%p) Returning IDirect3D7 interface at %p\n", This, *obj);
163 /* Direct3DDevice */
164 else if ( IsEqualGUID( &IID_IDirect3DDevice , refiid ) )
166 *obj = &This->IDirect3DDevice_iface;
167 TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
169 else if ( IsEqualGUID( &IID_IDirect3DDevice2 , refiid ) ) {
170 *obj = &This->IDirect3DDevice2_iface;
171 TRACE("(%p) Returning IDirect3DDevice2 interface at %p\n", This, *obj);
173 else if ( IsEqualGUID( &IID_IDirect3DDevice3 , refiid ) ) {
174 *obj = &This->IDirect3DDevice3_iface;
175 TRACE("(%p) Returning IDirect3DDevice3 interface at %p\n", This, *obj);
177 else if ( IsEqualGUID( &IID_IDirect3DDevice7 , refiid ) ) {
178 *obj = This;
179 TRACE("(%p) Returning IDirect3DDevice7 interface at %p\n", This, *obj);
182 /* Unknown interface */
183 else
185 ERR("(%p)->(%s, %p): No interface found\n", This, debugstr_guid(refiid), obj);
186 return E_NOINTERFACE;
189 /* AddRef the returned interface */
190 IUnknown_AddRef( (IUnknown *) *obj);
191 return D3D_OK;
194 static HRESULT WINAPI IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface, REFIID riid,
195 void **obj)
197 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
198 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
200 return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obj);
203 static HRESULT WINAPI IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface, REFIID riid,
204 void **obj)
206 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
207 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
209 return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obj);
212 static HRESULT WINAPI IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface, REFIID riid,
213 void **obp)
215 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
216 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
218 return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obp);
221 /*****************************************************************************
222 * IDirect3DDevice7::AddRef
224 * Increases the refcount....
225 * The most exciting Method, definitely
227 * Exists in Version 1, 2, 3 and 7
229 * Returns:
230 * The new refcount
232 *****************************************************************************/
233 static ULONG WINAPI
234 IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
236 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
237 ULONG ref = InterlockedIncrement(&This->ref);
239 TRACE("%p increasing refcount to %u.\n", This, ref);
241 return ref;
244 static ULONG WINAPI IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
246 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
247 TRACE("iface %p.\n", iface);
249 return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
252 static ULONG WINAPI IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
254 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
255 TRACE("iface %p.\n", iface);
257 return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
260 static ULONG WINAPI IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
262 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
263 TRACE("iface %p.\n", iface);
265 return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
268 /*****************************************************************************
269 * IDirect3DDevice7::Release
271 * Decreases the refcount of the interface
272 * When the refcount is reduced to 0, the object is destroyed.
274 * Exists in Version 1, 2, 3 and 7
276 * Returns:d
277 * The new refcount
279 *****************************************************************************/
280 static ULONG WINAPI
281 IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
283 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
284 ULONG ref = InterlockedDecrement(&This->ref);
286 TRACE("%p decreasing refcount to %u.\n", This, ref);
288 /* This method doesn't destroy the WineD3DDevice, because it's still in use for
289 * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
290 * when the render target is released
292 if (ref == 0)
294 DWORD i;
296 wined3d_mutex_lock();
298 /* There is no need to unset any resources here, wined3d will take
299 * care of that on Uninit3D(). */
301 /* Free the index buffer. */
302 wined3d_buffer_decref(This->indexbuffer);
304 /* Set the device up to render to the front buffer since the back
305 * buffer will vanish soon. */
306 wined3d_device_set_render_target(This->wined3d_device, 0,
307 This->ddraw->wined3d_frontbuffer, TRUE);
309 /* Release the WineD3DDevice. This won't destroy it. */
310 if (!wined3d_device_decref(This->wined3d_device))
311 ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This->wined3d_device);
313 /* The texture handles should be unset by now, but there might be some bits
314 * missing in our reference counting(needs test). Do a sanity check. */
315 for (i = 0; i < This->handle_table.entry_count; ++i)
317 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
319 switch (entry->type)
321 case DDRAW_HANDLE_FREE:
322 break;
324 case DDRAW_HANDLE_MATERIAL:
326 IDirect3DMaterialImpl *m = entry->object;
327 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
328 m->Handle = 0;
329 break;
332 case DDRAW_HANDLE_MATRIX:
334 /* No FIXME here because this might happen because of sloppy applications. */
335 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
336 IDirect3DDevice_DeleteMatrix(&This->IDirect3DDevice_iface, i + 1);
337 break;
340 case DDRAW_HANDLE_STATEBLOCK:
342 /* No FIXME here because this might happen because of sloppy applications. */
343 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
344 IDirect3DDevice7_DeleteStateBlock(iface, i + 1);
345 break;
348 case DDRAW_HANDLE_SURFACE:
350 IDirectDrawSurfaceImpl *surf = entry->object;
351 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
352 surf->Handle = 0;
353 break;
356 default:
357 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
358 break;
362 ddraw_handle_table_destroy(&This->handle_table);
364 TRACE("Releasing target %p.\n", This->target);
365 /* Release the render target and the WineD3D render target
366 * (See IDirect3D7::CreateDevice for more comments on this)
368 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
369 TRACE("Target release done\n");
371 This->ddraw->d3ddevice = NULL;
373 /* Now free the structure */
374 HeapFree(GetProcessHeap(), 0, This);
375 wined3d_mutex_unlock();
378 TRACE("Done\n");
379 return ref;
382 static ULONG WINAPI IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
384 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
385 TRACE("iface %p.\n", iface);
387 return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
390 static ULONG WINAPI IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
392 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
393 TRACE("iface %p.\n", iface);
395 return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
398 static ULONG WINAPI IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
400 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
401 TRACE("iface %p.\n", iface);
403 return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
406 /*****************************************************************************
407 * IDirect3DDevice Methods
408 *****************************************************************************/
410 /*****************************************************************************
411 * IDirect3DDevice::Initialize
413 * Initializes a Direct3DDevice. This implementation is a no-op, as all
414 * initialization is done at create time.
416 * Exists in Version 1
418 * Parameters:
419 * No idea what they mean, as the MSDN page is gone
421 * Returns: DD_OK
423 *****************************************************************************/
424 static HRESULT WINAPI
425 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
426 IDirect3D *Direct3D, GUID *guid,
427 D3DDEVICEDESC *Desc)
429 /* It shouldn't be crucial, but print a FIXME, I'm interested if
430 * any game calls it and when. */
431 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
432 iface, Direct3D, debugstr_guid(guid), Desc);
434 return D3D_OK;
437 /*****************************************************************************
438 * IDirect3DDevice7::GetCaps
440 * Retrieves the device's capabilities
442 * This implementation is used for Version 7 only, the older versions have
443 * their own implementation.
445 * Parameters:
446 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
448 * Returns:
449 * D3D_OK on success
450 * D3DERR_* if a problem occurs. See WineD3D
452 *****************************************************************************/
453 static HRESULT
454 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
455 D3DDEVICEDESC7 *Desc)
457 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
458 D3DDEVICEDESC OldDesc;
460 TRACE("iface %p, device_desc %p.\n", iface, Desc);
462 if (!Desc)
464 WARN("Desc is NULL, returning DDERR_INVALIDPARAMS.\n");
465 return DDERR_INVALIDPARAMS;
468 /* Call the same function used by IDirect3D, this saves code */
469 return IDirect3DImpl_GetCaps(This->ddraw->wined3d, &OldDesc, Desc);
472 static HRESULT WINAPI
473 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
474 D3DDEVICEDESC7 *Desc)
476 return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
479 static HRESULT WINAPI
480 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
481 D3DDEVICEDESC7 *Desc)
483 HRESULT hr;
484 WORD old_fpucw;
486 old_fpucw = d3d_fpu_setup();
487 hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
488 set_fpu_control_word(old_fpucw);
490 return hr;
492 /*****************************************************************************
493 * IDirect3DDevice3::GetCaps
495 * Retrieves the capabilities of the hardware device and the emulation
496 * device. For Wine, hardware and emulation are the same (it's all HW).
498 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
500 * Parameters:
501 * HWDesc: Structure to fill with the HW caps
502 * HelDesc: Structure to fill with the hardware emulation caps
504 * Returns:
505 * D3D_OK on success
506 * D3DERR_* if a problem occurs. See WineD3D
508 *****************************************************************************/
510 /* There are 3 versions of D3DDEVICEDESC. All 3 share the same name because
511 * Microsoft just expanded the existing structure without naming them
512 * D3DDEVICEDESC2 and D3DDEVICEDESC3. Which version is used have depends
513 * on the version of the DirectX SDK. DirectX 6+ and Wine use the latest
514 * one with 252 bytes.
516 * All 3 versions are allowed as parameters and only the specified amount of
517 * bytes is written.
519 * Note that Direct3D7 and earlier are not available in native Win64
520 * ddraw.dll builds, so possible size differences between 32 bit and
521 * 64 bit are a non-issue.
523 static inline BOOL check_d3ddevicedesc_size(DWORD size)
525 if (size == FIELD_OFFSET(D3DDEVICEDESC, dwMinTextureWidth) /* 172 */
526 || size == FIELD_OFFSET(D3DDEVICEDESC, dwMaxTextureRepeat) /* 204 */
527 || size == sizeof(D3DDEVICEDESC) /* 252 */) return TRUE;
528 return FALSE;
531 static HRESULT WINAPI
532 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
533 D3DDEVICEDESC *HWDesc,
534 D3DDEVICEDESC *HelDesc)
536 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
537 D3DDEVICEDESC oldDesc;
538 D3DDEVICEDESC7 newDesc;
539 HRESULT hr;
541 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
543 if (!HWDesc)
545 WARN("HWDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
546 return DDERR_INVALIDPARAMS;
548 if (!check_d3ddevicedesc_size(HWDesc->dwSize))
550 WARN("HWDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HWDesc->dwSize);
551 return DDERR_INVALIDPARAMS;
553 if (!HelDesc)
555 WARN("HelDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
556 return DDERR_INVALIDPARAMS;
558 if (!check_d3ddevicedesc_size(HelDesc->dwSize))
560 WARN("HelDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HelDesc->dwSize);
561 return DDERR_INVALIDPARAMS;
564 hr = IDirect3DImpl_GetCaps(This->ddraw->wined3d, &oldDesc, &newDesc);
565 if(hr != D3D_OK) return hr;
567 DD_STRUCT_COPY_BYSIZE(HWDesc, &oldDesc);
568 DD_STRUCT_COPY_BYSIZE(HelDesc, &oldDesc);
569 return D3D_OK;
572 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
573 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
575 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
576 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
577 return IDirect3DDevice3_GetCaps(&This->IDirect3DDevice3_iface, D3DHWDevDesc, D3DHELDevDesc);
580 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
581 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
583 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(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 /*****************************************************************************
589 * IDirect3DDevice2::SwapTextureHandles
591 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
593 * Parameters:
594 * Tex1, Tex2: The 2 Textures to swap
596 * Returns:
597 * D3D_OK
599 *****************************************************************************/
600 static HRESULT WINAPI
601 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
602 IDirect3DTexture2 *Tex1,
603 IDirect3DTexture2 *Tex2)
605 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
606 IDirectDrawSurfaceImpl *surf1 = unsafe_impl_from_IDirect3DTexture2(Tex1);
607 IDirectDrawSurfaceImpl *surf2 = unsafe_impl_from_IDirect3DTexture2(Tex2);
608 DWORD h1, h2;
610 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, Tex1, Tex2);
612 wined3d_mutex_lock();
614 h1 = surf1->Handle - 1;
615 h2 = surf2->Handle - 1;
616 This->handle_table.entries[h1].object = surf2;
617 This->handle_table.entries[h2].object = surf1;
618 surf2->Handle = h1 + 1;
619 surf1->Handle = h2 + 1;
621 wined3d_mutex_unlock();
623 return D3D_OK;
626 static HRESULT WINAPI IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
627 IDirect3DTexture *D3DTex1, IDirect3DTexture *D3DTex2)
629 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
630 IDirectDrawSurfaceImpl *surf1 = unsafe_impl_from_IDirect3DTexture(D3DTex1);
631 IDirectDrawSurfaceImpl *surf2 = unsafe_impl_from_IDirect3DTexture(D3DTex2);
632 IDirect3DTexture2 *t1 = surf1 ? &surf1->IDirect3DTexture2_iface : NULL;
633 IDirect3DTexture2 *t2 = surf2 ? &surf2->IDirect3DTexture2_iface : NULL;
635 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, D3DTex1, D3DTex2);
637 return IDirect3DDevice2_SwapTextureHandles(&This->IDirect3DDevice2_iface, t1, t2);
640 /*****************************************************************************
641 * IDirect3DDevice3::GetStats
643 * This method seems to retrieve some stats from the device.
644 * The MSDN documentation doesn't exist any more, but the D3DSTATS
645 * structure suggests that the amount of drawn primitives and processed
646 * vertices is returned.
648 * Exists in Version 1, 2 and 3
650 * Parameters:
651 * Stats: Pointer to a D3DSTATS structure to be filled
653 * Returns:
654 * D3D_OK on success
655 * DDERR_INVALIDPARAMS if Stats == NULL
657 *****************************************************************************/
658 static HRESULT WINAPI
659 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
660 D3DSTATS *Stats)
662 FIXME("iface %p, stats %p stub!\n", iface, Stats);
664 if(!Stats)
665 return DDERR_INVALIDPARAMS;
667 /* Fill the Stats with 0 */
668 Stats->dwTrianglesDrawn = 0;
669 Stats->dwLinesDrawn = 0;
670 Stats->dwPointsDrawn = 0;
671 Stats->dwSpansDrawn = 0;
672 Stats->dwVerticesProcessed = 0;
674 return D3D_OK;
677 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *Stats)
679 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
681 TRACE("iface %p, stats %p.\n", iface, Stats);
683 return IDirect3DDevice3_GetStats(&This->IDirect3DDevice3_iface, Stats);
686 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface, D3DSTATS *Stats)
688 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
690 TRACE("iface %p, stats %p.\n", iface, Stats);
692 return IDirect3DDevice3_GetStats(&This->IDirect3DDevice3_iface, Stats);
695 /*****************************************************************************
696 * IDirect3DDevice::CreateExecuteBuffer
698 * Creates an IDirect3DExecuteBuffer, used for rendering with a
699 * Direct3DDevice.
701 * Version 1 only.
703 * Params:
704 * Desc: Buffer description
705 * ExecuteBuffer: Address to return the Interface pointer at
706 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
707 * support
709 * Returns:
710 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
711 * DDERR_OUTOFMEMORY if we ran out of memory
712 * D3D_OK on success
714 *****************************************************************************/
715 static HRESULT WINAPI
716 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
717 D3DEXECUTEBUFFERDESC *Desc,
718 IDirect3DExecuteBuffer **ExecuteBuffer,
719 IUnknown *UnkOuter)
721 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
722 IDirect3DExecuteBufferImpl* object;
723 HRESULT hr;
725 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
726 iface, Desc, ExecuteBuffer, UnkOuter);
728 if(UnkOuter)
729 return CLASS_E_NOAGGREGATION;
731 /* Allocate the new Execute Buffer */
732 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
733 if(!object)
735 ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
736 return DDERR_OUTOFMEMORY;
739 hr = d3d_execute_buffer_init(object, This, Desc);
740 if (FAILED(hr))
742 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
743 HeapFree(GetProcessHeap(), 0, object);
744 return hr;
747 *ExecuteBuffer = &object->IDirect3DExecuteBuffer_iface;
749 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
751 return D3D_OK;
754 /*****************************************************************************
755 * IDirect3DDevice::Execute
757 * Executes all the stuff in an execute buffer.
759 * Params:
760 * ExecuteBuffer: The buffer to execute
761 * Viewport: The viewport used for rendering
762 * Flags: Some flags
764 * Returns:
765 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
766 * D3D_OK on success
768 *****************************************************************************/
769 static HRESULT WINAPI IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
770 IDirect3DExecuteBuffer *ExecuteBuffer, IDirect3DViewport *Viewport, DWORD Flags)
772 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
773 IDirect3DExecuteBufferImpl *buffer = unsafe_impl_from_IDirect3DExecuteBuffer(ExecuteBuffer);
774 IDirect3DViewportImpl *Direct3DViewportImpl = unsafe_impl_from_IDirect3DViewport(Viewport);
775 HRESULT hr;
777 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, Viewport, Flags);
779 if(!buffer)
780 return DDERR_INVALIDPARAMS;
782 /* Execute... */
783 wined3d_mutex_lock();
784 hr = d3d_execute_buffer_execute(buffer, This, Direct3DViewportImpl);
785 wined3d_mutex_unlock();
787 return hr;
790 /*****************************************************************************
791 * IDirect3DDevice3::AddViewport
793 * Add a Direct3DViewport to the device's viewport list. These viewports
794 * are wrapped to IDirect3DDevice7 viewports in viewport.c
796 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
797 * are the same interfaces.
799 * Params:
800 * Viewport: The viewport to add
802 * Returns:
803 * DDERR_INVALIDPARAMS if Viewport == NULL
804 * D3D_OK on success
806 *****************************************************************************/
807 static HRESULT WINAPI
808 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
809 IDirect3DViewport3 *Viewport)
811 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
812 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(Viewport);
814 TRACE("iface %p, viewport %p.\n", iface, Viewport);
816 /* Sanity check */
817 if(!vp)
818 return DDERR_INVALIDPARAMS;
820 wined3d_mutex_lock();
821 list_add_head(&This->viewport_list, &vp->entry);
822 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
823 so set active_device here. */
824 wined3d_mutex_unlock();
826 return D3D_OK;
829 static HRESULT WINAPI IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
830 IDirect3DViewport2 *Direct3DViewport2)
832 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
833 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
835 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
837 return IDirect3DDevice3_AddViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
840 static HRESULT WINAPI IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
841 IDirect3DViewport *Direct3DViewport)
843 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
844 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport(Direct3DViewport);
846 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
848 return IDirect3DDevice3_AddViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
851 /*****************************************************************************
852 * IDirect3DDevice3::DeleteViewport
854 * Deletes a Direct3DViewport from the device's viewport list.
856 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
857 * are equal.
859 * Params:
860 * Viewport: The viewport to delete
862 * Returns:
863 * D3D_OK on success
864 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
866 *****************************************************************************/
867 static HRESULT WINAPI IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
869 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
870 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
872 TRACE("iface %p, viewport %p.\n", iface, viewport);
874 wined3d_mutex_lock();
876 if (vp->active_device != This)
878 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
879 wined3d_mutex_unlock();
880 return DDERR_INVALIDPARAMS;
883 vp->active_device = NULL;
884 list_remove(&vp->entry);
886 wined3d_mutex_unlock();
888 return D3D_OK;
891 static HRESULT WINAPI IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
892 IDirect3DViewport2 *Direct3DViewport2)
894 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
895 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
897 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
899 return IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
902 static HRESULT WINAPI IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
903 IDirect3DViewport *Direct3DViewport)
905 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
906 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport(Direct3DViewport);
908 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
910 return IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
913 /*****************************************************************************
914 * IDirect3DDevice3::NextViewport
916 * Returns a viewport from the viewport list, depending on the
917 * passed viewport and the flags.
919 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
920 * are equal.
922 * Params:
923 * Viewport: Viewport to use for beginning the search
924 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
926 * Returns:
927 * D3D_OK on success
928 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
930 *****************************************************************************/
931 static HRESULT WINAPI
932 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
933 IDirect3DViewport3 *Viewport3,
934 IDirect3DViewport3 **lplpDirect3DViewport3,
935 DWORD Flags)
937 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
938 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(Viewport3);
939 IDirect3DViewportImpl *next;
940 struct list *entry;
942 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
943 iface, Viewport3, lplpDirect3DViewport3, Flags);
945 if(!vp)
947 *lplpDirect3DViewport3 = NULL;
948 return DDERR_INVALIDPARAMS;
952 wined3d_mutex_lock();
953 switch (Flags)
955 case D3DNEXT_NEXT:
956 entry = list_next(&This->viewport_list, &vp->entry);
957 break;
959 case D3DNEXT_HEAD:
960 entry = list_head(&This->viewport_list);
961 break;
963 case D3DNEXT_TAIL:
964 entry = list_tail(&This->viewport_list);
965 break;
967 default:
968 WARN("Invalid flags %#x.\n", Flags);
969 *lplpDirect3DViewport3 = NULL;
970 wined3d_mutex_unlock();
971 return DDERR_INVALIDPARAMS;
974 if (entry)
976 next = LIST_ENTRY(entry, IDirect3DViewportImpl, entry);
977 *lplpDirect3DViewport3 = &next->IDirect3DViewport3_iface;
979 else
980 *lplpDirect3DViewport3 = NULL;
982 wined3d_mutex_unlock();
984 return D3D_OK;
987 static HRESULT WINAPI IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
988 IDirect3DViewport2 *Viewport2, IDirect3DViewport2 **lplpDirect3DViewport2, DWORD Flags)
990 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
991 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Viewport2);
992 IDirect3DViewport3 *res;
993 HRESULT hr;
995 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
996 iface, Viewport2, lplpDirect3DViewport2, Flags);
998 hr = IDirect3DDevice3_NextViewport(&This->IDirect3DDevice3_iface,
999 &vp->IDirect3DViewport3_iface, &res, Flags);
1000 *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
1001 return hr;
1004 static HRESULT WINAPI IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
1005 IDirect3DViewport *Viewport, IDirect3DViewport **lplpDirect3DViewport, DWORD Flags)
1007 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1008 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport(Viewport);
1009 IDirect3DViewport3 *res;
1010 HRESULT hr;
1012 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
1013 iface, Viewport, lplpDirect3DViewport, Flags);
1015 hr = IDirect3DDevice3_NextViewport(&This->IDirect3DDevice3_iface,
1016 &vp->IDirect3DViewport3_iface, &res, Flags);
1017 *lplpDirect3DViewport = (IDirect3DViewport *)res;
1018 return hr;
1021 /*****************************************************************************
1022 * IDirect3DDevice::Pick
1024 * Executes an execute buffer without performing rendering. Instead, a
1025 * list of primitives that intersect with (x1,y1) of the passed rectangle
1026 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
1027 * this list.
1029 * Version 1 only
1031 * Params:
1032 * ExecuteBuffer: Buffer to execute
1033 * Viewport: Viewport to use for execution
1034 * Flags: None are defined, according to the SDK
1035 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
1036 * x2 and y2 are ignored.
1038 * Returns:
1039 * D3D_OK because it's a stub
1041 *****************************************************************************/
1042 static HRESULT WINAPI
1043 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
1044 IDirect3DExecuteBuffer *ExecuteBuffer,
1045 IDirect3DViewport *Viewport,
1046 DWORD Flags,
1047 D3DRECT *Rect)
1049 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
1050 iface, ExecuteBuffer, Viewport, Flags, wine_dbgstr_rect((RECT *)Rect));
1052 return D3D_OK;
1055 /*****************************************************************************
1056 * IDirect3DDevice::GetPickRecords
1058 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1060 * Version 1 only
1062 * Params:
1063 * Count: Pointer to a DWORD containing the numbers of pick records to
1064 * retrieve
1065 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1067 * Returns:
1068 * D3D_OK, because it's a stub
1070 *****************************************************************************/
1071 static HRESULT WINAPI
1072 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1073 DWORD *Count,
1074 D3DPICKRECORD *D3DPickRec)
1076 FIXME("iface %p, count %p, records %p stub!\n", iface, Count, D3DPickRec);
1078 return D3D_OK;
1081 /*****************************************************************************
1082 * IDirect3DDevice7::EnumTextureformats
1084 * Enumerates the supported texture formats. It has a list of all possible
1085 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1086 * WineD3D supports it. If so, then it is passed to the app.
1088 * This is for Version 7 and 3, older versions have a different
1089 * callback function and their own implementation
1091 * Params:
1092 * Callback: Callback to call for each enumerated format
1093 * Arg: Argument to pass to the callback
1095 * Returns:
1096 * D3D_OK on success
1097 * DDERR_INVALIDPARAMS if Callback == NULL
1099 *****************************************************************************/
1100 static HRESULT
1101 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1102 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1103 void *Arg)
1105 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1106 struct wined3d_display_mode mode;
1107 HRESULT hr;
1108 unsigned int i;
1110 static const enum wined3d_format_id FormatList[] =
1112 /* 16 bit */
1113 WINED3DFMT_B5G5R5X1_UNORM,
1114 WINED3DFMT_B5G5R5A1_UNORM,
1115 WINED3DFMT_B4G4R4A4_UNORM,
1116 WINED3DFMT_B5G6R5_UNORM,
1117 /* 32 bit */
1118 WINED3DFMT_B8G8R8X8_UNORM,
1119 WINED3DFMT_B8G8R8A8_UNORM,
1120 /* 8 bit */
1121 WINED3DFMT_B2G3R3_UNORM,
1122 WINED3DFMT_P8_UINT,
1123 /* FOURCC codes */
1124 WINED3DFMT_DXT1,
1125 WINED3DFMT_DXT3,
1126 WINED3DFMT_DXT5,
1129 static const enum wined3d_format_id BumpFormatList[] =
1131 WINED3DFMT_R8G8_SNORM,
1132 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1133 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1134 WINED3DFMT_R16G16_SNORM,
1135 WINED3DFMT_R10G11B11_SNORM,
1136 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1139 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1141 if(!Callback)
1142 return DDERR_INVALIDPARAMS;
1144 wined3d_mutex_lock();
1146 memset(&mode, 0, sizeof(mode));
1147 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1148 if (FAILED(hr))
1150 wined3d_mutex_unlock();
1151 WARN("Cannot get the current adapter format\n");
1152 return hr;
1155 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1157 hr = wined3d_check_device_format(This->ddraw->wined3d, WINED3DADAPTER_DEFAULT, WINED3DDEVTYPE_HAL,
1158 mode.format_id, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1159 if (hr == D3D_OK)
1161 DDPIXELFORMAT pformat;
1163 memset(&pformat, 0, sizeof(pformat));
1164 pformat.dwSize = sizeof(pformat);
1165 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1167 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1168 hr = Callback(&pformat, Arg);
1169 if(hr != DDENUMRET_OK)
1171 TRACE("Format enumeration cancelled by application\n");
1172 wined3d_mutex_unlock();
1173 return D3D_OK;
1178 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1180 hr = wined3d_check_device_format(This->ddraw->wined3d, WINED3DADAPTER_DEFAULT,
1181 WINED3DDEVTYPE_HAL, mode.format_id, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1182 WINED3DRTYPE_TEXTURE, BumpFormatList[i], SURFACE_OPENGL);
1183 if (hr == D3D_OK)
1185 DDPIXELFORMAT pformat;
1187 memset(&pformat, 0, sizeof(pformat));
1188 pformat.dwSize = sizeof(pformat);
1189 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1191 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1192 hr = Callback(&pformat, Arg);
1193 if(hr != DDENUMRET_OK)
1195 TRACE("Format enumeration cancelled by application\n");
1196 wined3d_mutex_unlock();
1197 return D3D_OK;
1201 TRACE("End of enumeration\n");
1202 wined3d_mutex_unlock();
1204 return D3D_OK;
1207 static HRESULT WINAPI
1208 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1209 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1210 void *Arg)
1212 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1215 static HRESULT WINAPI
1216 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1217 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1218 void *Arg)
1220 HRESULT hr;
1221 WORD old_fpucw;
1223 old_fpucw = d3d_fpu_setup();
1224 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1225 set_fpu_control_word(old_fpucw);
1227 return hr;
1230 static HRESULT WINAPI IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1231 LPD3DENUMPIXELFORMATSCALLBACK Callback, void *Arg)
1233 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1235 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1237 return IDirect3DDevice7_EnumTextureFormats(&This->IDirect3DDevice7_iface, Callback, Arg);
1240 /*****************************************************************************
1241 * IDirect3DDevice2::EnumTextureformats
1243 * EnumTextureFormats for Version 1 and 2, see
1244 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1246 * This version has a different callback and does not enumerate FourCC
1247 * formats
1249 *****************************************************************************/
1250 static HRESULT WINAPI
1251 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1252 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1253 void *Arg)
1255 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1256 struct wined3d_display_mode mode;
1257 HRESULT hr;
1258 unsigned int i;
1260 static const enum wined3d_format_id FormatList[] =
1262 /* 16 bit */
1263 WINED3DFMT_B5G5R5X1_UNORM,
1264 WINED3DFMT_B5G5R5A1_UNORM,
1265 WINED3DFMT_B4G4R4A4_UNORM,
1266 WINED3DFMT_B5G6R5_UNORM,
1267 /* 32 bit */
1268 WINED3DFMT_B8G8R8X8_UNORM,
1269 WINED3DFMT_B8G8R8A8_UNORM,
1270 /* 8 bit */
1271 WINED3DFMT_B2G3R3_UNORM,
1272 WINED3DFMT_P8_UINT,
1273 /* FOURCC codes - Not in this version*/
1276 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1278 if(!Callback)
1279 return DDERR_INVALIDPARAMS;
1281 wined3d_mutex_lock();
1283 memset(&mode, 0, sizeof(mode));
1284 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1285 if (FAILED(hr))
1287 wined3d_mutex_unlock();
1288 WARN("Cannot get the current adapter format\n");
1289 return hr;
1292 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1294 hr = wined3d_check_device_format(This->ddraw->wined3d, 0, WINED3DDEVTYPE_HAL,
1295 mode.format_id, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1296 if (hr == D3D_OK)
1298 DDSURFACEDESC sdesc;
1300 memset(&sdesc, 0, sizeof(sdesc));
1301 sdesc.dwSize = sizeof(sdesc);
1302 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1303 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1304 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1305 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1307 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1308 hr = Callback(&sdesc, Arg);
1309 if(hr != DDENUMRET_OK)
1311 TRACE("Format enumeration cancelled by application\n");
1312 wined3d_mutex_unlock();
1313 return D3D_OK;
1317 TRACE("End of enumeration\n");
1318 wined3d_mutex_unlock();
1320 return D3D_OK;
1323 static HRESULT WINAPI IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1324 LPD3DENUMTEXTUREFORMATSCALLBACK Callback, void *Arg)
1326 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1328 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1330 return IDirect3DDevice2_EnumTextureFormats(&This->IDirect3DDevice2_iface, Callback, Arg);
1333 /*****************************************************************************
1334 * IDirect3DDevice::CreateMatrix
1336 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1337 * allocated for the handle.
1339 * Version 1 only
1341 * Params
1342 * D3DMatHandle: Address to return the handle at
1344 * Returns:
1345 * D3D_OK on success
1346 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1348 *****************************************************************************/
1349 static HRESULT WINAPI
1350 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1352 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1353 D3DMATRIX *Matrix;
1354 DWORD h;
1356 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1358 if(!D3DMatHandle)
1359 return DDERR_INVALIDPARAMS;
1361 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1362 if(!Matrix)
1364 ERR("Out of memory when allocating a D3DMATRIX\n");
1365 return DDERR_OUTOFMEMORY;
1368 wined3d_mutex_lock();
1370 h = ddraw_allocate_handle(&This->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1371 if (h == DDRAW_INVALID_HANDLE)
1373 ERR("Failed to allocate a matrix handle.\n");
1374 HeapFree(GetProcessHeap(), 0, Matrix);
1375 wined3d_mutex_unlock();
1376 return DDERR_OUTOFMEMORY;
1379 *D3DMatHandle = h + 1;
1381 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1383 wined3d_mutex_unlock();
1385 return D3D_OK;
1388 /*****************************************************************************
1389 * IDirect3DDevice::SetMatrix
1391 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1392 * allocated for the handle
1394 * Version 1 only
1396 * Params:
1397 * D3DMatHandle: Handle to set the matrix to
1398 * D3DMatrix: Matrix to set
1400 * Returns:
1401 * D3D_OK on success
1402 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1403 * to set is NULL
1405 *****************************************************************************/
1406 static HRESULT WINAPI
1407 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1408 D3DMATRIXHANDLE D3DMatHandle,
1409 D3DMATRIX *D3DMatrix)
1411 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1412 D3DMATRIX *m;
1414 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1416 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1418 wined3d_mutex_lock();
1420 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1421 if (!m)
1423 WARN("Invalid matrix handle.\n");
1424 wined3d_mutex_unlock();
1425 return DDERR_INVALIDPARAMS;
1428 if (TRACE_ON(ddraw))
1429 dump_D3DMATRIX(D3DMatrix);
1431 *m = *D3DMatrix;
1433 if (D3DMatHandle == This->world)
1434 wined3d_device_set_transform(This->wined3d_device,
1435 WINED3DTS_WORLDMATRIX(0), (struct wined3d_matrix *)D3DMatrix);
1437 if (D3DMatHandle == This->view)
1438 wined3d_device_set_transform(This->wined3d_device,
1439 WINED3DTS_VIEW, (struct wined3d_matrix *)D3DMatrix);
1441 if (D3DMatHandle == This->proj)
1442 wined3d_device_set_transform(This->wined3d_device,
1443 WINED3DTS_PROJECTION, (struct wined3d_matrix *)D3DMatrix);
1445 wined3d_mutex_unlock();
1447 return D3D_OK;
1450 /*****************************************************************************
1451 * IDirect3DDevice::GetMatrix
1453 * Returns the content of a D3DMATRIX handle
1455 * Version 1 only
1457 * Params:
1458 * D3DMatHandle: Matrix handle to read the content from
1459 * D3DMatrix: Address to store the content at
1461 * Returns:
1462 * D3D_OK on success
1463 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1465 *****************************************************************************/
1466 static HRESULT WINAPI
1467 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1468 D3DMATRIXHANDLE D3DMatHandle,
1469 D3DMATRIX *D3DMatrix)
1471 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1472 D3DMATRIX *m;
1474 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1476 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1478 wined3d_mutex_lock();
1480 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1481 if (!m)
1483 WARN("Invalid matrix handle.\n");
1484 wined3d_mutex_unlock();
1485 return DDERR_INVALIDPARAMS;
1488 *D3DMatrix = *m;
1490 wined3d_mutex_unlock();
1492 return D3D_OK;
1495 /*****************************************************************************
1496 * IDirect3DDevice::DeleteMatrix
1498 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1500 * Version 1 only
1502 * Params:
1503 * D3DMatHandle: Handle to destroy
1505 * Returns:
1506 * D3D_OK on success
1507 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1509 *****************************************************************************/
1510 static HRESULT WINAPI
1511 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1512 D3DMATRIXHANDLE D3DMatHandle)
1514 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1515 D3DMATRIX *m;
1517 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1519 wined3d_mutex_lock();
1521 m = ddraw_free_handle(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1522 if (!m)
1524 WARN("Invalid matrix handle.\n");
1525 wined3d_mutex_unlock();
1526 return DDERR_INVALIDPARAMS;
1529 wined3d_mutex_unlock();
1531 HeapFree(GetProcessHeap(), 0, m);
1533 return D3D_OK;
1536 /*****************************************************************************
1537 * IDirect3DDevice7::BeginScene
1539 * This method must be called before any rendering is performed.
1540 * IDirect3DDevice::EndScene has to be called after the scene is complete
1542 * Version 1, 2, 3 and 7
1544 * Returns:
1545 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1546 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1547 * started scene).
1549 *****************************************************************************/
1550 static HRESULT
1551 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1553 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1554 HRESULT hr;
1556 TRACE("iface %p.\n", iface);
1558 wined3d_mutex_lock();
1559 hr = wined3d_device_begin_scene(This->wined3d_device);
1560 wined3d_mutex_unlock();
1562 if(hr == WINED3D_OK) return D3D_OK;
1563 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1566 static HRESULT WINAPI
1567 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1569 return IDirect3DDeviceImpl_7_BeginScene(iface);
1572 static HRESULT WINAPI
1573 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1575 HRESULT hr;
1576 WORD old_fpucw;
1578 old_fpucw = d3d_fpu_setup();
1579 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1580 set_fpu_control_word(old_fpucw);
1582 return hr;
1585 static HRESULT WINAPI IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1587 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1588 TRACE("iface %p.\n", iface);
1590 return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
1593 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1595 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1596 TRACE("iface %p.\n", iface);
1598 return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
1601 static HRESULT WINAPI IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1603 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1604 TRACE("iface %p.\n", iface);
1606 return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
1609 /*****************************************************************************
1610 * IDirect3DDevice7::EndScene
1612 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1613 * This method must be called after rendering is finished.
1615 * Version 1, 2, 3 and 7
1617 * Returns:
1618 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1619 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1620 * that only if the scene was already ended.
1622 *****************************************************************************/
1623 static HRESULT
1624 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1626 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1627 HRESULT hr;
1629 TRACE("iface %p.\n", iface);
1631 wined3d_mutex_lock();
1632 hr = wined3d_device_end_scene(This->wined3d_device);
1633 wined3d_mutex_unlock();
1635 if(hr == WINED3D_OK) return D3D_OK;
1636 else return D3DERR_SCENE_NOT_IN_SCENE;
1639 static HRESULT WINAPI DECLSPEC_HOTPATCH
1640 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1642 return IDirect3DDeviceImpl_7_EndScene(iface);
1645 static HRESULT WINAPI DECLSPEC_HOTPATCH
1646 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1648 HRESULT hr;
1649 WORD old_fpucw;
1651 old_fpucw = d3d_fpu_setup();
1652 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1653 set_fpu_control_word(old_fpucw);
1655 return hr;
1658 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1660 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1661 TRACE("iface %p.\n", iface);
1663 return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
1666 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1668 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1669 TRACE("iface %p.\n", iface);
1671 return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
1674 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1676 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1677 TRACE("iface %p.\n", iface);
1679 return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
1682 /*****************************************************************************
1683 * IDirect3DDevice7::GetDirect3D
1685 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1686 * this device.
1688 * Params:
1689 * Direct3D7: Address to store the interface pointer at
1691 * Returns:
1692 * D3D_OK on success
1693 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1695 *****************************************************************************/
1696 static HRESULT WINAPI
1697 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1698 IDirect3D7 **Direct3D7)
1700 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1702 TRACE("iface %p, d3d %p.\n", iface, Direct3D7);
1704 if(!Direct3D7)
1705 return DDERR_INVALIDPARAMS;
1707 *Direct3D7 = &This->ddraw->IDirect3D7_iface;
1708 IDirect3D7_AddRef(*Direct3D7);
1710 TRACE(" returning interface %p\n", *Direct3D7);
1711 return D3D_OK;
1714 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1715 IDirect3D3 **Direct3D3)
1717 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1719 TRACE("iface %p, d3d %p.\n", iface, Direct3D3);
1721 if(!Direct3D3)
1722 return DDERR_INVALIDPARAMS;
1724 IDirect3D3_AddRef(&This->ddraw->IDirect3D3_iface);
1725 *Direct3D3 = &This->ddraw->IDirect3D3_iface;
1726 TRACE(" returning interface %p\n", *Direct3D3);
1727 return D3D_OK;
1730 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1731 IDirect3D2 **Direct3D2)
1733 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1735 TRACE("iface %p, d3d %p.\n", iface, Direct3D2);
1737 if(!Direct3D2)
1738 return DDERR_INVALIDPARAMS;
1740 IDirect3D2_AddRef(&This->ddraw->IDirect3D2_iface);
1741 *Direct3D2 = &This->ddraw->IDirect3D2_iface;
1742 TRACE(" returning interface %p\n", *Direct3D2);
1743 return D3D_OK;
1746 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1747 IDirect3D **Direct3D)
1749 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1751 TRACE("iface %p, d3d %p.\n", iface, Direct3D);
1753 if(!Direct3D)
1754 return DDERR_INVALIDPARAMS;
1756 IDirect3D_AddRef(&This->ddraw->IDirect3D_iface);
1757 *Direct3D = &This->ddraw->IDirect3D_iface;
1758 TRACE(" returning interface %p\n", *Direct3D);
1759 return D3D_OK;
1762 /*****************************************************************************
1763 * IDirect3DDevice3::SetCurrentViewport
1765 * Sets a Direct3DViewport as the current viewport.
1766 * For the thunks note that all viewport interface versions are equal
1768 * Params:
1769 * Direct3DViewport3: The viewport to set
1771 * Version 2 and 3
1773 * Returns:
1774 * D3D_OK on success
1775 * (Is a NULL viewport valid?)
1777 *****************************************************************************/
1778 static HRESULT WINAPI
1779 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1780 IDirect3DViewport3 *Direct3DViewport3)
1782 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1783 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(Direct3DViewport3);
1785 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1787 wined3d_mutex_lock();
1788 /* Do nothing if the specified viewport is the same as the current one */
1789 if (This->current_viewport == vp )
1791 wined3d_mutex_unlock();
1792 return D3D_OK;
1795 if (vp->active_device != This)
1797 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1798 wined3d_mutex_unlock();
1799 return DDERR_INVALIDPARAMS;
1802 /* Release previous viewport and AddRef the new one */
1803 if (This->current_viewport)
1805 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1806 &This->current_viewport->IDirect3DViewport3_iface);
1807 IDirect3DViewport3_Release(&This->current_viewport->IDirect3DViewport3_iface);
1809 IDirect3DViewport3_AddRef(Direct3DViewport3);
1811 /* Set this viewport as the current viewport */
1812 This->current_viewport = vp;
1814 /* Activate this viewport */
1815 viewport_activate(This->current_viewport, FALSE);
1817 wined3d_mutex_unlock();
1819 return D3D_OK;
1822 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1823 IDirect3DViewport2 *Direct3DViewport2)
1825 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1826 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
1828 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1830 return IDirect3DDevice3_SetCurrentViewport(&This->IDirect3DDevice3_iface,
1831 &vp->IDirect3DViewport3_iface);
1834 /*****************************************************************************
1835 * IDirect3DDevice3::GetCurrentViewport
1837 * Returns the currently active viewport.
1839 * Version 2 and 3
1841 * Params:
1842 * Direct3DViewport3: Address to return the interface pointer at
1844 * Returns:
1845 * D3D_OK on success
1846 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1848 *****************************************************************************/
1849 static HRESULT WINAPI
1850 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1851 IDirect3DViewport3 **Direct3DViewport3)
1853 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1855 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1857 if(!Direct3DViewport3)
1858 return DDERR_INVALIDPARAMS;
1860 wined3d_mutex_lock();
1861 *Direct3DViewport3 = &This->current_viewport->IDirect3DViewport3_iface;
1863 /* AddRef the returned viewport */
1864 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1866 TRACE(" returning interface %p\n", *Direct3DViewport3);
1868 wined3d_mutex_unlock();
1870 return D3D_OK;
1873 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1874 IDirect3DViewport2 **Direct3DViewport2)
1876 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1877 HRESULT hr;
1879 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1881 hr = IDirect3DDevice3_GetCurrentViewport(&This->IDirect3DDevice3_iface,
1882 (IDirect3DViewport3 **)Direct3DViewport2);
1883 if(hr != D3D_OK) return hr;
1884 return D3D_OK;
1887 /*****************************************************************************
1888 * IDirect3DDevice7::SetRenderTarget
1890 * Sets the render target for the Direct3DDevice.
1891 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1892 * IDirectDrawSurface3 == IDirectDrawSurface
1894 * Version 2, 3 and 7
1896 * Params:
1897 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1898 * render target
1899 * Flags: Some flags
1901 * Returns:
1902 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1904 *****************************************************************************/
1905 static HRESULT d3d_device_set_render_target(IDirect3DDeviceImpl *This, IDirectDrawSurfaceImpl *Target)
1907 HRESULT hr;
1909 wined3d_mutex_lock();
1911 if(This->target == Target)
1913 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1914 wined3d_mutex_unlock();
1915 return D3D_OK;
1917 This->target = Target;
1918 hr = wined3d_device_set_render_target(This->wined3d_device, 0,
1919 Target ? Target->wined3d_surface : NULL, FALSE);
1920 if(hr != D3D_OK)
1922 wined3d_mutex_unlock();
1923 return hr;
1925 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1927 wined3d_mutex_unlock();
1929 return D3D_OK;
1932 static HRESULT
1933 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1934 IDirectDrawSurface7 *NewTarget,
1935 DWORD Flags)
1937 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1938 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface7(NewTarget);
1940 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, Flags);
1941 /* Flags: Not used */
1943 IDirectDrawSurface7_AddRef(NewTarget);
1944 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
1945 return d3d_device_set_render_target(This, Target);
1948 static HRESULT WINAPI
1949 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1950 IDirectDrawSurface7 *NewTarget,
1951 DWORD Flags)
1953 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1956 static HRESULT WINAPI
1957 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1958 IDirectDrawSurface7 *NewTarget,
1959 DWORD Flags)
1961 HRESULT hr;
1962 WORD old_fpucw;
1964 old_fpucw = d3d_fpu_setup();
1965 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1966 set_fpu_control_word(old_fpucw);
1968 return hr;
1971 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
1972 IDirectDrawSurface4 *NewRenderTarget, DWORD Flags)
1974 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1975 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface4(NewRenderTarget);
1977 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1979 IDirectDrawSurface4_AddRef(NewRenderTarget);
1980 IDirectDrawSurface4_Release(&This->target->IDirectDrawSurface4_iface);
1981 return d3d_device_set_render_target(This, Target);
1984 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
1985 IDirectDrawSurface *NewRenderTarget, DWORD Flags)
1987 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1988 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface(NewRenderTarget);
1990 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1992 IDirectDrawSurface_AddRef(NewRenderTarget);
1993 IDirectDrawSurface_Release(&This->target->IDirectDrawSurface_iface);
1994 return d3d_device_set_render_target(This, Target);
1997 /*****************************************************************************
1998 * IDirect3DDevice7::GetRenderTarget
2000 * Returns the current render target.
2001 * This is handled locally, because the WineD3D render target's parent
2002 * is an IParent
2004 * Version 2, 3 and 7
2006 * Params:
2007 * RenderTarget: Address to store the surface interface pointer
2009 * Returns:
2010 * D3D_OK on success
2011 * DDERR_INVALIDPARAMS if RenderTarget == NULL
2013 *****************************************************************************/
2014 static HRESULT WINAPI
2015 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
2016 IDirectDrawSurface7 **RenderTarget)
2018 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
2020 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2022 if(!RenderTarget)
2023 return DDERR_INVALIDPARAMS;
2025 wined3d_mutex_lock();
2026 *RenderTarget = &This->target->IDirectDrawSurface7_iface;
2027 IDirectDrawSurface7_AddRef(*RenderTarget);
2028 wined3d_mutex_unlock();
2030 return D3D_OK;
2033 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
2034 IDirectDrawSurface4 **RenderTarget)
2036 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2037 IDirectDrawSurface7 *RenderTarget7;
2038 IDirectDrawSurfaceImpl *RenderTargetImpl;
2039 HRESULT hr;
2041 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2043 if(!RenderTarget)
2044 return DDERR_INVALIDPARAMS;
2046 hr = IDirect3DDevice7_GetRenderTarget(&This->IDirect3DDevice7_iface, &RenderTarget7);
2047 if(hr != D3D_OK) return hr;
2048 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2049 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface;
2050 IDirectDrawSurface4_AddRef(*RenderTarget);
2051 IDirectDrawSurface7_Release(RenderTarget7);
2052 return D3D_OK;
2055 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
2056 IDirectDrawSurface **RenderTarget)
2058 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2059 IDirectDrawSurface7 *RenderTarget7;
2060 IDirectDrawSurfaceImpl *RenderTargetImpl;
2061 HRESULT hr;
2063 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2065 if(!RenderTarget)
2066 return DDERR_INVALIDPARAMS;
2068 hr = IDirect3DDevice7_GetRenderTarget(&This->IDirect3DDevice7_iface, &RenderTarget7);
2069 if(hr != D3D_OK) return hr;
2070 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2071 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
2072 IDirectDrawSurface_AddRef(*RenderTarget);
2073 IDirectDrawSurface7_Release(RenderTarget7);
2074 return D3D_OK;
2077 /*****************************************************************************
2078 * IDirect3DDevice3::Begin
2080 * Begins a description block of vertices. This is similar to glBegin()
2081 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2082 * described with IDirect3DDevice::Vertex are drawn.
2084 * Version 2 and 3
2086 * Params:
2087 * PrimitiveType: The type of primitives to draw
2088 * VertexTypeDesc: A flexible vertex format description of the vertices
2089 * Flags: Some flags..
2091 * Returns:
2092 * D3D_OK on success
2094 *****************************************************************************/
2095 static HRESULT WINAPI
2096 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2097 D3DPRIMITIVETYPE PrimitiveType,
2098 DWORD VertexTypeDesc,
2099 DWORD Flags)
2101 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2103 TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
2104 iface, PrimitiveType, VertexTypeDesc, Flags);
2106 wined3d_mutex_lock();
2107 This->primitive_type = PrimitiveType;
2108 This->vertex_type = VertexTypeDesc;
2109 This->render_flags = Flags;
2110 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2111 This->nb_vertices = 0;
2112 wined3d_mutex_unlock();
2114 return D3D_OK;
2117 static HRESULT WINAPI IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface, D3DPRIMITIVETYPE d3dpt,
2118 D3DVERTEXTYPE dwVertexTypeDesc, DWORD dwFlags)
2120 DWORD FVF;
2121 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2123 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2124 iface, d3dpt, dwVertexTypeDesc, dwFlags);
2126 switch(dwVertexTypeDesc)
2128 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2129 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2130 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2131 default:
2132 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2133 return DDERR_INVALIDPARAMS; /* Should never happen */
2136 return IDirect3DDevice3_Begin(&This->IDirect3DDevice3_iface, d3dpt, FVF, dwFlags);
2139 /*****************************************************************************
2140 * IDirect3DDevice3::BeginIndexed
2142 * Draws primitives based on vertices in a vertex array which are specified
2143 * by indices.
2145 * Version 2 and 3
2147 * Params:
2148 * PrimitiveType: Primitive type to draw
2149 * VertexType: A FVF description of the vertex format
2150 * Vertices: pointer to an array containing the vertices
2151 * NumVertices: The number of vertices in the vertex array
2152 * Flags: Some flags ...
2154 * Returns:
2155 * D3D_OK, because it's a stub
2157 *****************************************************************************/
2158 static HRESULT WINAPI
2159 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2160 D3DPRIMITIVETYPE PrimitiveType,
2161 DWORD VertexType,
2162 void *Vertices,
2163 DWORD NumVertices,
2164 DWORD Flags)
2166 FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2167 iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2169 return D3D_OK;
2173 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2174 D3DPRIMITIVETYPE d3dptPrimitiveType, D3DVERTEXTYPE d3dvtVertexType,
2175 void *lpvVertices, DWORD dwNumVertices, DWORD dwFlags)
2177 DWORD FVF;
2178 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2180 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2181 iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2183 switch(d3dvtVertexType)
2185 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2186 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2187 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2188 default:
2189 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2190 return DDERR_INVALIDPARAMS; /* Should never happen */
2193 return IDirect3DDevice3_BeginIndexed(&This->IDirect3DDevice3_iface,
2194 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2197 /*****************************************************************************
2198 * IDirect3DDevice3::Vertex
2200 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2201 * drawn vertices in a vertex buffer. If the buffer is too small, its
2202 * size is increased.
2204 * Version 2 and 3
2206 * Params:
2207 * Vertex: Pointer to the vertex
2209 * Returns:
2210 * D3D_OK, on success
2211 * DDERR_INVALIDPARAMS if Vertex is NULL
2213 *****************************************************************************/
2214 static HRESULT WINAPI
2215 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2216 void *Vertex)
2218 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2220 TRACE("iface %p, vertex %p.\n", iface, Vertex);
2222 if(!Vertex)
2223 return DDERR_INVALIDPARAMS;
2225 wined3d_mutex_lock();
2226 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2228 BYTE *old_buffer;
2229 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2230 old_buffer = This->vertex_buffer;
2231 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2232 if (old_buffer)
2234 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2235 HeapFree(GetProcessHeap(), 0, old_buffer);
2239 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2240 wined3d_mutex_unlock();
2242 return D3D_OK;
2245 static HRESULT WINAPI IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface, void *lpVertexType)
2247 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2249 TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
2251 return IDirect3DDevice3_Vertex(&This->IDirect3DDevice3_iface, lpVertexType);
2254 /*****************************************************************************
2255 * IDirect3DDevice3::Index
2257 * Specifies an index to a vertex to be drawn. The vertex array has to
2258 * be specified with BeginIndexed first.
2260 * Parameters:
2261 * VertexIndex: The index of the vertex to draw
2263 * Returns:
2264 * D3D_OK because it's a stub
2266 *****************************************************************************/
2267 static HRESULT WINAPI
2268 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2269 WORD VertexIndex)
2271 FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
2273 return D3D_OK;
2276 static HRESULT WINAPI IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface, WORD wVertexIndex)
2278 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2280 TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
2282 return IDirect3DDevice3_Index(&This->IDirect3DDevice3_iface, wVertexIndex);
2285 /*****************************************************************************
2286 * IDirect3DDevice3::End
2288 * Ends a draw begun with IDirect3DDevice3::Begin or
2289 * IDirect3DDevice::BeginIndexed. The vertices specified with
2290 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2291 * the IDirect3DDevice7::DrawPrimitive method. So far only
2292 * non-indexed mode is supported
2294 * Version 2 and 3
2296 * Params:
2297 * Flags: Some flags, as usual. Don't know which are defined
2299 * Returns:
2300 * The return value of IDirect3DDevice7::DrawPrimitive
2302 *****************************************************************************/
2303 static HRESULT WINAPI
2304 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2305 DWORD Flags)
2307 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2309 TRACE("iface %p, flags %#x.\n", iface, Flags);
2311 return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface, This->primitive_type,
2312 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2315 static HRESULT WINAPI IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface, DWORD dwFlags)
2317 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2319 TRACE("iface %p, flags %#x.\n", iface, dwFlags);
2321 return IDirect3DDevice3_End(&This->IDirect3DDevice3_iface, dwFlags);
2324 /*****************************************************************************
2325 * IDirect3DDevice7::GetRenderState
2327 * Returns the value of a render state. The possible render states are
2328 * defined in include/d3dtypes.h
2330 * Version 2, 3 and 7
2332 * Params:
2333 * RenderStateType: Render state to return the current setting of
2334 * Value: Address to store the value at
2336 * Returns:
2337 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2338 * DDERR_INVALIDPARAMS if Value == NULL
2340 *****************************************************************************/
2341 static HRESULT IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2342 D3DRENDERSTATETYPE RenderStateType, DWORD *Value)
2344 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
2345 HRESULT hr;
2347 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2349 if(!Value)
2350 return DDERR_INVALIDPARAMS;
2352 wined3d_mutex_lock();
2353 switch(RenderStateType)
2355 case D3DRENDERSTATE_TEXTUREMAG:
2357 WINED3DTEXTUREFILTERTYPE tex_mag;
2359 hr = wined3d_device_get_sampler_state(This->wined3d_device, 0, WINED3DSAMP_MAGFILTER, &tex_mag);
2361 switch (tex_mag)
2363 case WINED3DTEXF_POINT:
2364 *Value = D3DFILTER_NEAREST;
2365 break;
2366 case WINED3DTEXF_LINEAR:
2367 *Value = D3DFILTER_LINEAR;
2368 break;
2369 default:
2370 ERR("Unhandled texture mag %d !\n",tex_mag);
2371 *Value = 0;
2373 break;
2376 case D3DRENDERSTATE_TEXTUREMIN:
2378 WINED3DTEXTUREFILTERTYPE tex_min;
2379 WINED3DTEXTUREFILTERTYPE tex_mip;
2381 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2382 0, WINED3DSAMP_MINFILTER, &tex_min);
2383 if (FAILED(hr))
2385 wined3d_mutex_unlock();
2386 return hr;
2388 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2389 0, WINED3DSAMP_MIPFILTER, &tex_mip);
2391 switch (tex_min)
2393 case WINED3DTEXF_POINT:
2394 switch (tex_mip)
2396 case WINED3DTEXF_NONE:
2397 *Value = D3DFILTER_NEAREST;
2398 break;
2399 case WINED3DTEXF_POINT:
2400 *Value = D3DFILTER_MIPNEAREST;
2401 break;
2402 case WINED3DTEXF_LINEAR:
2403 *Value = D3DFILTER_LINEARMIPNEAREST;
2404 break;
2405 default:
2406 ERR("Unhandled mip filter %#x.\n", tex_mip);
2407 *Value = D3DFILTER_NEAREST;
2408 break;
2410 break;
2411 case WINED3DTEXF_LINEAR:
2412 switch (tex_mip)
2414 case WINED3DTEXF_NONE:
2415 *Value = D3DFILTER_LINEAR;
2416 break;
2417 case WINED3DTEXF_POINT:
2418 *Value = D3DFILTER_MIPLINEAR;
2419 break;
2420 case WINED3DTEXF_LINEAR:
2421 *Value = D3DFILTER_LINEARMIPLINEAR;
2422 break;
2423 default:
2424 ERR("Unhandled mip filter %#x.\n", tex_mip);
2425 *Value = D3DFILTER_LINEAR;
2426 break;
2428 break;
2429 default:
2430 ERR("Unhandled texture min filter %#x.\n",tex_min);
2431 *Value = D3DFILTER_NEAREST;
2432 break;
2434 break;
2437 case D3DRENDERSTATE_TEXTUREADDRESS:
2438 case D3DRENDERSTATE_TEXTUREADDRESSU:
2439 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2440 0, WINED3DSAMP_ADDRESSU, Value);
2441 break;
2442 case D3DRENDERSTATE_TEXTUREADDRESSV:
2443 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2444 0, WINED3DSAMP_ADDRESSV, Value);
2445 break;
2447 case D3DRENDERSTATE_BORDERCOLOR:
2448 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2449 hr = E_NOTIMPL;
2450 break;
2452 case D3DRENDERSTATE_TEXTUREHANDLE:
2453 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2454 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2455 hr = DDERR_INVALIDPARAMS;
2456 break;
2458 case D3DRENDERSTATE_ZBIAS:
2459 hr = wined3d_device_get_render_state(This->wined3d_device, WINED3DRS_DEPTHBIAS, Value);
2460 break;
2462 default:
2463 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2464 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2466 FIXME("Unhandled stipple pattern render state (%#x).\n",
2467 RenderStateType);
2468 hr = E_NOTIMPL;
2469 break;
2471 hr = wined3d_device_get_render_state(This->wined3d_device, RenderStateType, Value);
2473 wined3d_mutex_unlock();
2475 return hr;
2478 static HRESULT WINAPI
2479 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2480 D3DRENDERSTATETYPE RenderStateType,
2481 DWORD *Value)
2483 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2486 static HRESULT WINAPI
2487 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2488 D3DRENDERSTATETYPE RenderStateType,
2489 DWORD *Value)
2491 HRESULT hr;
2492 WORD old_fpucw;
2494 old_fpucw = d3d_fpu_setup();
2495 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2496 set_fpu_control_word(old_fpucw);
2498 return hr;
2501 static HRESULT WINAPI
2502 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2503 D3DRENDERSTATETYPE dwRenderStateType,
2504 DWORD *lpdwRenderState)
2506 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2507 HRESULT hr;
2509 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2511 switch(dwRenderStateType)
2513 case D3DRENDERSTATE_TEXTUREHANDLE:
2515 /* This state is wrapped to SetTexture in SetRenderState, so
2516 * it has to be wrapped to GetTexture here. */
2517 struct wined3d_texture *tex = NULL;
2518 *lpdwRenderState = 0;
2520 wined3d_mutex_lock();
2521 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2522 if (SUCCEEDED(hr) && tex)
2524 /* The parent of the texture is the IDirectDrawSurface7
2525 * interface of the ddraw surface. */
2526 IDirectDrawSurfaceImpl *parent = wined3d_texture_get_parent(tex);
2527 if (parent) *lpdwRenderState = parent->Handle;
2528 wined3d_texture_decref(tex);
2530 wined3d_mutex_unlock();
2532 return hr;
2535 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2537 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2538 the mapping to get the value. */
2539 DWORD colorop, colorarg1, colorarg2;
2540 DWORD alphaop, alphaarg1, alphaarg2;
2542 wined3d_mutex_lock();
2544 This->legacyTextureBlending = TRUE;
2546 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLOROP, &colorop);
2547 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLORARG1, &colorarg1);
2548 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLORARG2, &colorarg2);
2549 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, &alphaop);
2550 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2551 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2553 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2554 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2556 *lpdwRenderState = D3DTBLEND_DECAL;
2558 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2559 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2561 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2563 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2564 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2566 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2568 else
2570 struct wined3d_texture *tex = NULL;
2571 HRESULT hr;
2572 BOOL tex_alpha = FALSE;
2573 DDPIXELFORMAT ddfmt;
2575 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2577 if(hr == WINED3D_OK && tex)
2579 struct wined3d_resource *sub_resource;
2581 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2583 struct wined3d_resource_desc desc;
2585 wined3d_resource_get_desc(sub_resource, &desc);
2586 ddfmt.dwSize = sizeof(ddfmt);
2587 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2588 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2591 wined3d_texture_decref(tex);
2594 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2595 alphaop == (tex_alpha ? WINED3DTOP_SELECTARG1 : WINED3DTOP_SELECTARG2) &&
2596 alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2598 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2601 *lpdwRenderState = D3DTBLEND_MODULATE;
2604 wined3d_mutex_unlock();
2606 return D3D_OK;
2609 default:
2610 return IDirect3DDevice7_GetRenderState(&This->IDirect3DDevice7_iface, dwRenderStateType, lpdwRenderState);
2614 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2615 D3DRENDERSTATETYPE dwRenderStateType, DWORD *lpdwRenderState)
2617 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2619 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2621 return IDirect3DDevice3_GetRenderState(&This->IDirect3DDevice3_iface,
2622 dwRenderStateType, lpdwRenderState);
2625 /*****************************************************************************
2626 * IDirect3DDevice7::SetRenderState
2628 * Sets a render state. The possible render states are defined in
2629 * include/d3dtypes.h
2631 * Version 2, 3 and 7
2633 * Params:
2634 * RenderStateType: State to set
2635 * Value: Value to assign to that state
2637 * Returns:
2638 * D3D_OK on success,
2639 * for details see IWineD3DDevice::SetRenderState
2641 *****************************************************************************/
2642 static HRESULT
2643 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2644 D3DRENDERSTATETYPE RenderStateType,
2645 DWORD Value)
2647 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
2648 HRESULT hr;
2650 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2652 wined3d_mutex_lock();
2653 /* Some render states need special care */
2654 switch(RenderStateType)
2657 * The ddraw texture filter mapping works like this:
2658 * D3DFILTER_NEAREST Point min/mag, no mip
2659 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2660 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2662 * D3DFILTER_LINEAR Linear min/mag, no mip
2663 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2664 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2666 * This is the opposite of the GL naming convention,
2667 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2669 case D3DRENDERSTATE_TEXTUREMAG:
2671 WINED3DTEXTUREFILTERTYPE tex_mag;
2673 switch (Value)
2675 case D3DFILTER_NEAREST:
2676 case D3DFILTER_MIPNEAREST:
2677 case D3DFILTER_LINEARMIPNEAREST:
2678 tex_mag = WINED3DTEXF_POINT;
2679 break;
2680 case D3DFILTER_LINEAR:
2681 case D3DFILTER_MIPLINEAR:
2682 case D3DFILTER_LINEARMIPLINEAR:
2683 tex_mag = WINED3DTEXF_LINEAR;
2684 break;
2685 default:
2686 tex_mag = WINED3DTEXF_POINT;
2687 ERR("Unhandled texture mag %d !\n",Value);
2688 break;
2691 hr = wined3d_device_set_sampler_state(This->wined3d_device, 0, WINED3DSAMP_MAGFILTER, tex_mag);
2692 break;
2695 case D3DRENDERSTATE_TEXTUREMIN:
2697 WINED3DTEXTUREFILTERTYPE tex_min;
2698 WINED3DTEXTUREFILTERTYPE tex_mip;
2700 switch ((D3DTEXTUREFILTER) Value)
2702 case D3DFILTER_NEAREST:
2703 tex_min = WINED3DTEXF_POINT;
2704 tex_mip = WINED3DTEXF_NONE;
2705 break;
2706 case D3DFILTER_LINEAR:
2707 tex_min = WINED3DTEXF_LINEAR;
2708 tex_mip = WINED3DTEXF_NONE;
2709 break;
2710 case D3DFILTER_MIPNEAREST:
2711 tex_min = WINED3DTEXF_POINT;
2712 tex_mip = WINED3DTEXF_POINT;
2713 break;
2714 case D3DFILTER_MIPLINEAR:
2715 tex_min = WINED3DTEXF_LINEAR;
2716 tex_mip = WINED3DTEXF_POINT;
2717 break;
2718 case D3DFILTER_LINEARMIPNEAREST:
2719 tex_min = WINED3DTEXF_POINT;
2720 tex_mip = WINED3DTEXF_LINEAR;
2721 break;
2722 case D3DFILTER_LINEARMIPLINEAR:
2723 tex_min = WINED3DTEXF_LINEAR;
2724 tex_mip = WINED3DTEXF_LINEAR;
2725 break;
2727 default:
2728 ERR("Unhandled texture min %d !\n",Value);
2729 tex_min = WINED3DTEXF_POINT;
2730 tex_mip = WINED3DTEXF_NONE;
2731 break;
2734 wined3d_device_set_sampler_state(This->wined3d_device,
2735 0, WINED3DSAMP_MIPFILTER, tex_mip);
2736 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2737 0, WINED3DSAMP_MINFILTER, tex_min);
2738 break;
2741 case D3DRENDERSTATE_TEXTUREADDRESS:
2742 wined3d_device_set_sampler_state(This->wined3d_device,
2743 0, WINED3DSAMP_ADDRESSV, Value);
2744 /* Drop through */
2745 case D3DRENDERSTATE_TEXTUREADDRESSU:
2746 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2747 0, WINED3DSAMP_ADDRESSU, Value);
2748 break;
2749 case D3DRENDERSTATE_TEXTUREADDRESSV:
2750 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2751 0, WINED3DSAMP_ADDRESSV, Value);
2752 break;
2754 case D3DRENDERSTATE_BORDERCOLOR:
2755 /* This should probably just forward to the corresponding sampler
2756 * state. Needs tests. */
2757 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2758 hr = E_NOTIMPL;
2759 break;
2761 case D3DRENDERSTATE_TEXTUREHANDLE:
2762 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2763 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2764 hr = DDERR_INVALIDPARAMS;
2765 break;
2767 case D3DRENDERSTATE_ZBIAS:
2768 hr = wined3d_device_set_render_state(This->wined3d_device, WINED3DRS_DEPTHBIAS, Value);
2769 break;
2771 default:
2772 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2773 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2775 FIXME("Unhandled stipple pattern render state (%#x).\n",
2776 RenderStateType);
2777 hr = E_NOTIMPL;
2778 break;
2781 hr = wined3d_device_set_render_state(This->wined3d_device, RenderStateType, Value);
2782 break;
2784 wined3d_mutex_unlock();
2786 return hr;
2789 static HRESULT WINAPI
2790 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2791 D3DRENDERSTATETYPE RenderStateType,
2792 DWORD Value)
2794 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2797 static HRESULT WINAPI
2798 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2799 D3DRENDERSTATETYPE RenderStateType,
2800 DWORD Value)
2802 HRESULT hr;
2803 WORD old_fpucw;
2805 old_fpucw = d3d_fpu_setup();
2806 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2807 set_fpu_control_word(old_fpucw);
2809 return hr;
2812 static HRESULT WINAPI
2813 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2814 D3DRENDERSTATETYPE RenderStateType,
2815 DWORD Value)
2817 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2818 for this state can be directly mapped to texture stage colorop and alphaop, but
2819 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2820 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2821 alphaarg when needed.
2823 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2825 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2826 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2827 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2828 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2829 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2830 in device - TRUE if the app is using TEXTUREMAPBLEND.
2832 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2833 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2834 unless some broken game will be found that cares. */
2836 HRESULT hr;
2837 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2839 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2841 wined3d_mutex_lock();
2843 switch(RenderStateType)
2845 case D3DRENDERSTATE_TEXTUREHANDLE:
2847 IDirectDrawSurfaceImpl *surf;
2849 if(Value == 0)
2851 hr = wined3d_device_set_texture(This->wined3d_device, 0, NULL);
2852 break;
2855 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2856 if (!surf)
2858 WARN("Invalid texture handle.\n");
2859 hr = DDERR_INVALIDPARAMS;
2860 break;
2863 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2864 break;
2867 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2869 This->legacyTextureBlending = TRUE;
2871 switch ( (D3DTEXTUREBLEND) Value)
2873 case D3DTBLEND_MODULATE:
2875 struct wined3d_texture *tex = NULL;
2876 BOOL tex_alpha = FALSE;
2877 DDPIXELFORMAT ddfmt;
2879 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2881 if(hr == WINED3D_OK && tex)
2883 struct wined3d_resource *sub_resource;
2885 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2887 struct wined3d_resource_desc desc;
2889 wined3d_resource_get_desc(sub_resource, &desc);
2890 ddfmt.dwSize = sizeof(ddfmt);
2891 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2892 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2895 wined3d_texture_decref(tex);
2898 if (tex_alpha)
2899 wined3d_device_set_texture_stage_state(This->wined3d_device,
2900 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2901 else
2902 wined3d_device_set_texture_stage_state(This->wined3d_device,
2903 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2904 wined3d_device_set_texture_stage_state(This->wined3d_device,
2905 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2906 wined3d_device_set_texture_stage_state(This->wined3d_device,
2907 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2908 wined3d_device_set_texture_stage_state(This->wined3d_device,
2909 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2910 wined3d_device_set_texture_stage_state(This->wined3d_device,
2911 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2912 wined3d_device_set_texture_stage_state(This->wined3d_device,
2913 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2914 break;
2917 case D3DTBLEND_ADD:
2918 wined3d_device_set_texture_stage_state(This->wined3d_device,
2919 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2920 wined3d_device_set_texture_stage_state(This->wined3d_device,
2921 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2922 wined3d_device_set_texture_stage_state(This->wined3d_device,
2923 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2924 wined3d_device_set_texture_stage_state(This->wined3d_device,
2925 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2926 wined3d_device_set_texture_stage_state(This->wined3d_device,
2927 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2928 break;
2930 case D3DTBLEND_MODULATEALPHA:
2931 wined3d_device_set_texture_stage_state(This->wined3d_device,
2932 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2933 wined3d_device_set_texture_stage_state(This->wined3d_device,
2934 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2935 wined3d_device_set_texture_stage_state(This->wined3d_device,
2936 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2937 wined3d_device_set_texture_stage_state(This->wined3d_device,
2938 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2939 wined3d_device_set_texture_stage_state(This->wined3d_device,
2940 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2941 wined3d_device_set_texture_stage_state(This->wined3d_device,
2942 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2943 break;
2945 case D3DTBLEND_COPY:
2946 case D3DTBLEND_DECAL:
2947 wined3d_device_set_texture_stage_state(This->wined3d_device,
2948 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2949 wined3d_device_set_texture_stage_state(This->wined3d_device,
2950 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2951 wined3d_device_set_texture_stage_state(This->wined3d_device,
2952 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2953 wined3d_device_set_texture_stage_state(This->wined3d_device,
2954 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2955 break;
2957 case D3DTBLEND_DECALALPHA:
2958 wined3d_device_set_texture_stage_state(This->wined3d_device,
2959 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2960 wined3d_device_set_texture_stage_state(This->wined3d_device,
2961 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2962 wined3d_device_set_texture_stage_state(This->wined3d_device,
2963 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2964 wined3d_device_set_texture_stage_state(This->wined3d_device,
2965 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2966 wined3d_device_set_texture_stage_state(This->wined3d_device,
2967 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2968 break;
2970 default:
2971 ERR("Unhandled texture environment %d !\n",Value);
2974 hr = D3D_OK;
2975 break;
2978 default:
2979 hr = IDirect3DDevice7_SetRenderState(&This->IDirect3DDevice7_iface, RenderStateType, Value);
2980 break;
2982 wined3d_mutex_unlock();
2984 return hr;
2987 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2988 D3DRENDERSTATETYPE RenderStateType, DWORD Value)
2990 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2992 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2994 return IDirect3DDevice3_SetRenderState(&This->IDirect3DDevice3_iface, RenderStateType, Value);
2997 /*****************************************************************************
2998 * Direct3DDevice3::SetLightState
3000 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
3001 * light states are forwarded to Direct3DDevice7 render states
3003 * Version 2 and 3
3005 * Params:
3006 * LightStateType: The light state to change
3007 * Value: The value to assign to that light state
3009 * Returns:
3010 * D3D_OK on success
3011 * DDERR_INVALIDPARAMS if the parameters were incorrect
3012 * Also check IDirect3DDevice7::SetRenderState
3014 *****************************************************************************/
3015 static HRESULT WINAPI
3016 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
3017 D3DLIGHTSTATETYPE LightStateType,
3018 DWORD Value)
3020 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3021 HRESULT hr;
3023 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3025 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3027 TRACE("Unexpected Light State Type\n");
3028 return DDERR_INVALIDPARAMS;
3031 wined3d_mutex_lock();
3032 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3034 IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
3035 if (!m)
3037 WARN("Invalid material handle.\n");
3038 wined3d_mutex_unlock();
3039 return DDERR_INVALIDPARAMS;
3042 TRACE(" activating material %p.\n", m);
3043 material_activate(m);
3045 This->material = Value;
3047 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3049 switch (Value)
3051 case D3DCOLOR_MONO:
3052 ERR("DDCOLOR_MONO should not happen!\n");
3053 break;
3054 case D3DCOLOR_RGB:
3055 /* We are already in this mode */
3056 TRACE("Setting color model to RGB (no-op).\n");
3057 break;
3058 default:
3059 ERR("Unknown color model!\n");
3060 wined3d_mutex_unlock();
3061 return DDERR_INVALIDPARAMS;
3064 else
3066 D3DRENDERSTATETYPE rs;
3067 switch (LightStateType)
3069 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3070 rs = D3DRENDERSTATE_AMBIENT;
3071 break;
3072 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3073 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3074 break;
3075 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3076 rs = D3DRENDERSTATE_FOGSTART;
3077 break;
3078 case D3DLIGHTSTATE_FOGEND: /* 6 */
3079 rs = D3DRENDERSTATE_FOGEND;
3080 break;
3081 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3082 rs = D3DRENDERSTATE_FOGDENSITY;
3083 break;
3084 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3085 rs = D3DRENDERSTATE_COLORVERTEX;
3086 break;
3087 default:
3088 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3089 wined3d_mutex_unlock();
3090 return DDERR_INVALIDPARAMS;
3093 hr = IDirect3DDevice7_SetRenderState(&This->IDirect3DDevice7_iface, rs, Value);
3094 wined3d_mutex_unlock();
3095 return hr;
3097 wined3d_mutex_unlock();
3099 return D3D_OK;
3102 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3103 D3DLIGHTSTATETYPE LightStateType, DWORD Value)
3105 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3107 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3109 return IDirect3DDevice3_SetLightState(&This->IDirect3DDevice3_iface, LightStateType, Value);
3112 /*****************************************************************************
3113 * IDirect3DDevice3::GetLightState
3115 * Returns the current setting of a light state. The state is read from
3116 * the Direct3DDevice7 render state.
3118 * Version 2 and 3
3120 * Params:
3121 * LightStateType: The light state to return
3122 * Value: The address to store the light state setting at
3124 * Returns:
3125 * D3D_OK on success
3126 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3127 * Also see IDirect3DDevice7::GetRenderState
3129 *****************************************************************************/
3130 static HRESULT WINAPI
3131 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3132 D3DLIGHTSTATETYPE LightStateType,
3133 DWORD *Value)
3135 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3136 HRESULT hr;
3138 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3140 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3142 TRACE("Unexpected Light State Type\n");
3143 return DDERR_INVALIDPARAMS;
3146 if(!Value)
3147 return DDERR_INVALIDPARAMS;
3149 wined3d_mutex_lock();
3150 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3152 *Value = This->material;
3154 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3156 *Value = D3DCOLOR_RGB;
3158 else
3160 D3DRENDERSTATETYPE rs;
3161 switch (LightStateType)
3163 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3164 rs = D3DRENDERSTATE_AMBIENT;
3165 break;
3166 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3167 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3168 break;
3169 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3170 rs = D3DRENDERSTATE_FOGSTART;
3171 break;
3172 case D3DLIGHTSTATE_FOGEND: /* 6 */
3173 rs = D3DRENDERSTATE_FOGEND;
3174 break;
3175 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3176 rs = D3DRENDERSTATE_FOGDENSITY;
3177 break;
3178 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3179 rs = D3DRENDERSTATE_COLORVERTEX;
3180 break;
3181 default:
3182 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3183 wined3d_mutex_unlock();
3184 return DDERR_INVALIDPARAMS;
3187 hr = IDirect3DDevice7_GetRenderState(&This->IDirect3DDevice7_iface, rs, Value);
3188 wined3d_mutex_unlock();
3189 return hr;
3191 wined3d_mutex_unlock();
3193 return D3D_OK;
3196 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3197 D3DLIGHTSTATETYPE LightStateType, DWORD *Value)
3199 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3201 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3203 return IDirect3DDevice3_GetLightState(&This->IDirect3DDevice3_iface, LightStateType, Value);
3206 /*****************************************************************************
3207 * IDirect3DDevice7::SetTransform
3209 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3210 * in include/d3dtypes.h.
3211 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3212 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3213 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3215 * Version 2, 3 and 7
3217 * Params:
3218 * TransformStateType: transform state to set
3219 * Matrix: Matrix to assign to the state
3221 * Returns:
3222 * D3D_OK on success
3223 * DDERR_INVALIDPARAMS if Matrix == NULL
3224 * For details see IWineD3DDevice::SetTransform
3226 *****************************************************************************/
3227 static HRESULT
3228 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3229 D3DTRANSFORMSTATETYPE TransformStateType,
3230 D3DMATRIX *Matrix)
3232 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3233 D3DTRANSFORMSTATETYPE type;
3234 HRESULT hr;
3236 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3238 switch(TransformStateType)
3240 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3241 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3242 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3243 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3244 default: type = TransformStateType;
3247 if (!Matrix)
3248 return DDERR_INVALIDPARAMS;
3250 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3251 wined3d_mutex_lock();
3252 hr = wined3d_device_set_transform(This->wined3d_device, type, (struct wined3d_matrix *)Matrix);
3253 wined3d_mutex_unlock();
3255 return hr;
3258 static HRESULT WINAPI
3259 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3260 D3DTRANSFORMSTATETYPE TransformStateType,
3261 D3DMATRIX *Matrix)
3263 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3266 static HRESULT WINAPI
3267 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3268 D3DTRANSFORMSTATETYPE TransformStateType,
3269 D3DMATRIX *Matrix)
3271 HRESULT hr;
3272 WORD old_fpucw;
3274 old_fpucw = d3d_fpu_setup();
3275 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3276 set_fpu_control_word(old_fpucw);
3278 return hr;
3281 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3282 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3284 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3286 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3288 return IDirect3DDevice7_SetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3291 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3292 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3294 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3296 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3298 return IDirect3DDevice7_SetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3301 /*****************************************************************************
3302 * IDirect3DDevice7::GetTransform
3304 * Returns the matrix assigned to a transform state
3305 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3306 * SetTransform
3308 * Params:
3309 * TransformStateType: State to read the matrix from
3310 * Matrix: Address to store the matrix at
3312 * Returns:
3313 * D3D_OK on success
3314 * DDERR_INVALIDPARAMS if Matrix == NULL
3315 * For details, see IWineD3DDevice::GetTransform
3317 *****************************************************************************/
3318 static HRESULT
3319 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3320 D3DTRANSFORMSTATETYPE TransformStateType,
3321 D3DMATRIX *Matrix)
3323 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3324 D3DTRANSFORMSTATETYPE type;
3325 HRESULT hr;
3327 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3329 switch(TransformStateType)
3331 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3332 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3333 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3334 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3335 default: type = TransformStateType;
3338 if(!Matrix)
3339 return DDERR_INVALIDPARAMS;
3341 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3342 wined3d_mutex_lock();
3343 hr = wined3d_device_get_transform(This->wined3d_device, type, (struct wined3d_matrix *)Matrix);
3344 wined3d_mutex_unlock();
3346 return hr;
3349 static HRESULT WINAPI
3350 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3351 D3DTRANSFORMSTATETYPE TransformStateType,
3352 D3DMATRIX *Matrix)
3354 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3357 static HRESULT WINAPI
3358 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3359 D3DTRANSFORMSTATETYPE TransformStateType,
3360 D3DMATRIX *Matrix)
3362 HRESULT hr;
3363 WORD old_fpucw;
3365 old_fpucw = d3d_fpu_setup();
3366 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3367 set_fpu_control_word(old_fpucw);
3369 return hr;
3372 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3373 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3375 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3377 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3379 return IDirect3DDevice7_GetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3382 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3383 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3385 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3387 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3389 return IDirect3DDevice7_GetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3392 /*****************************************************************************
3393 * IDirect3DDevice7::MultiplyTransform
3395 * Multiplies the already-set transform matrix of a transform state
3396 * with another matrix. For the world matrix, see SetTransform
3398 * Version 2, 3 and 7
3400 * Params:
3401 * TransformStateType: Transform state to multiply
3402 * D3DMatrix Matrix to multiply with.
3404 * Returns
3405 * D3D_OK on success
3406 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3407 * For details, see IWineD3DDevice::MultiplyTransform
3409 *****************************************************************************/
3410 static HRESULT
3411 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3412 D3DTRANSFORMSTATETYPE TransformStateType,
3413 D3DMATRIX *D3DMatrix)
3415 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3416 HRESULT hr;
3417 D3DTRANSFORMSTATETYPE type;
3419 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3421 switch(TransformStateType)
3423 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3424 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3425 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3426 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3427 default: type = TransformStateType;
3430 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3431 wined3d_mutex_lock();
3432 hr = wined3d_device_multiply_transform(This->wined3d_device,
3433 type, (struct wined3d_matrix *)D3DMatrix);
3434 wined3d_mutex_unlock();
3436 return hr;
3439 static HRESULT WINAPI
3440 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3441 D3DTRANSFORMSTATETYPE TransformStateType,
3442 D3DMATRIX *D3DMatrix)
3444 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3447 static HRESULT WINAPI
3448 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3449 D3DTRANSFORMSTATETYPE TransformStateType,
3450 D3DMATRIX *D3DMatrix)
3452 HRESULT hr;
3453 WORD old_fpucw;
3455 old_fpucw = d3d_fpu_setup();
3456 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3457 set_fpu_control_word(old_fpucw);
3459 return hr;
3462 static HRESULT WINAPI IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3463 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3465 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3467 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3469 return IDirect3DDevice7_MultiplyTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3472 static HRESULT WINAPI IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3473 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3475 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3477 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3479 return IDirect3DDevice7_MultiplyTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3482 /*****************************************************************************
3483 * IDirect3DDevice7::DrawPrimitive
3485 * Draws primitives based on vertices in an application-provided pointer
3487 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3488 * an FVF format for D3D7
3490 * Params:
3491 * PrimitiveType: The type of the primitives to draw
3492 * Vertex type: Flexible vertex format vertex description
3493 * Vertices: Pointer to the vertex array
3494 * VertexCount: The number of vertices to draw
3495 * Flags: As usual a few flags
3497 * Returns:
3498 * D3D_OK on success
3499 * DDERR_INVALIDPARAMS if Vertices is NULL
3500 * For details, see IWineD3DDevice::DrawPrimitiveUP
3502 *****************************************************************************/
3503 static HRESULT
3504 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3505 D3DPRIMITIVETYPE PrimitiveType,
3506 DWORD VertexType,
3507 void *Vertices,
3508 DWORD VertexCount,
3509 DWORD Flags)
3511 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3512 UINT stride;
3513 HRESULT hr;
3515 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3516 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3518 if(!Vertices)
3519 return DDERR_INVALIDPARAMS;
3521 /* Get the stride */
3522 stride = get_flexible_vertex_size(VertexType);
3524 /* Set the FVF */
3525 wined3d_mutex_lock();
3526 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3527 if(hr != D3D_OK)
3529 wined3d_mutex_unlock();
3530 return hr;
3533 /* This method translates to the user pointer draw of WineD3D */
3534 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3535 hr = wined3d_device_draw_primitive_up(This->wined3d_device, VertexCount, Vertices, stride);
3536 wined3d_mutex_unlock();
3538 return hr;
3541 static HRESULT WINAPI
3542 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3543 D3DPRIMITIVETYPE PrimitiveType,
3544 DWORD VertexType,
3545 void *Vertices,
3546 DWORD VertexCount,
3547 DWORD Flags)
3549 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3552 static HRESULT WINAPI
3553 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3554 D3DPRIMITIVETYPE PrimitiveType,
3555 DWORD VertexType,
3556 void *Vertices,
3557 DWORD VertexCount,
3558 DWORD Flags)
3560 HRESULT hr;
3561 WORD old_fpucw;
3563 old_fpucw = d3d_fpu_setup();
3564 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3565 set_fpu_control_word(old_fpucw);
3567 return hr;
3570 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3571 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3572 DWORD Flags)
3574 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3575 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3576 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3578 return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface,
3579 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3582 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3583 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3584 DWORD VertexCount, DWORD Flags)
3586 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3587 DWORD FVF;
3589 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3590 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3592 switch(VertexType)
3594 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3595 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3596 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3597 default:
3598 ERR("Unexpected vertex type %d\n", VertexType);
3599 return DDERR_INVALIDPARAMS; /* Should never happen */
3602 return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface,
3603 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3606 /*****************************************************************************
3607 * IDirect3DDevice7::DrawIndexedPrimitive
3609 * Draws vertices from an application-provided pointer, based on the index
3610 * numbers in a WORD array.
3612 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3613 * an FVF format for D3D7
3615 * Params:
3616 * PrimitiveType: The primitive type to draw
3617 * VertexType: The FVF vertex description
3618 * Vertices: Pointer to the vertex array
3619 * VertexCount: ?
3620 * Indices: Pointer to the index array
3621 * IndexCount: Number of indices = Number of vertices to draw
3622 * Flags: As usual, some flags
3624 * Returns:
3625 * D3D_OK on success
3626 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3627 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3629 *****************************************************************************/
3630 static HRESULT
3631 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3632 D3DPRIMITIVETYPE PrimitiveType,
3633 DWORD VertexType,
3634 void *Vertices,
3635 DWORD VertexCount,
3636 WORD *Indices,
3637 DWORD IndexCount,
3638 DWORD Flags)
3640 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3641 HRESULT hr;
3643 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3644 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3646 /* Set the D3DDevice's FVF */
3647 wined3d_mutex_lock();
3648 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3649 if(FAILED(hr))
3651 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3652 wined3d_mutex_unlock();
3653 return hr;
3656 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3657 hr = wined3d_device_draw_indexed_primitive_up(This->wined3d_device, IndexCount, Indices,
3658 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3659 wined3d_mutex_unlock();
3661 return hr;
3664 static HRESULT WINAPI
3665 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3666 D3DPRIMITIVETYPE PrimitiveType,
3667 DWORD VertexType,
3668 void *Vertices,
3669 DWORD VertexCount,
3670 WORD *Indices,
3671 DWORD IndexCount,
3672 DWORD Flags)
3674 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3677 static HRESULT WINAPI
3678 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3679 D3DPRIMITIVETYPE PrimitiveType,
3680 DWORD VertexType,
3681 void *Vertices,
3682 DWORD VertexCount,
3683 WORD *Indices,
3684 DWORD IndexCount,
3685 DWORD Flags)
3687 HRESULT hr;
3688 WORD old_fpucw;
3690 old_fpucw = d3d_fpu_setup();
3691 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3692 set_fpu_control_word(old_fpucw);
3694 return hr;
3697 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3698 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3699 WORD *Indices, DWORD IndexCount, DWORD Flags)
3701 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3702 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3703 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3705 return IDirect3DDevice7_DrawIndexedPrimitive(&This->IDirect3DDevice7_iface,
3706 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3709 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3710 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3711 DWORD VertexCount, WORD *Indices, DWORD IndexCount, DWORD Flags)
3713 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3714 DWORD FVF;
3716 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3717 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3719 switch(VertexType)
3721 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3722 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3723 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3724 default:
3725 ERR("Unexpected vertex type %d\n", VertexType);
3726 return DDERR_INVALIDPARAMS; /* Should never happen */
3729 return IDirect3DDevice7_DrawIndexedPrimitive(&This->IDirect3DDevice7_iface,
3730 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3733 /*****************************************************************************
3734 * IDirect3DDevice7::SetClipStatus
3736 * Sets the clip status. This defines things as clipping conditions and
3737 * the extents of the clipping region.
3739 * Version 2, 3 and 7
3741 * Params:
3742 * ClipStatus:
3744 * Returns:
3745 * D3D_OK because it's a stub
3746 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3748 *****************************************************************************/
3749 static HRESULT WINAPI
3750 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3751 D3DCLIPSTATUS *ClipStatus)
3753 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3755 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3756 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3758 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3759 return D3D_OK;
3762 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3763 D3DCLIPSTATUS *ClipStatus)
3765 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3766 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3768 return IDirect3DDevice7_SetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3771 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3772 D3DCLIPSTATUS *ClipStatus)
3774 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3775 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3777 return IDirect3DDevice7_SetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3780 /*****************************************************************************
3781 * IDirect3DDevice7::GetClipStatus
3783 * Returns the clip status
3785 * Params:
3786 * ClipStatus: Address to write the clip status to
3788 * Returns:
3789 * D3D_OK because it's a stub
3791 *****************************************************************************/
3792 static HRESULT WINAPI
3793 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3794 D3DCLIPSTATUS *ClipStatus)
3796 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3798 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3799 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3800 return D3D_OK;
3803 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3804 D3DCLIPSTATUS *ClipStatus)
3806 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3807 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3809 return IDirect3DDevice7_GetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3812 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3813 D3DCLIPSTATUS *ClipStatus)
3815 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3816 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3818 return IDirect3DDevice7_GetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3821 /*****************************************************************************
3822 * IDirect3DDevice::DrawPrimitiveStrided
3824 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3826 * Version 3 and 7
3828 * Params:
3829 * PrimitiveType: The primitive type to draw
3830 * VertexType: The FVF description of the vertices to draw (for the stride??)
3831 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3832 * the vertex data locations
3833 * VertexCount: The number of vertices to draw
3834 * Flags: Some flags
3836 * Returns:
3837 * D3D_OK, because it's a stub
3838 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3839 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3841 *****************************************************************************/
3842 static HRESULT
3843 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3844 D3DPRIMITIVETYPE PrimitiveType,
3845 DWORD VertexType,
3846 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3847 DWORD VertexCount,
3848 DWORD Flags)
3850 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3851 WineDirect3DVertexStridedData WineD3DStrided;
3852 DWORD i;
3853 HRESULT hr;
3855 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3856 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3858 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3859 /* Get the strided data right. the wined3d structure is a bit bigger
3860 * Watch out: The contents of the strided data are determined by the fvf,
3861 * not by the members set in D3DDrawPrimStrideData. So it's valid
3862 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3863 * not set in the fvf.
3865 if(VertexType & D3DFVF_POSITION_MASK)
3867 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3868 WineD3DStrided.position.data = D3DDrawPrimStrideData->position.lpvData;
3869 WineD3DStrided.position.stride = D3DDrawPrimStrideData->position.dwStride;
3870 if (VertexType & D3DFVF_XYZRHW)
3872 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3873 WineD3DStrided.position_transformed = TRUE;
3874 } else
3875 WineD3DStrided.position_transformed = FALSE;
3878 if(VertexType & D3DFVF_NORMAL)
3880 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3881 WineD3DStrided.normal.data = D3DDrawPrimStrideData->normal.lpvData;
3882 WineD3DStrided.normal.stride = D3DDrawPrimStrideData->normal.dwStride;
3885 if(VertexType & D3DFVF_DIFFUSE)
3887 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3888 WineD3DStrided.diffuse.data = D3DDrawPrimStrideData->diffuse.lpvData;
3889 WineD3DStrided.diffuse.stride = D3DDrawPrimStrideData->diffuse.dwStride;
3892 if(VertexType & D3DFVF_SPECULAR)
3894 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3895 WineD3DStrided.specular.data = D3DDrawPrimStrideData->specular.lpvData;
3896 WineD3DStrided.specular.stride = D3DDrawPrimStrideData->specular.dwStride;
3899 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3901 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3903 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3904 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3905 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3906 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3907 default: ERR("Unexpected texture coordinate size %d\n",
3908 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3910 WineD3DStrided.texCoords[i].data = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3911 WineD3DStrided.texCoords[i].stride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3914 /* WineD3D doesn't need the FVF here */
3915 wined3d_mutex_lock();
3916 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3917 hr = wined3d_device_draw_primitive_strided(This->wined3d_device, VertexCount, &WineD3DStrided);
3918 wined3d_mutex_unlock();
3920 return hr;
3923 static HRESULT WINAPI
3924 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3925 D3DPRIMITIVETYPE PrimitiveType,
3926 DWORD VertexType,
3927 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3928 DWORD VertexCount,
3929 DWORD Flags)
3931 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3934 static HRESULT WINAPI
3935 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3936 D3DPRIMITIVETYPE PrimitiveType,
3937 DWORD VertexType,
3938 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3939 DWORD VertexCount,
3940 DWORD Flags)
3942 HRESULT hr;
3943 WORD old_fpucw;
3945 old_fpucw = d3d_fpu_setup();
3946 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3947 set_fpu_control_word(old_fpucw);
3949 return hr;
3952 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3953 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3954 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3956 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3958 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3959 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3961 return IDirect3DDevice7_DrawPrimitiveStrided(&This->IDirect3DDevice7_iface,
3962 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3965 /*****************************************************************************
3966 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3968 * Draws primitives specified by strided data locations based on indices
3970 * Version 3 and 7
3972 * Params:
3973 * PrimitiveType:
3975 * Returns:
3976 * D3D_OK, because it's a stub
3977 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3978 * (DDERR_INVALIDPARAMS if Indices is NULL)
3979 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3981 *****************************************************************************/
3982 static HRESULT
3983 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3984 D3DPRIMITIVETYPE PrimitiveType,
3985 DWORD VertexType,
3986 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3987 DWORD VertexCount,
3988 WORD *Indices,
3989 DWORD IndexCount,
3990 DWORD Flags)
3992 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3993 WineDirect3DVertexStridedData WineD3DStrided;
3994 DWORD i;
3995 HRESULT hr;
3997 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3998 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4000 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
4001 /* Get the strided data right. the wined3d structure is a bit bigger
4002 * Watch out: The contents of the strided data are determined by the fvf,
4003 * not by the members set in D3DDrawPrimStrideData. So it's valid
4004 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
4005 * not set in the fvf.
4007 if(VertexType & D3DFVF_POSITION_MASK)
4009 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
4010 WineD3DStrided.position.data = D3DDrawPrimStrideData->position.lpvData;
4011 WineD3DStrided.position.stride = D3DDrawPrimStrideData->position.dwStride;
4012 if (VertexType & D3DFVF_XYZRHW)
4014 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
4015 WineD3DStrided.position_transformed = TRUE;
4016 } else
4017 WineD3DStrided.position_transformed = FALSE;
4020 if(VertexType & D3DFVF_NORMAL)
4022 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
4023 WineD3DStrided.normal.data = D3DDrawPrimStrideData->normal.lpvData;
4024 WineD3DStrided.normal.stride = D3DDrawPrimStrideData->normal.dwStride;
4027 if(VertexType & D3DFVF_DIFFUSE)
4029 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
4030 WineD3DStrided.diffuse.data = D3DDrawPrimStrideData->diffuse.lpvData;
4031 WineD3DStrided.diffuse.stride = D3DDrawPrimStrideData->diffuse.dwStride;
4034 if(VertexType & D3DFVF_SPECULAR)
4036 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
4037 WineD3DStrided.specular.data = D3DDrawPrimStrideData->specular.lpvData;
4038 WineD3DStrided.specular.stride = D3DDrawPrimStrideData->specular.dwStride;
4041 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
4043 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
4045 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
4046 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
4047 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
4048 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
4049 default: ERR("Unexpected texture coordinate size %d\n",
4050 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4052 WineD3DStrided.texCoords[i].data = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4053 WineD3DStrided.texCoords[i].stride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4056 /* WineD3D doesn't need the FVF here */
4057 wined3d_mutex_lock();
4058 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4059 hr = wined3d_device_draw_indexed_primitive_strided(This->wined3d_device,
4060 IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
4061 wined3d_mutex_unlock();
4063 return hr;
4066 static HRESULT WINAPI
4067 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4068 D3DPRIMITIVETYPE PrimitiveType,
4069 DWORD VertexType,
4070 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4071 DWORD VertexCount,
4072 WORD *Indices,
4073 DWORD IndexCount,
4074 DWORD Flags)
4076 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4079 static HRESULT WINAPI
4080 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4081 D3DPRIMITIVETYPE PrimitiveType,
4082 DWORD VertexType,
4083 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4084 DWORD VertexCount,
4085 WORD *Indices,
4086 DWORD IndexCount,
4087 DWORD Flags)
4089 HRESULT hr;
4090 WORD old_fpucw;
4092 old_fpucw = d3d_fpu_setup();
4093 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4094 set_fpu_control_word(old_fpucw);
4096 return hr;
4099 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4100 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4101 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4102 DWORD IndexCount, DWORD Flags)
4104 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4106 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4107 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4109 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&This->IDirect3DDevice7_iface,
4110 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4113 /*****************************************************************************
4114 * IDirect3DDevice7::DrawPrimitiveVB
4116 * Draws primitives from a vertex buffer to the screen.
4118 * Version 3 and 7
4120 * Params:
4121 * PrimitiveType: Type of primitive to be rendered.
4122 * D3DVertexBuf: Source Vertex Buffer
4123 * StartVertex: Index of the first vertex from the buffer to be rendered
4124 * NumVertices: Number of vertices to be rendered
4125 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4127 * Return values
4128 * D3D_OK on success
4129 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4131 *****************************************************************************/
4132 static HRESULT
4133 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4134 D3DPRIMITIVETYPE PrimitiveType,
4135 IDirect3DVertexBuffer7 *D3DVertexBuf,
4136 DWORD StartVertex,
4137 DWORD NumVertices,
4138 DWORD Flags)
4140 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4141 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4142 HRESULT hr;
4143 DWORD stride;
4145 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4146 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4148 /* Sanity checks */
4149 if(!vb)
4151 ERR("(%p) No Vertex buffer specified\n", This);
4152 return DDERR_INVALIDPARAMS;
4154 stride = get_flexible_vertex_size(vb->fvf);
4156 wined3d_mutex_lock();
4157 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4158 if (FAILED(hr))
4160 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4161 wined3d_mutex_unlock();
4162 return hr;
4165 /* Set the vertex stream source */
4166 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4167 if(hr != D3D_OK)
4169 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4170 wined3d_mutex_unlock();
4171 return hr;
4174 /* Now draw the primitives */
4175 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4176 hr = wined3d_device_draw_primitive(This->wined3d_device, StartVertex, NumVertices);
4177 wined3d_mutex_unlock();
4179 return hr;
4182 static HRESULT WINAPI
4183 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4184 D3DPRIMITIVETYPE PrimitiveType,
4185 IDirect3DVertexBuffer7 *D3DVertexBuf,
4186 DWORD StartVertex,
4187 DWORD NumVertices,
4188 DWORD Flags)
4190 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4193 static HRESULT WINAPI
4194 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4195 D3DPRIMITIVETYPE PrimitiveType,
4196 IDirect3DVertexBuffer7 *D3DVertexBuf,
4197 DWORD StartVertex,
4198 DWORD NumVertices,
4199 DWORD Flags)
4201 HRESULT hr;
4202 WORD old_fpucw;
4204 old_fpucw = d3d_fpu_setup();
4205 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4206 set_fpu_control_word(old_fpucw);
4208 return hr;
4211 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4212 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex,
4213 DWORD NumVertices, DWORD Flags)
4215 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4216 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4218 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4219 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4221 return IDirect3DDevice7_DrawPrimitiveVB(&This->IDirect3DDevice7_iface,
4222 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4226 /*****************************************************************************
4227 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4229 * Draws primitives from a vertex buffer to the screen
4231 * Params:
4232 * PrimitiveType: Type of primitive to be rendered.
4233 * D3DVertexBuf: Source Vertex Buffer
4234 * StartVertex: Index of the first vertex from the buffer to be rendered
4235 * NumVertices: Number of vertices to be rendered
4236 * Indices: Array of DWORDs used to index into the Vertices
4237 * IndexCount: Number of indices in Indices
4238 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4240 * Return values
4242 *****************************************************************************/
4243 static HRESULT
4244 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4245 D3DPRIMITIVETYPE PrimitiveType,
4246 IDirect3DVertexBuffer7 *D3DVertexBuf,
4247 DWORD StartVertex,
4248 DWORD NumVertices,
4249 WORD *Indices,
4250 DWORD IndexCount,
4251 DWORD Flags)
4253 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4254 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4255 DWORD stride = get_flexible_vertex_size(vb->fvf);
4256 struct wined3d_resource *wined3d_resource;
4257 struct wined3d_resource_desc desc;
4258 WORD *LockedIndices;
4259 HRESULT hr;
4261 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4262 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4264 /* Steps:
4265 * 1) Upload the Indices to the index buffer
4266 * 2) Set the index source
4267 * 3) Set the Vertex Buffer as the Stream source
4268 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4271 wined3d_mutex_lock();
4273 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4274 if (FAILED(hr))
4276 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4277 wined3d_mutex_unlock();
4278 return hr;
4281 /* check that the buffer is large enough to hold the indices,
4282 * reallocate if necessary. */
4283 wined3d_resource = wined3d_buffer_get_resource(This->indexbuffer);
4284 wined3d_resource_get_desc(wined3d_resource, &desc);
4285 if (desc.size < IndexCount * sizeof(WORD))
4287 UINT size = max(desc.size * 2, IndexCount * sizeof(WORD));
4288 struct wined3d_buffer *buffer;
4290 TRACE("Growing index buffer to %u bytes\n", size);
4292 hr = wined3d_buffer_create_ib(This->wined3d_device, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4293 WINED3DPOOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
4294 if (FAILED(hr))
4296 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4297 wined3d_mutex_unlock();
4298 return hr;
4301 wined3d_buffer_decref(This->indexbuffer);
4302 This->indexbuffer = buffer;
4305 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4306 * method could be created which takes an user pointer containing the
4307 * indices or a SetData-Method for the index buffer, which overrides the
4308 * index buffer data with our pointer. */
4309 hr = wined3d_buffer_map(This->indexbuffer, 0, IndexCount * sizeof(WORD),
4310 (BYTE **)&LockedIndices, 0);
4311 if (FAILED(hr))
4313 ERR("Failed to map buffer, hr %#x.\n", hr);
4314 wined3d_mutex_unlock();
4315 return hr;
4317 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4318 wined3d_buffer_unmap(This->indexbuffer);
4320 /* Set the index stream */
4321 wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4322 hr = wined3d_device_set_index_buffer(This->wined3d_device, This->indexbuffer, WINED3DFMT_R16_UINT);
4324 /* Set the vertex stream source */
4325 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4326 if (FAILED(hr))
4328 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4329 wined3d_mutex_unlock();
4330 return hr;
4334 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4335 hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, 0, IndexCount);
4337 wined3d_mutex_unlock();
4339 return hr;
4342 static HRESULT WINAPI
4343 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4344 D3DPRIMITIVETYPE PrimitiveType,
4345 IDirect3DVertexBuffer7 *D3DVertexBuf,
4346 DWORD StartVertex,
4347 DWORD NumVertices,
4348 WORD *Indices,
4349 DWORD IndexCount,
4350 DWORD Flags)
4352 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4355 static HRESULT WINAPI
4356 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4357 D3DPRIMITIVETYPE PrimitiveType,
4358 IDirect3DVertexBuffer7 *D3DVertexBuf,
4359 DWORD StartVertex,
4360 DWORD NumVertices,
4361 WORD *Indices,
4362 DWORD IndexCount,
4363 DWORD Flags)
4365 HRESULT hr;
4366 WORD old_fpucw;
4368 old_fpucw = d3d_fpu_setup();
4369 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4370 set_fpu_control_word(old_fpucw);
4372 return hr;
4375 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4376 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4377 DWORD IndexCount, DWORD Flags)
4379 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4380 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4382 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4383 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4385 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&This->IDirect3DDevice7_iface,
4386 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount,
4387 Flags);
4390 /*****************************************************************************
4391 * IDirect3DDevice7::ComputeSphereVisibility
4393 * Calculates the visibility of spheres in the current viewport. The spheres
4394 * are passed in the Centers and Radii arrays, the results are passed back
4395 * in the ReturnValues array. Return values are either completely visible,
4396 * partially visible or completely invisible.
4397 * The return value consist of a combination of D3DCLIP_* flags, or it's
4398 * 0 if the sphere is completely visible(according to the SDK, not checked)
4400 * Version 3 and 7
4402 * Params:
4403 * Centers: Array containing the sphere centers
4404 * Radii: Array containing the sphere radii
4405 * NumSpheres: The number of centers and radii in the arrays
4406 * Flags: Some flags
4407 * ReturnValues: Array to write the results to
4409 * Returns:
4410 * D3D_OK
4411 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4412 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4413 * is singular)
4415 *****************************************************************************/
4417 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4419 float distance, norm;
4421 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4422 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4424 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4425 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4426 return 0;
4429 static HRESULT WINAPI
4430 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4431 D3DVECTOR *Centers,
4432 D3DVALUE *Radii,
4433 DWORD NumSpheres,
4434 DWORD Flags,
4435 DWORD *ReturnValues)
4437 D3DMATRIX m, temp;
4438 D3DVALUE origin_plane[6];
4439 D3DVECTOR vec[6];
4440 HRESULT hr;
4441 UINT i, j;
4443 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4444 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4446 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4447 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4448 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4449 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4450 multiply_matrix(&m, &temp, &m);
4452 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4453 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4454 multiply_matrix(&m, &temp, &m);
4456 /* Left plane */
4457 vec[0].u1.x = m._14 + m._11;
4458 vec[0].u2.y = m._24 + m._21;
4459 vec[0].u3.z = m._34 + m._31;
4460 origin_plane[0] = m._44 + m._41;
4462 /* Right plane */
4463 vec[1].u1.x = m._14 - m._11;
4464 vec[1].u2.y = m._24 - m._21;
4465 vec[1].u3.z = m._34 - m._31;
4466 origin_plane[1] = m._44 - m._41;
4468 /* Top plane */
4469 vec[2].u1.x = m._14 - m._12;
4470 vec[2].u2.y = m._24 - m._22;
4471 vec[2].u3.z = m._34 - m._32;
4472 origin_plane[2] = m._44 - m._42;
4474 /* Bottom plane */
4475 vec[3].u1.x = m._14 + m._12;
4476 vec[3].u2.y = m._24 + m._22;
4477 vec[3].u3.z = m._34 + m._32;
4478 origin_plane[3] = m._44 + m._42;
4480 /* Front plane */
4481 vec[4].u1.x = m._13;
4482 vec[4].u2.y = m._23;
4483 vec[4].u3.z = m._33;
4484 origin_plane[4] = m._43;
4486 /* Back plane*/
4487 vec[5].u1.x = m._14 - m._13;
4488 vec[5].u2.y = m._24 - m._23;
4489 vec[5].u3.z = m._34 - m._33;
4490 origin_plane[5] = m._44 - m._43;
4492 for(i=0; i<NumSpheres; i++)
4494 ReturnValues[i] = 0;
4495 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4498 return D3D_OK;
4501 static HRESULT WINAPI IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4502 D3DVECTOR *Centers, D3DVALUE *Radii, DWORD NumSpheres, DWORD Flags, DWORD *ReturnValues)
4504 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4506 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4507 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4509 return IDirect3DDevice7_ComputeSphereVisibility(&This->IDirect3DDevice7_iface,
4510 Centers, Radii, NumSpheres, Flags, ReturnValues);
4513 /*****************************************************************************
4514 * IDirect3DDevice7::GetTexture
4516 * Returns the texture interface handle assigned to a texture stage.
4517 * The returned texture is AddRefed. This is taken from old ddraw,
4518 * not checked in Windows.
4520 * Version 3 and 7
4522 * Params:
4523 * Stage: Texture stage to read the texture from
4524 * Texture: Address to store the interface pointer at
4526 * Returns:
4527 * D3D_OK on success
4528 * DDERR_INVALIDPARAMS if Texture is NULL
4529 * For details, see IWineD3DDevice::GetTexture
4531 *****************************************************************************/
4532 static HRESULT
4533 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4534 DWORD Stage,
4535 IDirectDrawSurface7 **Texture)
4537 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4538 struct wined3d_texture *wined3d_texture;
4539 HRESULT hr;
4541 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4543 if(!Texture)
4545 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4546 return DDERR_INVALIDPARAMS;
4549 wined3d_mutex_lock();
4550 hr = wined3d_device_get_texture(This->wined3d_device, Stage, &wined3d_texture);
4551 if (FAILED(hr) || !wined3d_texture)
4553 *Texture = NULL;
4554 wined3d_mutex_unlock();
4555 return hr;
4558 *Texture = wined3d_texture_get_parent(wined3d_texture);
4559 IDirectDrawSurface7_AddRef(*Texture);
4560 wined3d_texture_decref(wined3d_texture);
4561 wined3d_mutex_unlock();
4563 return hr;
4566 static HRESULT WINAPI
4567 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4568 DWORD Stage,
4569 IDirectDrawSurface7 **Texture)
4571 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4574 static HRESULT WINAPI
4575 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4576 DWORD Stage,
4577 IDirectDrawSurface7 **Texture)
4579 HRESULT hr;
4580 WORD old_fpucw;
4582 old_fpucw = d3d_fpu_setup();
4583 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4584 set_fpu_control_word(old_fpucw);
4586 return hr;
4589 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface, DWORD Stage,
4590 IDirect3DTexture2 **Texture2)
4592 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4593 HRESULT ret;
4594 IDirectDrawSurface7 *ret_val;
4595 IDirectDrawSurfaceImpl *ret_val_impl;
4597 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4599 ret = IDirect3DDevice7_GetTexture(&This->IDirect3DDevice7_iface, Stage, &ret_val);
4601 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4602 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4604 TRACE("Returning texture %p.\n", *Texture2);
4606 return ret;
4609 /*****************************************************************************
4610 * IDirect3DDevice7::SetTexture
4612 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4614 * Version 3 and 7
4616 * Params:
4617 * Stage: The stage to assign the texture to
4618 * Texture: Interface pointer to the texture surface
4620 * Returns
4621 * D3D_OK on success
4622 * For details, see IWineD3DDevice::SetTexture
4624 *****************************************************************************/
4625 static HRESULT
4626 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4627 DWORD Stage,
4628 IDirectDrawSurface7 *Texture)
4630 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4631 IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
4632 HRESULT hr;
4634 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4636 /* Texture may be NULL here */
4637 wined3d_mutex_lock();
4638 hr = wined3d_device_set_texture(This->wined3d_device,
4639 Stage, surf ? surf->wined3d_texture : NULL);
4640 wined3d_mutex_unlock();
4642 return hr;
4645 static HRESULT WINAPI
4646 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4647 DWORD Stage,
4648 IDirectDrawSurface7 *Texture)
4650 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4653 static HRESULT WINAPI
4654 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4655 DWORD Stage,
4656 IDirectDrawSurface7 *Texture)
4658 HRESULT hr;
4659 WORD old_fpucw;
4661 old_fpucw = d3d_fpu_setup();
4662 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4663 set_fpu_control_word(old_fpucw);
4665 return hr;
4668 static HRESULT WINAPI
4669 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4670 DWORD Stage,
4671 IDirect3DTexture2 *Texture2)
4673 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4674 IDirectDrawSurfaceImpl *tex = unsafe_impl_from_IDirect3DTexture2(Texture2);
4675 DWORD texmapblend;
4676 HRESULT hr;
4678 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4680 wined3d_mutex_lock();
4682 if (This->legacyTextureBlending)
4683 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4685 hr = IDirect3DDevice7_SetTexture(&This->IDirect3DDevice7_iface, Stage, &tex->IDirectDrawSurface7_iface);
4687 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4689 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4690 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4691 struct wined3d_texture *tex = NULL;
4692 BOOL tex_alpha = FALSE;
4693 DDPIXELFORMAT ddfmt;
4694 HRESULT result;
4696 result = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
4697 if (result == WINED3D_OK && tex)
4699 struct wined3d_resource *sub_resource;
4701 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4703 struct wined3d_resource_desc desc;
4705 wined3d_resource_get_desc(sub_resource, &desc);
4706 ddfmt.dwSize = sizeof(ddfmt);
4707 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4708 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4711 wined3d_texture_decref(tex);
4714 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4715 if (tex_alpha)
4716 wined3d_device_set_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4717 else
4718 wined3d_device_set_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4721 wined3d_mutex_unlock();
4723 return hr;
4726 static const struct tss_lookup
4728 BOOL sampler_state;
4729 DWORD state;
4731 tss_lookup[] =
4733 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
4734 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
4735 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
4736 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
4737 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
4738 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
4739 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
4740 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4741 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4742 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4743 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4744 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4745 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
4746 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
4747 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
4748 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
4749 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
4750 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
4751 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
4752 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4753 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4754 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4755 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4756 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4757 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4760 /*****************************************************************************
4761 * IDirect3DDevice7::GetTextureStageState
4763 * Retrieves a state from a texture stage.
4765 * Version 3 and 7
4767 * Params:
4768 * Stage: The stage to retrieve the state from
4769 * TexStageStateType: The state type to retrieve
4770 * State: Address to store the state's value at
4772 * Returns:
4773 * D3D_OK on success
4774 * DDERR_INVALIDPARAMS if State is NULL
4775 * For details, see IWineD3DDevice::GetTextureStageState
4777 *****************************************************************************/
4778 static HRESULT
4779 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4780 DWORD Stage,
4781 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4782 DWORD *State)
4784 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4785 HRESULT hr;
4786 const struct tss_lookup *l;
4788 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4789 iface, Stage, TexStageStateType, State);
4791 if(!State)
4792 return DDERR_INVALIDPARAMS;
4794 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4796 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4797 return DD_OK;
4800 l = &tss_lookup[TexStageStateType];
4802 wined3d_mutex_lock();
4804 if (l->sampler_state)
4806 hr = wined3d_device_get_sampler_state(This->wined3d_device, Stage, l->state, State);
4808 switch(TexStageStateType)
4810 /* Mipfilter is a sampler state with different values */
4811 case D3DTSS_MIPFILTER:
4813 switch(*State)
4815 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4816 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4817 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4818 default:
4819 ERR("Unexpected mipfilter value %#x\n", *State);
4820 *State = D3DTFP_NONE;
4821 break;
4823 break;
4826 /* Magfilter has slightly different values */
4827 case D3DTSS_MAGFILTER:
4829 switch(*State)
4831 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4832 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4833 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4834 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4835 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4836 default:
4837 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4838 *State = D3DTFG_POINT;
4839 break;
4841 break;
4844 default:
4845 break;
4848 else
4850 hr = wined3d_device_get_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4853 wined3d_mutex_unlock();
4855 return hr;
4858 static HRESULT WINAPI
4859 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4860 DWORD Stage,
4861 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4862 DWORD *State)
4864 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4867 static HRESULT WINAPI
4868 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4869 DWORD Stage,
4870 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4871 DWORD *State)
4873 HRESULT hr;
4874 WORD old_fpucw;
4876 old_fpucw = d3d_fpu_setup();
4877 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4878 set_fpu_control_word(old_fpucw);
4880 return hr;
4883 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4884 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD *State)
4886 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4888 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4889 iface, Stage, TexStageStateType, State);
4891 return IDirect3DDevice7_GetTextureStageState(&This->IDirect3DDevice7_iface,
4892 Stage, TexStageStateType, State);
4895 /*****************************************************************************
4896 * IDirect3DDevice7::SetTextureStageState
4898 * Sets a texture stage state. Some stage types need to be handled specially,
4899 * because they do not exist in WineD3D and were moved to another place
4901 * Version 3 and 7
4903 * Params:
4904 * Stage: The stage to modify
4905 * TexStageStateType: The state to change
4906 * State: The new value for the state
4908 * Returns:
4909 * D3D_OK on success
4910 * For details, see IWineD3DDevice::SetTextureStageState
4912 *****************************************************************************/
4913 static HRESULT
4914 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4915 DWORD Stage,
4916 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4917 DWORD State)
4919 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4920 const struct tss_lookup *l;
4921 HRESULT hr;
4923 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4924 iface, Stage, TexStageStateType, State);
4926 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4928 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4929 return DD_OK;
4932 l = &tss_lookup[TexStageStateType];
4934 wined3d_mutex_lock();
4936 if (l->sampler_state)
4938 switch(TexStageStateType)
4940 /* Mipfilter is a sampler state with different values */
4941 case D3DTSS_MIPFILTER:
4943 switch(State)
4945 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
4946 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
4947 case 0: /* Unchecked */
4948 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
4949 default:
4950 ERR("Unexpected mipfilter value %d\n", State);
4951 State = WINED3DTEXF_NONE;
4952 break;
4954 break;
4957 /* Magfilter has slightly different values */
4958 case D3DTSS_MAGFILTER:
4960 switch(State)
4962 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
4963 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
4964 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
4965 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
4966 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
4967 default:
4968 ERR("Unexpected d3d7 mag filter type %d\n", State);
4969 State = WINED3DTEXF_POINT;
4970 break;
4972 break;
4975 case D3DTSS_ADDRESS:
4976 wined3d_device_set_sampler_state(This->wined3d_device, Stage, WINED3DSAMP_ADDRESSV, State);
4977 break;
4979 default:
4980 break;
4983 hr = wined3d_device_set_sampler_state(This->wined3d_device, Stage, l->state, State);
4985 else
4987 hr = wined3d_device_set_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4990 wined3d_mutex_unlock();
4992 return hr;
4995 static HRESULT WINAPI
4996 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4997 DWORD Stage,
4998 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4999 DWORD State)
5001 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5004 static HRESULT WINAPI
5005 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5006 DWORD Stage,
5007 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5008 DWORD State)
5010 HRESULT hr;
5011 WORD old_fpucw;
5013 old_fpucw = d3d_fpu_setup();
5014 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5015 set_fpu_control_word(old_fpucw);
5017 return hr;
5020 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
5021 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD State)
5023 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
5025 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5026 iface, Stage, TexStageStateType, State);
5028 return IDirect3DDevice7_SetTextureStageState(&This->IDirect3DDevice7_iface,
5029 Stage, TexStageStateType, State);
5032 /*****************************************************************************
5033 * IDirect3DDevice7::ValidateDevice
5035 * SDK: "Reports the device's ability to render the currently set
5036 * texture-blending operations in a single pass". Whatever that means
5037 * exactly...
5039 * Version 3 and 7
5041 * Params:
5042 * NumPasses: Address to write the number of necessary passes for the
5043 * desired effect to.
5045 * Returns:
5046 * D3D_OK on success
5047 * See IWineD3DDevice::ValidateDevice for more details
5049 *****************************************************************************/
5050 static HRESULT
5051 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
5052 DWORD *NumPasses)
5054 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5055 HRESULT hr;
5057 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
5059 wined3d_mutex_lock();
5060 hr = wined3d_device_validate_device(This->wined3d_device, NumPasses);
5061 wined3d_mutex_unlock();
5063 return hr;
5066 static HRESULT WINAPI
5067 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
5068 DWORD *NumPasses)
5070 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5073 static HRESULT WINAPI
5074 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
5075 DWORD *NumPasses)
5077 HRESULT hr;
5078 WORD old_fpucw;
5080 old_fpucw = d3d_fpu_setup();
5081 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5082 set_fpu_control_word(old_fpucw);
5084 return hr;
5087 static HRESULT WINAPI IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *Passes)
5089 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
5091 TRACE("iface %p, pass_count %p.\n", iface, Passes);
5093 return IDirect3DDevice7_ValidateDevice(&This->IDirect3DDevice7_iface, Passes);
5096 /*****************************************************************************
5097 * IDirect3DDevice7::Clear
5099 * Fills the render target, the z buffer and the stencil buffer with a
5100 * clear color / value
5102 * Version 7 only
5104 * Params:
5105 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5106 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5107 * Flags: Some flags, as usual
5108 * Color: Clear color for the render target
5109 * Z: Clear value for the Z buffer
5110 * Stencil: Clear value to store in each stencil buffer entry
5112 * Returns:
5113 * D3D_OK on success
5114 * For details, see IWineD3DDevice::Clear
5116 *****************************************************************************/
5117 static HRESULT IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface, DWORD count,
5118 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5120 const struct wined3d_color c =
5122 ((color >> 16) & 0xff) / 255.0f,
5123 ((color >> 8) & 0xff) / 255.0f,
5124 (color & 0xff) / 255.0f,
5125 ((color >> 24) & 0xff) / 255.0f,
5127 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5128 HRESULT hr;
5130 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5131 iface, count, rects, flags, color, z, stencil);
5133 wined3d_mutex_lock();
5134 hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
5135 wined3d_mutex_unlock();
5137 return hr;
5140 static HRESULT WINAPI
5141 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5142 DWORD Count,
5143 D3DRECT *Rects,
5144 DWORD Flags,
5145 D3DCOLOR Color,
5146 D3DVALUE Z,
5147 DWORD Stencil)
5149 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5152 static HRESULT WINAPI
5153 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5154 DWORD Count,
5155 D3DRECT *Rects,
5156 DWORD Flags,
5157 D3DCOLOR Color,
5158 D3DVALUE Z,
5159 DWORD Stencil)
5161 HRESULT hr;
5162 WORD old_fpucw;
5164 old_fpucw = d3d_fpu_setup();
5165 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5166 set_fpu_control_word(old_fpucw);
5168 return hr;
5171 /*****************************************************************************
5172 * IDirect3DDevice7::SetViewport
5174 * Sets the current viewport.
5176 * Version 7 only, but IDirect3DViewport uses this call for older
5177 * versions
5179 * Params:
5180 * Data: The new viewport to set
5182 * Returns:
5183 * D3D_OK on success
5184 * DDERR_INVALIDPARAMS if Data is NULL
5185 * For more details, see IWineDDDevice::SetViewport
5187 *****************************************************************************/
5188 static HRESULT
5189 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5190 D3DVIEWPORT7 *Data)
5192 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5193 HRESULT hr;
5195 TRACE("iface %p, viewport %p.\n", iface, Data);
5197 if(!Data)
5198 return DDERR_INVALIDPARAMS;
5200 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5201 wined3d_mutex_lock();
5202 hr = wined3d_device_set_viewport(This->wined3d_device, (struct wined3d_viewport *)Data);
5203 wined3d_mutex_unlock();
5205 return hr;
5208 static HRESULT WINAPI
5209 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5210 D3DVIEWPORT7 *Data)
5212 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5215 static HRESULT WINAPI
5216 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5217 D3DVIEWPORT7 *Data)
5219 HRESULT hr;
5220 WORD old_fpucw;
5222 old_fpucw = d3d_fpu_setup();
5223 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5224 set_fpu_control_word(old_fpucw);
5226 return hr;
5229 /*****************************************************************************
5230 * IDirect3DDevice::GetViewport
5232 * Returns the current viewport
5234 * Version 7
5236 * Params:
5237 * Data: D3D7Viewport structure to write the viewport information to
5239 * Returns:
5240 * D3D_OK on success
5241 * DDERR_INVALIDPARAMS if Data is NULL
5242 * For more details, see IWineD3DDevice::GetViewport
5244 *****************************************************************************/
5245 static HRESULT
5246 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5247 D3DVIEWPORT7 *Data)
5249 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5250 HRESULT hr;
5252 TRACE("iface %p, viewport %p.\n", iface, Data);
5254 if(!Data)
5255 return DDERR_INVALIDPARAMS;
5257 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5258 wined3d_mutex_lock();
5259 hr = wined3d_device_get_viewport(This->wined3d_device, (struct wined3d_viewport *)Data);
5260 wined3d_mutex_unlock();
5262 return hr_ddraw_from_wined3d(hr);
5265 static HRESULT WINAPI
5266 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5267 D3DVIEWPORT7 *Data)
5269 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5272 static HRESULT WINAPI
5273 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5274 D3DVIEWPORT7 *Data)
5276 HRESULT hr;
5277 WORD old_fpucw;
5279 old_fpucw = d3d_fpu_setup();
5280 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5281 set_fpu_control_word(old_fpucw);
5283 return hr;
5286 /*****************************************************************************
5287 * IDirect3DDevice7::SetMaterial
5289 * Sets the Material
5291 * Version 7
5293 * Params:
5294 * Mat: The material to set
5296 * Returns:
5297 * D3D_OK on success
5298 * DDERR_INVALIDPARAMS if Mat is NULL.
5299 * For more details, see IWineD3DDevice::SetMaterial
5301 *****************************************************************************/
5302 static HRESULT
5303 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5304 D3DMATERIAL7 *Mat)
5306 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5307 HRESULT hr;
5309 TRACE("iface %p, material %p.\n", iface, Mat);
5311 if (!Mat) return DDERR_INVALIDPARAMS;
5313 wined3d_mutex_lock();
5314 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5315 hr = wined3d_device_set_material(This->wined3d_device, (struct wined3d_material *)Mat);
5316 wined3d_mutex_unlock();
5318 return hr_ddraw_from_wined3d(hr);
5321 static HRESULT WINAPI
5322 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5323 D3DMATERIAL7 *Mat)
5325 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5328 static HRESULT WINAPI
5329 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5330 D3DMATERIAL7 *Mat)
5332 HRESULT hr;
5333 WORD old_fpucw;
5335 old_fpucw = d3d_fpu_setup();
5336 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5337 set_fpu_control_word(old_fpucw);
5339 return hr;
5342 /*****************************************************************************
5343 * IDirect3DDevice7::GetMaterial
5345 * Returns the current material
5347 * Version 7
5349 * Params:
5350 * Mat: D3DMATERIAL7 structure to write the material parameters to
5352 * Returns:
5353 * D3D_OK on success
5354 * DDERR_INVALIDPARAMS if Mat is NULL
5355 * For more details, see IWineD3DDevice::GetMaterial
5357 *****************************************************************************/
5358 static HRESULT
5359 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5360 D3DMATERIAL7 *Mat)
5362 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5363 HRESULT hr;
5365 TRACE("iface %p, material %p.\n", iface, Mat);
5367 wined3d_mutex_lock();
5368 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5369 hr = wined3d_device_get_material(This->wined3d_device, (struct wined3d_material *)Mat);
5370 wined3d_mutex_unlock();
5372 return hr_ddraw_from_wined3d(hr);
5375 static HRESULT WINAPI
5376 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5377 D3DMATERIAL7 *Mat)
5379 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5382 static HRESULT WINAPI
5383 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5384 D3DMATERIAL7 *Mat)
5386 HRESULT hr;
5387 WORD old_fpucw;
5389 old_fpucw = d3d_fpu_setup();
5390 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5391 set_fpu_control_word(old_fpucw);
5393 return hr;
5396 /*****************************************************************************
5397 * IDirect3DDevice7::SetLight
5399 * Assigns a light to a light index, but doesn't activate it yet.
5401 * Version 7, IDirect3DLight uses this method for older versions
5403 * Params:
5404 * LightIndex: The index of the new light
5405 * Light: A D3DLIGHT7 structure describing the light
5407 * Returns:
5408 * D3D_OK on success
5409 * For more details, see IWineD3DDevice::SetLight
5411 *****************************************************************************/
5412 static HRESULT
5413 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5414 DWORD LightIndex,
5415 D3DLIGHT7 *Light)
5417 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5418 HRESULT hr;
5420 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5422 wined3d_mutex_lock();
5423 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5424 hr = wined3d_device_set_light(This->wined3d_device, LightIndex, (struct wined3d_light *)Light);
5425 wined3d_mutex_unlock();
5427 return hr_ddraw_from_wined3d(hr);
5430 static HRESULT WINAPI
5431 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5432 DWORD LightIndex,
5433 D3DLIGHT7 *Light)
5435 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5438 static HRESULT WINAPI
5439 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5440 DWORD LightIndex,
5441 D3DLIGHT7 *Light)
5443 HRESULT hr;
5444 WORD old_fpucw;
5446 old_fpucw = d3d_fpu_setup();
5447 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5448 set_fpu_control_word(old_fpucw);
5450 return hr;
5453 /*****************************************************************************
5454 * IDirect3DDevice7::GetLight
5456 * Returns the light assigned to a light index
5458 * Params:
5459 * Light: Structure to write the light information to
5461 * Returns:
5462 * D3D_OK on success
5463 * DDERR_INVALIDPARAMS if Light is NULL
5464 * For details, see IWineD3DDevice::GetLight
5466 *****************************************************************************/
5467 static HRESULT
5468 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5469 DWORD LightIndex,
5470 D3DLIGHT7 *Light)
5472 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5473 HRESULT rc;
5475 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5477 wined3d_mutex_lock();
5478 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5479 rc = wined3d_device_get_light(This->wined3d_device, LightIndex, (struct wined3d_light *)Light);
5480 wined3d_mutex_unlock();
5482 /* Translate the result. WineD3D returns other values than D3D7 */
5483 return hr_ddraw_from_wined3d(rc);
5486 static HRESULT WINAPI
5487 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5488 DWORD LightIndex,
5489 D3DLIGHT7 *Light)
5491 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5494 static HRESULT WINAPI
5495 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5496 DWORD LightIndex,
5497 D3DLIGHT7 *Light)
5499 HRESULT hr;
5500 WORD old_fpucw;
5502 old_fpucw = d3d_fpu_setup();
5503 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5504 set_fpu_control_word(old_fpucw);
5506 return hr;
5509 /*****************************************************************************
5510 * IDirect3DDevice7::BeginStateBlock
5512 * Begins recording to a stateblock
5514 * Version 7
5516 * Returns:
5517 * D3D_OK on success
5518 * For details see IWineD3DDevice::BeginStateBlock
5520 *****************************************************************************/
5521 static HRESULT
5522 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5524 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5525 HRESULT hr;
5527 TRACE("iface %p.\n", iface);
5529 wined3d_mutex_lock();
5530 hr = wined3d_device_begin_stateblock(This->wined3d_device);
5531 wined3d_mutex_unlock();
5533 return hr_ddraw_from_wined3d(hr);
5536 static HRESULT WINAPI
5537 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5539 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5542 static HRESULT WINAPI
5543 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5545 HRESULT hr;
5546 WORD old_fpucw;
5548 old_fpucw = d3d_fpu_setup();
5549 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5550 set_fpu_control_word(old_fpucw);
5552 return hr;
5555 /*****************************************************************************
5556 * IDirect3DDevice7::EndStateBlock
5558 * Stops recording to a state block and returns the created stateblock
5559 * handle.
5561 * Version 7
5563 * Params:
5564 * BlockHandle: Address to store the stateblock's handle to
5566 * Returns:
5567 * D3D_OK on success
5568 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5569 * See IWineD3DDevice::EndStateBlock for more details
5571 *****************************************************************************/
5572 static HRESULT
5573 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5574 DWORD *BlockHandle)
5576 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5577 struct wined3d_stateblock *wined3d_sb;
5578 HRESULT hr;
5579 DWORD h;
5581 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5583 if(!BlockHandle)
5585 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5586 return DDERR_INVALIDPARAMS;
5589 wined3d_mutex_lock();
5591 hr = wined3d_device_end_stateblock(This->wined3d_device, &wined3d_sb);
5592 if (FAILED(hr))
5594 WARN("Failed to end stateblock, hr %#x.\n", hr);
5595 wined3d_mutex_unlock();
5596 *BlockHandle = 0;
5597 return hr_ddraw_from_wined3d(hr);
5600 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5601 if (h == DDRAW_INVALID_HANDLE)
5603 ERR("Failed to allocate a stateblock handle.\n");
5604 wined3d_stateblock_decref(wined3d_sb);
5605 wined3d_mutex_unlock();
5606 *BlockHandle = 0;
5607 return DDERR_OUTOFMEMORY;
5610 wined3d_mutex_unlock();
5611 *BlockHandle = h + 1;
5613 return hr_ddraw_from_wined3d(hr);
5616 static HRESULT WINAPI
5617 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5618 DWORD *BlockHandle)
5620 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5623 static HRESULT WINAPI
5624 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5625 DWORD *BlockHandle)
5627 HRESULT hr;
5628 WORD old_fpucw;
5630 old_fpucw = d3d_fpu_setup();
5631 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5632 set_fpu_control_word(old_fpucw);
5634 return hr;
5637 /*****************************************************************************
5638 * IDirect3DDevice7::PreLoad
5640 * Allows the app to signal that a texture will be used soon, to allow
5641 * the Direct3DDevice to load it to the video card in the meantime.
5643 * Version 7
5645 * Params:
5646 * Texture: The texture to preload
5648 * Returns:
5649 * D3D_OK on success
5650 * DDERR_INVALIDPARAMS if Texture is NULL
5651 * See IWineD3DSurface::PreLoad for details
5653 *****************************************************************************/
5654 static HRESULT
5655 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5656 IDirectDrawSurface7 *Texture)
5658 IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
5660 TRACE("iface %p, texture %p.\n", iface, Texture);
5662 if(!Texture)
5663 return DDERR_INVALIDPARAMS;
5665 wined3d_mutex_lock();
5666 wined3d_surface_preload(surf->wined3d_surface);
5667 wined3d_mutex_unlock();
5669 return D3D_OK;
5672 static HRESULT WINAPI
5673 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5674 IDirectDrawSurface7 *Texture)
5676 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5679 static HRESULT WINAPI
5680 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5681 IDirectDrawSurface7 *Texture)
5683 HRESULT hr;
5684 WORD old_fpucw;
5686 old_fpucw = d3d_fpu_setup();
5687 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5688 set_fpu_control_word(old_fpucw);
5690 return hr;
5693 /*****************************************************************************
5694 * IDirect3DDevice7::ApplyStateBlock
5696 * Activates the state stored in a state block handle.
5698 * Params:
5699 * BlockHandle: The stateblock handle to activate
5701 * Returns:
5702 * D3D_OK on success
5703 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5705 *****************************************************************************/
5706 static HRESULT
5707 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5708 DWORD BlockHandle)
5710 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5711 struct wined3d_stateblock *wined3d_sb;
5712 HRESULT hr;
5714 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5716 wined3d_mutex_lock();
5717 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5718 if (!wined3d_sb)
5720 WARN("Invalid stateblock handle.\n");
5721 wined3d_mutex_unlock();
5722 return D3DERR_INVALIDSTATEBLOCK;
5725 hr = wined3d_stateblock_apply(wined3d_sb);
5726 wined3d_mutex_unlock();
5728 return hr_ddraw_from_wined3d(hr);
5731 static HRESULT WINAPI
5732 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5733 DWORD BlockHandle)
5735 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5738 static HRESULT WINAPI
5739 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5740 DWORD BlockHandle)
5742 HRESULT hr;
5743 WORD old_fpucw;
5745 old_fpucw = d3d_fpu_setup();
5746 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5747 set_fpu_control_word(old_fpucw);
5749 return hr;
5752 /*****************************************************************************
5753 * IDirect3DDevice7::CaptureStateBlock
5755 * Updates a stateblock's values to the values currently set for the device
5757 * Version 7
5759 * Params:
5760 * BlockHandle: Stateblock to update
5762 * Returns:
5763 * D3D_OK on success
5764 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5765 * See IWineD3DDevice::CaptureStateBlock for more details
5767 *****************************************************************************/
5768 static HRESULT
5769 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5770 DWORD BlockHandle)
5772 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5773 struct wined3d_stateblock *wined3d_sb;
5774 HRESULT hr;
5776 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5778 wined3d_mutex_lock();
5779 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5780 if (!wined3d_sb)
5782 WARN("Invalid stateblock handle.\n");
5783 wined3d_mutex_unlock();
5784 return D3DERR_INVALIDSTATEBLOCK;
5787 hr = wined3d_stateblock_capture(wined3d_sb);
5788 wined3d_mutex_unlock();
5790 return hr_ddraw_from_wined3d(hr);
5793 static HRESULT WINAPI
5794 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5795 DWORD BlockHandle)
5797 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5800 static HRESULT WINAPI
5801 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5802 DWORD BlockHandle)
5804 HRESULT hr;
5805 WORD old_fpucw;
5807 old_fpucw = d3d_fpu_setup();
5808 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5809 set_fpu_control_word(old_fpucw);
5811 return hr;
5814 /*****************************************************************************
5815 * IDirect3DDevice7::DeleteStateBlock
5817 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5819 * Version 7
5821 * Params:
5822 * BlockHandle: Stateblock handle to delete
5824 * Returns:
5825 * D3D_OK on success
5826 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5828 *****************************************************************************/
5829 static HRESULT
5830 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5831 DWORD BlockHandle)
5833 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5834 struct wined3d_stateblock *wined3d_sb;
5835 ULONG ref;
5837 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5839 wined3d_mutex_lock();
5841 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5842 if (!wined3d_sb)
5844 WARN("Invalid stateblock handle.\n");
5845 wined3d_mutex_unlock();
5846 return D3DERR_INVALIDSTATEBLOCK;
5849 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5851 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5854 wined3d_mutex_unlock();
5856 return D3D_OK;
5859 static HRESULT WINAPI
5860 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5861 DWORD BlockHandle)
5863 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5866 static HRESULT WINAPI
5867 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5868 DWORD BlockHandle)
5870 HRESULT hr;
5871 WORD old_fpucw;
5873 old_fpucw = d3d_fpu_setup();
5874 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5875 set_fpu_control_word(old_fpucw);
5877 return hr;
5880 /*****************************************************************************
5881 * IDirect3DDevice7::CreateStateBlock
5883 * Creates a new state block handle.
5885 * Version 7
5887 * Params:
5888 * Type: The state block type
5889 * BlockHandle: Address to write the created handle to
5891 * Returns:
5892 * D3D_OK on success
5893 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5895 *****************************************************************************/
5896 static HRESULT
5897 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5898 D3DSTATEBLOCKTYPE Type,
5899 DWORD *BlockHandle)
5901 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5902 struct wined3d_stateblock *wined3d_sb;
5903 HRESULT hr;
5904 DWORD h;
5906 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5908 if(!BlockHandle)
5910 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5911 return DDERR_INVALIDPARAMS;
5913 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5914 Type != D3DSBT_VERTEXSTATE ) {
5915 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5916 return DDERR_INVALIDPARAMS;
5919 wined3d_mutex_lock();
5921 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5922 hr = wined3d_stateblock_create(This->wined3d_device, Type, &wined3d_sb);
5923 if (FAILED(hr))
5925 WARN("Failed to create stateblock, hr %#x.\n", hr);
5926 wined3d_mutex_unlock();
5927 return hr_ddraw_from_wined3d(hr);
5930 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5931 if (h == DDRAW_INVALID_HANDLE)
5933 ERR("Failed to allocate stateblock handle.\n");
5934 wined3d_stateblock_decref(wined3d_sb);
5935 wined3d_mutex_unlock();
5936 return DDERR_OUTOFMEMORY;
5939 *BlockHandle = h + 1;
5940 wined3d_mutex_unlock();
5942 return hr_ddraw_from_wined3d(hr);
5945 static HRESULT WINAPI
5946 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5947 D3DSTATEBLOCKTYPE Type,
5948 DWORD *BlockHandle)
5950 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5953 static HRESULT WINAPI
5954 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5955 D3DSTATEBLOCKTYPE Type,
5956 DWORD *BlockHandle)
5958 HRESULT hr;
5959 WORD old_fpucw;
5961 old_fpucw = d3d_fpu_setup();
5962 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5963 set_fpu_control_word(old_fpucw);
5965 return hr;
5968 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5969 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
5970 IDirectDrawSurfaceImpl *src)
5972 IDirectDrawSurfaceImpl *src_level, *dest_level;
5973 IDirectDrawSurface7 *temp;
5974 DDSURFACEDESC2 ddsd;
5975 BOOL levelFound; /* at least one suitable sublevel in dest found */
5977 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5978 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5979 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5981 levelFound = FALSE;
5983 src_level = src;
5984 dest_level = dest;
5986 for (;src_level && dest_level;)
5988 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5989 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5991 levelFound = TRUE;
5993 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5994 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5995 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5997 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5999 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6002 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6003 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6004 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6006 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6008 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6011 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6012 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6014 return !dest_level && levelFound;
6017 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6018 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
6019 IDirectDrawSurfaceImpl *dest,
6020 IDirectDrawSurfaceImpl *src,
6021 const POINT *DestPoint,
6022 const RECT *SrcRect)
6024 IDirectDrawSurfaceImpl *src_level, *dest_level;
6025 IDirectDrawSurface7 *temp;
6026 DDSURFACEDESC2 ddsd;
6027 POINT point;
6028 RECT src_rect;
6029 HRESULT hr;
6030 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
6031 DWORD ckeyflag;
6032 DDCOLORKEY ddckey;
6034 /* Copy palette, if possible. */
6035 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
6036 IDirectDrawSurface7_GetPalette(&dest->IDirectDrawSurface7_iface, &pal);
6038 if (pal_src != NULL && pal != NULL)
6040 PALETTEENTRY palent[256];
6042 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
6043 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
6046 if (pal) IDirectDrawPalette_Release(pal);
6047 if (pal_src) IDirectDrawPalette_Release(pal_src);
6049 /* Copy colorkeys, if present. */
6050 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6052 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6054 if (SUCCEEDED(hr))
6056 IDirectDrawSurface7_SetColorKey(&dest->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6060 src_level = src;
6061 dest_level = dest;
6063 point = *DestPoint;
6064 src_rect = *SrcRect;
6066 for (;src_level && dest_level;)
6068 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6069 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6071 UINT src_w = src_rect.right - src_rect.left;
6072 UINT src_h = src_rect.bottom - src_rect.top;
6073 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
6075 if (FAILED(hr = wined3d_surface_blt(dest_level->wined3d_surface, &dst_rect,
6076 src_level->wined3d_surface, &src_rect, 0, NULL, WINED3DTEXF_POINT)))
6077 ERR("Blit failed, hr %#x.\n", hr);
6079 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6080 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6081 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6083 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6085 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6088 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6089 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6090 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6092 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6094 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6096 point.x /= 2;
6097 point.y /= 2;
6099 src_rect.top /= 2;
6100 src_rect.left /= 2;
6101 src_rect.right = (src_rect.right + 1) / 2;
6102 src_rect.bottom = (src_rect.bottom + 1) / 2;
6105 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6106 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6109 /*****************************************************************************
6110 * IDirect3DDevice7::Load
6112 * Loads a rectangular area from the source into the destination texture.
6113 * It can also copy the source to the faces of a cubic environment map
6115 * Version 7
6117 * Params:
6118 * DestTex: Destination texture
6119 * DestPoint: Point in the destination where the source image should be
6120 * written to
6121 * SrcTex: Source texture
6122 * SrcRect: Source rectangle
6123 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6124 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6125 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6127 * Returns:
6128 * D3D_OK on success
6129 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6132 *****************************************************************************/
6134 static HRESULT
6135 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6136 IDirectDrawSurface7 *DestTex,
6137 POINT *DestPoint,
6138 IDirectDrawSurface7 *SrcTex,
6139 RECT *SrcRect,
6140 DWORD Flags)
6142 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6143 IDirectDrawSurfaceImpl *dest = unsafe_impl_from_IDirectDrawSurface7(DestTex);
6144 IDirectDrawSurfaceImpl *src = unsafe_impl_from_IDirectDrawSurface7(SrcTex);
6145 POINT destpoint;
6146 RECT srcrect;
6148 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6149 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6151 if( (!src) || (!dest) )
6152 return DDERR_INVALIDPARAMS;
6154 wined3d_mutex_lock();
6156 if (SrcRect) srcrect = *SrcRect;
6157 else
6159 srcrect.left = srcrect.top = 0;
6160 srcrect.right = src->surface_desc.dwWidth;
6161 srcrect.bottom = src->surface_desc.dwHeight;
6164 if (DestPoint) destpoint = *DestPoint;
6165 else
6167 destpoint.x = destpoint.y = 0;
6169 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6170 * destination can be a subset of mip levels, in which case actual coordinates used
6171 * for it may be divided. If any dimension of dest is larger than source, it can't be
6172 * mip level subset, so an error can be returned early.
6174 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6175 srcrect.right > src->surface_desc.dwWidth ||
6176 srcrect.bottom > src->surface_desc.dwHeight ||
6177 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6178 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6179 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6180 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6182 wined3d_mutex_unlock();
6183 return DDERR_INVALIDPARAMS;
6186 /* Must be top level surfaces. */
6187 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6188 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6190 wined3d_mutex_unlock();
6191 return DDERR_INVALIDPARAMS;
6194 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6196 DWORD src_face_flag, dest_face_flag;
6197 IDirectDrawSurfaceImpl *src_face, *dest_face;
6198 IDirectDrawSurface7 *temp;
6199 DDSURFACEDESC2 ddsd;
6200 int i;
6202 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6204 wined3d_mutex_unlock();
6205 return DDERR_INVALIDPARAMS;
6208 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6209 * time it's actual surface loading. */
6210 for (i = 0; i < 2; i++)
6212 dest_face = dest;
6213 src_face = src;
6215 for (;dest_face && src_face;)
6217 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6218 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6220 if (src_face_flag == dest_face_flag)
6222 if (i == 0)
6224 /* Destination mip levels must be subset of source mip levels. */
6225 if (!is_mip_level_subset(dest_face, src_face))
6227 wined3d_mutex_unlock();
6228 return DDERR_INVALIDPARAMS;
6231 else if (Flags & dest_face_flag)
6233 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6236 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6238 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6239 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6240 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6242 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6244 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6246 else
6248 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6250 src_face = NULL;
6254 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6256 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6257 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6258 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6260 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6262 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6264 else
6266 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6268 dest_face = NULL;
6272 if (i == 0)
6274 /* Native returns error if src faces are not subset of dest faces. */
6275 if (src_face)
6277 wined3d_mutex_unlock();
6278 return DDERR_INVALIDPARAMS;
6283 wined3d_mutex_unlock();
6284 return D3D_OK;
6286 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6288 wined3d_mutex_unlock();
6289 return DDERR_INVALIDPARAMS;
6292 /* Handle non cube map textures. */
6294 /* Destination mip levels must be subset of source mip levels. */
6295 if (!is_mip_level_subset(dest, src))
6297 wined3d_mutex_unlock();
6298 return DDERR_INVALIDPARAMS;
6301 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6303 wined3d_mutex_unlock();
6305 return D3D_OK;
6308 static HRESULT WINAPI
6309 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6310 IDirectDrawSurface7 *DestTex,
6311 POINT *DestPoint,
6312 IDirectDrawSurface7 *SrcTex,
6313 RECT *SrcRect,
6314 DWORD Flags)
6316 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6319 static HRESULT WINAPI
6320 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6321 IDirectDrawSurface7 *DestTex,
6322 POINT *DestPoint,
6323 IDirectDrawSurface7 *SrcTex,
6324 RECT *SrcRect,
6325 DWORD Flags)
6327 HRESULT hr;
6328 WORD old_fpucw;
6330 old_fpucw = d3d_fpu_setup();
6331 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6332 set_fpu_control_word(old_fpucw);
6334 return hr;
6337 /*****************************************************************************
6338 * IDirect3DDevice7::LightEnable
6340 * Enables or disables a light
6342 * Version 7, IDirect3DLight uses this method too.
6344 * Params:
6345 * LightIndex: The index of the light to enable / disable
6346 * Enable: Enable or disable the light
6348 * Returns:
6349 * D3D_OK on success
6350 * For more details, see IWineD3DDevice::SetLightEnable
6352 *****************************************************************************/
6353 static HRESULT
6354 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6355 DWORD LightIndex,
6356 BOOL Enable)
6358 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6359 HRESULT hr;
6361 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6363 wined3d_mutex_lock();
6364 hr = wined3d_device_set_light_enable(This->wined3d_device, LightIndex, Enable);
6365 wined3d_mutex_unlock();
6367 return hr_ddraw_from_wined3d(hr);
6370 static HRESULT WINAPI
6371 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6372 DWORD LightIndex,
6373 BOOL Enable)
6375 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6378 static HRESULT WINAPI
6379 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6380 DWORD LightIndex,
6381 BOOL Enable)
6383 HRESULT hr;
6384 WORD old_fpucw;
6386 old_fpucw = d3d_fpu_setup();
6387 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6388 set_fpu_control_word(old_fpucw);
6390 return hr;
6393 /*****************************************************************************
6394 * IDirect3DDevice7::GetLightEnable
6396 * Retrieves if the light with the given index is enabled or not
6398 * Version 7
6400 * Params:
6401 * LightIndex: Index of desired light
6402 * Enable: Pointer to a BOOL which contains the result
6404 * Returns:
6405 * D3D_OK on success
6406 * DDERR_INVALIDPARAMS if Enable is NULL
6407 * See IWineD3DDevice::GetLightEnable for more details
6409 *****************************************************************************/
6410 static HRESULT
6411 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6412 DWORD LightIndex,
6413 BOOL* Enable)
6415 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6416 HRESULT hr;
6418 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6420 if(!Enable)
6421 return DDERR_INVALIDPARAMS;
6423 wined3d_mutex_lock();
6424 hr = wined3d_device_get_light_enable(This->wined3d_device, LightIndex, Enable);
6425 wined3d_mutex_unlock();
6427 return hr_ddraw_from_wined3d(hr);
6430 static HRESULT WINAPI
6431 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6432 DWORD LightIndex,
6433 BOOL* Enable)
6435 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6438 static HRESULT WINAPI
6439 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6440 DWORD LightIndex,
6441 BOOL* Enable)
6443 HRESULT hr;
6444 WORD old_fpucw;
6446 old_fpucw = d3d_fpu_setup();
6447 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6448 set_fpu_control_word(old_fpucw);
6450 return hr;
6453 /*****************************************************************************
6454 * IDirect3DDevice7::SetClipPlane
6456 * Sets custom clipping plane
6458 * Version 7
6460 * Params:
6461 * Index: The index of the clipping plane
6462 * PlaneEquation: An equation defining the clipping plane
6464 * Returns:
6465 * D3D_OK on success
6466 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6467 * See IWineD3DDevice::SetClipPlane for more details
6469 *****************************************************************************/
6470 static HRESULT
6471 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6472 DWORD Index,
6473 D3DVALUE* PlaneEquation)
6475 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6476 HRESULT hr;
6478 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6480 if(!PlaneEquation)
6481 return DDERR_INVALIDPARAMS;
6483 wined3d_mutex_lock();
6484 hr = wined3d_device_set_clip_plane(This->wined3d_device, Index, PlaneEquation);
6485 wined3d_mutex_unlock();
6487 return hr;
6490 static HRESULT WINAPI
6491 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6492 DWORD Index,
6493 D3DVALUE* PlaneEquation)
6495 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6498 static HRESULT WINAPI
6499 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6500 DWORD Index,
6501 D3DVALUE* PlaneEquation)
6503 HRESULT hr;
6504 WORD old_fpucw;
6506 old_fpucw = d3d_fpu_setup();
6507 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6508 set_fpu_control_word(old_fpucw);
6510 return hr;
6513 /*****************************************************************************
6514 * IDirect3DDevice7::GetClipPlane
6516 * Returns the clipping plane with a specific index
6518 * Params:
6519 * Index: The index of the desired plane
6520 * PlaneEquation: Address to store the plane equation to
6522 * Returns:
6523 * D3D_OK on success
6524 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6525 * See IWineD3DDevice::GetClipPlane for more details
6527 *****************************************************************************/
6528 static HRESULT
6529 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6530 DWORD Index,
6531 D3DVALUE* PlaneEquation)
6533 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6534 HRESULT hr;
6536 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6538 if(!PlaneEquation)
6539 return DDERR_INVALIDPARAMS;
6541 wined3d_mutex_lock();
6542 hr = wined3d_device_get_clip_plane(This->wined3d_device, Index, PlaneEquation);
6543 wined3d_mutex_unlock();
6545 return hr;
6548 static HRESULT WINAPI
6549 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6550 DWORD Index,
6551 D3DVALUE* PlaneEquation)
6553 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6556 static HRESULT WINAPI
6557 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6558 DWORD Index,
6559 D3DVALUE* PlaneEquation)
6561 HRESULT hr;
6562 WORD old_fpucw;
6564 old_fpucw = d3d_fpu_setup();
6565 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6566 set_fpu_control_word(old_fpucw);
6568 return hr;
6571 /*****************************************************************************
6572 * IDirect3DDevice7::GetInfo
6574 * Retrieves some information about the device. The DirectX sdk says that
6575 * this version returns S_FALSE for all retail builds of DirectX, that's what
6576 * this implementation does.
6578 * Params:
6579 * DevInfoID: Information type requested
6580 * DevInfoStruct: Pointer to a structure to store the info to
6581 * Size: Size of the structure
6583 * Returns:
6584 * S_FALSE, because it's a non-debug driver
6586 *****************************************************************************/
6587 static HRESULT WINAPI
6588 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6589 DWORD DevInfoID,
6590 void *DevInfoStruct,
6591 DWORD Size)
6593 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6594 iface, DevInfoID, DevInfoStruct, Size);
6596 if (TRACE_ON(ddraw))
6598 TRACE(" info requested : ");
6599 switch (DevInfoID)
6601 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6602 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6603 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6604 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6608 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6611 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6612 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6613 * are not duplicated.
6615 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6616 * has already been setup for optimal d3d operation.
6618 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6619 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6620 * by Sacrifice (game). */
6621 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6623 /*** IUnknown Methods ***/
6624 IDirect3DDeviceImpl_7_QueryInterface,
6625 IDirect3DDeviceImpl_7_AddRef,
6626 IDirect3DDeviceImpl_7_Release,
6627 /*** IDirect3DDevice7 ***/
6628 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6629 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6630 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6631 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6632 IDirect3DDeviceImpl_7_GetDirect3D,
6633 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6634 IDirect3DDeviceImpl_7_GetRenderTarget,
6635 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6636 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6637 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6638 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6639 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6640 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6641 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6642 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6643 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6644 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6645 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6646 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6647 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6648 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6649 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6650 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6651 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6652 IDirect3DDeviceImpl_7_SetClipStatus,
6653 IDirect3DDeviceImpl_7_GetClipStatus,
6654 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6655 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6656 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6657 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6658 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6659 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6660 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6661 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6662 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6663 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6664 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6665 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6666 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6667 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6668 IDirect3DDeviceImpl_7_Load_FPUSetup,
6669 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6670 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6671 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6672 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6673 IDirect3DDeviceImpl_7_GetInfo
6676 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6678 /*** IUnknown Methods ***/
6679 IDirect3DDeviceImpl_7_QueryInterface,
6680 IDirect3DDeviceImpl_7_AddRef,
6681 IDirect3DDeviceImpl_7_Release,
6682 /*** IDirect3DDevice7 ***/
6683 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6684 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6685 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6686 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6687 IDirect3DDeviceImpl_7_GetDirect3D,
6688 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6689 IDirect3DDeviceImpl_7_GetRenderTarget,
6690 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6691 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6692 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6693 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6694 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6695 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6696 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6697 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6698 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6699 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6700 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6701 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6702 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6703 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6704 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6705 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6706 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6707 IDirect3DDeviceImpl_7_SetClipStatus,
6708 IDirect3DDeviceImpl_7_GetClipStatus,
6709 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6710 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6711 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6712 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6713 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6714 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6715 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6716 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6717 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6718 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6719 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6720 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6721 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6722 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6723 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6724 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6725 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6726 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6727 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6728 IDirect3DDeviceImpl_7_GetInfo
6731 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6733 /*** IUnknown Methods ***/
6734 IDirect3DDeviceImpl_3_QueryInterface,
6735 IDirect3DDeviceImpl_3_AddRef,
6736 IDirect3DDeviceImpl_3_Release,
6737 /*** IDirect3DDevice3 ***/
6738 IDirect3DDeviceImpl_3_GetCaps,
6739 IDirect3DDeviceImpl_3_GetStats,
6740 IDirect3DDeviceImpl_3_AddViewport,
6741 IDirect3DDeviceImpl_3_DeleteViewport,
6742 IDirect3DDeviceImpl_3_NextViewport,
6743 IDirect3DDeviceImpl_3_EnumTextureFormats,
6744 IDirect3DDeviceImpl_3_BeginScene,
6745 IDirect3DDeviceImpl_3_EndScene,
6746 IDirect3DDeviceImpl_3_GetDirect3D,
6747 IDirect3DDeviceImpl_3_SetCurrentViewport,
6748 IDirect3DDeviceImpl_3_GetCurrentViewport,
6749 IDirect3DDeviceImpl_3_SetRenderTarget,
6750 IDirect3DDeviceImpl_3_GetRenderTarget,
6751 IDirect3DDeviceImpl_3_Begin,
6752 IDirect3DDeviceImpl_3_BeginIndexed,
6753 IDirect3DDeviceImpl_3_Vertex,
6754 IDirect3DDeviceImpl_3_Index,
6755 IDirect3DDeviceImpl_3_End,
6756 IDirect3DDeviceImpl_3_GetRenderState,
6757 IDirect3DDeviceImpl_3_SetRenderState,
6758 IDirect3DDeviceImpl_3_GetLightState,
6759 IDirect3DDeviceImpl_3_SetLightState,
6760 IDirect3DDeviceImpl_3_SetTransform,
6761 IDirect3DDeviceImpl_3_GetTransform,
6762 IDirect3DDeviceImpl_3_MultiplyTransform,
6763 IDirect3DDeviceImpl_3_DrawPrimitive,
6764 IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6765 IDirect3DDeviceImpl_3_SetClipStatus,
6766 IDirect3DDeviceImpl_3_GetClipStatus,
6767 IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6768 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6769 IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6770 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6771 IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6772 IDirect3DDeviceImpl_3_GetTexture,
6773 IDirect3DDeviceImpl_3_SetTexture,
6774 IDirect3DDeviceImpl_3_GetTextureStageState,
6775 IDirect3DDeviceImpl_3_SetTextureStageState,
6776 IDirect3DDeviceImpl_3_ValidateDevice
6779 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6781 /*** IUnknown Methods ***/
6782 IDirect3DDeviceImpl_2_QueryInterface,
6783 IDirect3DDeviceImpl_2_AddRef,
6784 IDirect3DDeviceImpl_2_Release,
6785 /*** IDirect3DDevice2 ***/
6786 IDirect3DDeviceImpl_2_GetCaps,
6787 IDirect3DDeviceImpl_2_SwapTextureHandles,
6788 IDirect3DDeviceImpl_2_GetStats,
6789 IDirect3DDeviceImpl_2_AddViewport,
6790 IDirect3DDeviceImpl_2_DeleteViewport,
6791 IDirect3DDeviceImpl_2_NextViewport,
6792 IDirect3DDeviceImpl_2_EnumTextureFormats,
6793 IDirect3DDeviceImpl_2_BeginScene,
6794 IDirect3DDeviceImpl_2_EndScene,
6795 IDirect3DDeviceImpl_2_GetDirect3D,
6796 IDirect3DDeviceImpl_2_SetCurrentViewport,
6797 IDirect3DDeviceImpl_2_GetCurrentViewport,
6798 IDirect3DDeviceImpl_2_SetRenderTarget,
6799 IDirect3DDeviceImpl_2_GetRenderTarget,
6800 IDirect3DDeviceImpl_2_Begin,
6801 IDirect3DDeviceImpl_2_BeginIndexed,
6802 IDirect3DDeviceImpl_2_Vertex,
6803 IDirect3DDeviceImpl_2_Index,
6804 IDirect3DDeviceImpl_2_End,
6805 IDirect3DDeviceImpl_2_GetRenderState,
6806 IDirect3DDeviceImpl_2_SetRenderState,
6807 IDirect3DDeviceImpl_2_GetLightState,
6808 IDirect3DDeviceImpl_2_SetLightState,
6809 IDirect3DDeviceImpl_2_SetTransform,
6810 IDirect3DDeviceImpl_2_GetTransform,
6811 IDirect3DDeviceImpl_2_MultiplyTransform,
6812 IDirect3DDeviceImpl_2_DrawPrimitive,
6813 IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6814 IDirect3DDeviceImpl_2_SetClipStatus,
6815 IDirect3DDeviceImpl_2_GetClipStatus
6818 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6820 /*** IUnknown Methods ***/
6821 IDirect3DDeviceImpl_1_QueryInterface,
6822 IDirect3DDeviceImpl_1_AddRef,
6823 IDirect3DDeviceImpl_1_Release,
6824 /*** IDirect3DDevice1 ***/
6825 IDirect3DDeviceImpl_1_Initialize,
6826 IDirect3DDeviceImpl_1_GetCaps,
6827 IDirect3DDeviceImpl_1_SwapTextureHandles,
6828 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6829 IDirect3DDeviceImpl_1_GetStats,
6830 IDirect3DDeviceImpl_1_Execute,
6831 IDirect3DDeviceImpl_1_AddViewport,
6832 IDirect3DDeviceImpl_1_DeleteViewport,
6833 IDirect3DDeviceImpl_1_NextViewport,
6834 IDirect3DDeviceImpl_1_Pick,
6835 IDirect3DDeviceImpl_1_GetPickRecords,
6836 IDirect3DDeviceImpl_1_EnumTextureFormats,
6837 IDirect3DDeviceImpl_1_CreateMatrix,
6838 IDirect3DDeviceImpl_1_SetMatrix,
6839 IDirect3DDeviceImpl_1_GetMatrix,
6840 IDirect3DDeviceImpl_1_DeleteMatrix,
6841 IDirect3DDeviceImpl_1_BeginScene,
6842 IDirect3DDeviceImpl_1_EndScene,
6843 IDirect3DDeviceImpl_1_GetDirect3D
6846 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6848 if (!iface) return NULL;
6849 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6850 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice7_iface);
6853 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6855 if (!iface) return NULL;
6856 assert(iface->lpVtbl == &d3d_device3_vtbl);
6857 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice3_iface);
6860 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6862 if (!iface) return NULL;
6863 assert(iface->lpVtbl == &d3d_device2_vtbl);
6864 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice2_iface);
6867 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6869 if (!iface) return NULL;
6870 assert(iface->lpVtbl == &d3d_device1_vtbl);
6871 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice_iface);
6874 /*****************************************************************************
6875 * IDirect3DDeviceImpl_UpdateDepthStencil
6877 * Checks the current render target for attached depth stencils and sets the
6878 * WineD3D depth stencil accordingly.
6880 * Returns:
6881 * The depth stencil state to set if creating the device
6883 *****************************************************************************/
6884 WINED3DZBUFFERTYPE
6885 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6887 IDirectDrawSurface7 *depthStencil = NULL;
6888 IDirectDrawSurfaceImpl *dsi;
6889 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6891 IDirectDrawSurface7_GetAttachedSurface(&This->target->IDirectDrawSurface7_iface, &depthcaps, &depthStencil);
6892 if(!depthStencil)
6894 TRACE("Setting wined3d depth stencil to NULL\n");
6895 wined3d_device_set_depth_stencil(This->wined3d_device, NULL);
6896 return WINED3DZB_FALSE;
6899 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6900 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
6901 wined3d_device_set_depth_stencil(This->wined3d_device, dsi->wined3d_surface);
6903 IDirectDrawSurface7_Release(depthStencil);
6904 return WINED3DZB_TRUE;
6907 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
6909 HRESULT hr;
6911 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6912 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6913 else
6914 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
6916 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6917 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6918 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6919 device->ref = 1;
6920 device->ddraw = ddraw;
6921 device->target = target;
6922 list_init(&device->viewport_list);
6924 if (!ddraw_handle_table_init(&device->handle_table, 64))
6926 ERR("Failed to initialize handle table.\n");
6927 return DDERR_OUTOFMEMORY;
6930 device->legacyTextureBlending = FALSE;
6932 /* Create an index buffer, it's needed for indexed drawing */
6933 hr = wined3d_buffer_create_ib(ddraw->wined3d_device, 0x40000 /* Length. Don't know how long it should be */,
6934 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, NULL,
6935 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
6936 if (FAILED(hr))
6938 ERR("Failed to create an index buffer, hr %#x.\n", hr);
6939 ddraw_handle_table_destroy(&device->handle_table);
6940 return hr;
6943 /* This is for convenience. */
6944 device->wined3d_device = ddraw->wined3d_device;
6945 wined3d_device_incref(ddraw->wined3d_device);
6947 /* Render to the back buffer */
6948 hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
6949 if (FAILED(hr))
6951 ERR("Failed to set render target, hr %#x.\n", hr);
6952 wined3d_buffer_decref(device->indexbuffer);
6953 ddraw_handle_table_destroy(&device->handle_table);
6954 return hr;
6957 /* FIXME: This is broken. The target AddRef() makes some sense, because
6958 * we store a pointer during initialization, but then that's also where
6959 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6960 /* AddRef the render target. Also AddRef the render target from ddraw,
6961 * because if it is released before the app releases the D3D device, the
6962 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6964 * In most cases, those surfaces are the same anyway, but this will simply
6965 * add another ref which is released when the device is destroyed. */
6966 IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
6968 ddraw->d3ddevice = device;
6970 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3DRS_ZENABLE,
6971 IDirect3DDeviceImpl_UpdateDepthStencil(device));
6973 return D3D_OK;