winhlp32: Fix hlpfile content decompression in phrase40 mode.
[wine/multimedia.git] / dlls / ddraw / device.c
blobecff7fa51cfc9455903f9a0d484a302d42f0b7fe
1 /*
2 * Copyright (c) 1998-2004 Lionel Ulmer
3 * Copyright (c) 2002-2005 Christian Costa
4 * Copyright (c) 2006 Stefan Dösinger
5 * Copyright (c) 2008 Alexander Dorofeyev
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * IDirect3DDevice implementation, version 1, 2, 3 and 7. Rendering is relayed
22 * to WineD3D, some minimal DirectDraw specific management is handled here.
23 * The Direct3DDevice is NOT the parent of the WineD3DDevice, because d3d
24 * is initialized when DirectDraw creates the primary surface.
25 * Some type management is necessary, because some D3D types changed between
26 * D3D7 and D3D9.
30 #include "config.h"
31 #include "wine/port.h"
33 #include "ddraw_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
37 /* The device ID */
38 const GUID IID_D3DDEVICE_WineD3D = {
39 0xaef72d43,
40 0xb09a,
41 0x4b7b,
42 { 0xb7,0x98,0xc6,0x8a,0x77,0x2d,0x72,0x2a }
45 static inline void set_fpu_control_word(WORD fpucw)
47 #if defined(__i386__) && defined(__GNUC__)
48 __asm__ volatile ("fldcw %0" : : "m" (fpucw));
49 #elif defined(__i386__) && defined(_MSC_VER)
50 __asm fldcw fpucw;
51 #endif
54 static inline WORD d3d_fpu_setup(void)
56 WORD oldcw;
58 #if defined(__i386__) && defined(__GNUC__)
59 __asm__ volatile ("fnstcw %0" : "=m" (oldcw));
60 #elif defined(__i386__) && defined(_MSC_VER)
61 __asm fnstcw oldcw;
62 #else
63 static BOOL warned = FALSE;
64 if(!warned)
66 FIXME("FPUPRESERVE not implemented for this platform / compiler\n");
67 warned = TRUE;
69 return 0;
70 #endif
72 set_fpu_control_word(0x37f);
74 return oldcw;
77 /*****************************************************************************
78 * IUnknown Methods. Common for Version 1, 2, 3 and 7
79 *****************************************************************************/
81 /*****************************************************************************
82 * IDirect3DDevice7::QueryInterface
84 * Used to query other interfaces from a Direct3DDevice interface.
85 * It can return interface pointers to all Direct3DDevice versions as well
86 * as IDirectDraw and IDirect3D. For a link to QueryInterface
87 * rules see ddraw.c, IDirectDraw7::QueryInterface
89 * Exists in Version 1, 2, 3 and 7
91 * Params:
92 * refiid: Interface ID queried for
93 * obj: Used to return the interface pointer
95 * Returns:
96 * D3D_OK or E_NOINTERFACE
98 *****************************************************************************/
99 static HRESULT WINAPI
100 IDirect3DDeviceImpl_7_QueryInterface(IDirect3DDevice7 *iface,
101 REFIID refiid,
102 void **obj)
104 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
106 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(refiid), obj);
108 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
109 *obj = NULL;
111 if(!refiid)
112 return DDERR_INVALIDPARAMS;
114 if ( IsEqualGUID( &IID_IUnknown, refiid ) )
116 *obj = iface;
119 /* Check DirectDraw Interfaces. */
120 else if( IsEqualGUID( &IID_IDirectDraw7, refiid ) )
122 *obj = &This->ddraw->IDirectDraw7_iface;
123 TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
125 else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
127 *obj = &This->ddraw->IDirectDraw4_iface;
128 TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
130 else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
132 *obj = &This->ddraw->IDirectDraw2_iface;
133 TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
135 else if( IsEqualGUID( &IID_IDirectDraw, refiid ) )
137 *obj = &This->ddraw->IDirectDraw_iface;
138 TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
141 /* Direct3D */
142 else if ( IsEqualGUID( &IID_IDirect3D , refiid ) )
144 *obj = &This->ddraw->IDirect3D_iface;
145 TRACE("(%p) Returning IDirect3D interface at %p\n", This, *obj);
147 else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) )
149 *obj = &This->ddraw->IDirect3D2_iface;
150 TRACE("(%p) Returning IDirect3D2 interface at %p\n", This, *obj);
152 else if ( IsEqualGUID( &IID_IDirect3D3 , refiid ) )
154 *obj = &This->ddraw->IDirect3D3_iface;
155 TRACE("(%p) Returning IDirect3D3 interface at %p\n", This, *obj);
157 else if ( IsEqualGUID( &IID_IDirect3D7 , refiid ) )
159 *obj = &This->ddraw->IDirect3D7_iface;
160 TRACE("(%p) Returning IDirect3D7 interface at %p\n", This, *obj);
163 /* Direct3DDevice */
164 else if ( IsEqualGUID( &IID_IDirect3DDevice , refiid ) )
166 *obj = &This->IDirect3DDevice_iface;
167 TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
169 else if ( IsEqualGUID( &IID_IDirect3DDevice2 , refiid ) ) {
170 *obj = &This->IDirect3DDevice2_iface;
171 TRACE("(%p) Returning IDirect3DDevice2 interface at %p\n", This, *obj);
173 else if ( IsEqualGUID( &IID_IDirect3DDevice3 , refiid ) ) {
174 *obj = &This->IDirect3DDevice3_iface;
175 TRACE("(%p) Returning IDirect3DDevice3 interface at %p\n", This, *obj);
177 else if ( IsEqualGUID( &IID_IDirect3DDevice7 , refiid ) ) {
178 *obj = This;
179 TRACE("(%p) Returning IDirect3DDevice7 interface at %p\n", This, *obj);
182 /* Unknown interface */
183 else
185 ERR("(%p)->(%s, %p): No interface found\n", This, debugstr_guid(refiid), obj);
186 return E_NOINTERFACE;
189 /* AddRef the returned interface */
190 IUnknown_AddRef( (IUnknown *) *obj);
191 return D3D_OK;
194 static HRESULT WINAPI IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface, REFIID riid,
195 void **obj)
197 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
198 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
200 return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obj);
203 static HRESULT WINAPI IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface, REFIID riid,
204 void **obj)
206 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
207 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
209 return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obj);
212 static HRESULT WINAPI IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface, REFIID riid,
213 void **obp)
215 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
216 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
218 return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obp);
221 /*****************************************************************************
222 * IDirect3DDevice7::AddRef
224 * Increases the refcount....
225 * The most exciting Method, definitely
227 * Exists in Version 1, 2, 3 and 7
229 * Returns:
230 * The new refcount
232 *****************************************************************************/
233 static ULONG WINAPI
234 IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
236 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
237 ULONG ref = InterlockedIncrement(&This->ref);
239 TRACE("%p increasing refcount to %u.\n", This, ref);
241 return ref;
244 static ULONG WINAPI IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
246 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
247 TRACE("iface %p.\n", iface);
249 return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
252 static ULONG WINAPI IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
254 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
255 TRACE("iface %p.\n", iface);
257 return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
260 static ULONG WINAPI IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
262 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
263 TRACE("iface %p.\n", iface);
265 return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
268 /*****************************************************************************
269 * IDirect3DDevice7::Release
271 * Decreases the refcount of the interface
272 * When the refcount is reduced to 0, the object is destroyed.
274 * Exists in Version 1, 2, 3 and 7
276 * Returns:d
277 * The new refcount
279 *****************************************************************************/
280 static ULONG WINAPI
281 IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
283 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
284 ULONG ref = InterlockedDecrement(&This->ref);
286 TRACE("%p decreasing refcount to %u.\n", This, ref);
288 /* This method doesn't destroy the WineD3DDevice, because it's still in use for
289 * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
290 * when the render target is released
292 if (ref == 0)
294 DWORD i;
296 wined3d_mutex_lock();
298 /* There is no need to unset any resources here, wined3d will take
299 * care of that on Uninit3D(). */
301 /* Free the index buffer. */
302 wined3d_buffer_decref(This->indexbuffer);
304 /* Set the device up to render to the front buffer since the back
305 * buffer will vanish soon. */
306 wined3d_device_set_render_target(This->wined3d_device, 0,
307 This->ddraw->d3d_target->wined3d_surface, TRUE);
309 /* Release the WineD3DDevice. This won't destroy it. */
310 if (!wined3d_device_decref(This->wined3d_device))
311 ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This->wined3d_device);
313 /* The texture handles should be unset by now, but there might be some bits
314 * missing in our reference counting(needs test). Do a sanity check. */
315 for (i = 0; i < This->handle_table.entry_count; ++i)
317 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
319 switch (entry->type)
321 case DDRAW_HANDLE_FREE:
322 break;
324 case DDRAW_HANDLE_MATERIAL:
326 IDirect3DMaterialImpl *m = entry->object;
327 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
328 m->Handle = 0;
329 break;
332 case DDRAW_HANDLE_MATRIX:
334 /* No FIXME here because this might happen because of sloppy applications. */
335 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
336 IDirect3DDevice_DeleteMatrix(&This->IDirect3DDevice_iface, i + 1);
337 break;
340 case DDRAW_HANDLE_STATEBLOCK:
342 /* No FIXME here because this might happen because of sloppy applications. */
343 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
344 IDirect3DDevice7_DeleteStateBlock(iface, i + 1);
345 break;
348 case DDRAW_HANDLE_SURFACE:
350 IDirectDrawSurfaceImpl *surf = entry->object;
351 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
352 surf->Handle = 0;
353 break;
356 default:
357 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
358 break;
362 ddraw_handle_table_destroy(&This->handle_table);
364 TRACE("Releasing target %p %p\n", This->target, This->ddraw->d3d_target);
365 /* Release the render target and the WineD3D render target
366 * (See IDirect3D7::CreateDevice for more comments on this)
368 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
369 IDirectDrawSurface7_Release(&This->ddraw->d3d_target->IDirectDrawSurface7_iface);
370 TRACE("Target release done\n");
372 This->ddraw->d3ddevice = NULL;
374 /* Now free the structure */
375 HeapFree(GetProcessHeap(), 0, This);
376 wined3d_mutex_unlock();
379 TRACE("Done\n");
380 return ref;
383 static ULONG WINAPI IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
385 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
386 TRACE("iface %p.\n", iface);
388 return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
391 static ULONG WINAPI IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
393 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
394 TRACE("iface %p.\n", iface);
396 return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
399 static ULONG WINAPI IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
401 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
402 TRACE("iface %p.\n", iface);
404 return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
407 /*****************************************************************************
408 * IDirect3DDevice Methods
409 *****************************************************************************/
411 /*****************************************************************************
412 * IDirect3DDevice::Initialize
414 * Initializes a Direct3DDevice. This implementation is a no-op, as all
415 * initialization is done at create time.
417 * Exists in Version 1
419 * Parameters:
420 * No idea what they mean, as the MSDN page is gone
422 * Returns: DD_OK
424 *****************************************************************************/
425 static HRESULT WINAPI
426 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
427 IDirect3D *Direct3D, GUID *guid,
428 D3DDEVICEDESC *Desc)
430 /* It shouldn't be crucial, but print a FIXME, I'm interested if
431 * any game calls it and when. */
432 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
433 iface, Direct3D, debugstr_guid(guid), Desc);
435 return D3D_OK;
438 /*****************************************************************************
439 * IDirect3DDevice7::GetCaps
441 * Retrieves the device's capabilities
443 * This implementation is used for Version 7 only, the older versions have
444 * their own implementation.
446 * Parameters:
447 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
449 * Returns:
450 * D3D_OK on success
451 * D3DERR_* if a problem occurs. See WineD3D
453 *****************************************************************************/
454 static HRESULT
455 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
456 D3DDEVICEDESC7 *Desc)
458 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
459 D3DDEVICEDESC OldDesc;
461 TRACE("iface %p, device_desc %p.\n", iface, Desc);
463 /* Call the same function used by IDirect3D, this saves code */
464 return IDirect3DImpl_GetCaps(This->ddraw->wineD3D, &OldDesc, Desc);
467 static HRESULT WINAPI
468 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
469 D3DDEVICEDESC7 *Desc)
471 return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
474 static HRESULT WINAPI
475 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
476 D3DDEVICEDESC7 *Desc)
478 HRESULT hr;
479 WORD old_fpucw;
481 old_fpucw = d3d_fpu_setup();
482 hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
483 set_fpu_control_word(old_fpucw);
485 return hr;
487 /*****************************************************************************
488 * IDirect3DDevice3::GetCaps
490 * Retrieves the capabilities of the hardware device and the emulation
491 * device. For Wine, hardware and emulation are the same (it's all HW).
493 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
495 * Parameters:
496 * HWDesc: Structure to fill with the HW caps
497 * HelDesc: Structure to fill with the hardware emulation caps
499 * Returns:
500 * D3D_OK on success
501 * D3DERR_* if a problem occurs. See WineD3D
503 *****************************************************************************/
504 static HRESULT WINAPI
505 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
506 D3DDEVICEDESC *HWDesc,
507 D3DDEVICEDESC *HelDesc)
509 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
510 D3DDEVICEDESC7 newDesc;
511 HRESULT hr;
513 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
515 hr = IDirect3DImpl_GetCaps(This->ddraw->wineD3D, HWDesc, &newDesc);
516 if(hr != D3D_OK) return hr;
518 *HelDesc = *HWDesc;
519 return D3D_OK;
522 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
523 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
525 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
526 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
527 return IDirect3DDevice3_GetCaps(&This->IDirect3DDevice3_iface, D3DHWDevDesc, D3DHELDevDesc);
530 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
531 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
533 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
534 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
535 return IDirect3DDevice3_GetCaps(&This->IDirect3DDevice3_iface, D3DHWDevDesc, D3DHELDevDesc);
538 /*****************************************************************************
539 * IDirect3DDevice2::SwapTextureHandles
541 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
543 * Parameters:
544 * Tex1, Tex2: The 2 Textures to swap
546 * Returns:
547 * D3D_OK
549 *****************************************************************************/
550 static HRESULT WINAPI
551 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
552 IDirect3DTexture2 *Tex1,
553 IDirect3DTexture2 *Tex2)
555 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
556 IDirectDrawSurfaceImpl *surf1 = unsafe_impl_from_IDirect3DTexture2(Tex1);
557 IDirectDrawSurfaceImpl *surf2 = unsafe_impl_from_IDirect3DTexture2(Tex2);
558 DWORD h1, h2;
560 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, Tex1, Tex2);
562 wined3d_mutex_lock();
564 h1 = surf1->Handle - 1;
565 h2 = surf2->Handle - 1;
566 This->handle_table.entries[h1].object = surf2;
567 This->handle_table.entries[h2].object = surf1;
568 surf2->Handle = h1 + 1;
569 surf1->Handle = h2 + 1;
571 wined3d_mutex_unlock();
573 return D3D_OK;
576 static HRESULT WINAPI IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
577 IDirect3DTexture *D3DTex1, IDirect3DTexture *D3DTex2)
579 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
580 IDirectDrawSurfaceImpl *surf1 = unsafe_impl_from_IDirect3DTexture(D3DTex1);
581 IDirectDrawSurfaceImpl *surf2 = unsafe_impl_from_IDirect3DTexture(D3DTex2);
582 IDirect3DTexture2 *t1 = surf1 ? &surf1->IDirect3DTexture2_iface : NULL;
583 IDirect3DTexture2 *t2 = surf2 ? &surf2->IDirect3DTexture2_iface : NULL;
585 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, D3DTex1, D3DTex2);
587 return IDirect3DDevice2_SwapTextureHandles(&This->IDirect3DDevice2_iface, t1, t2);
590 /*****************************************************************************
591 * IDirect3DDevice3::GetStats
593 * This method seems to retrieve some stats from the device.
594 * The MSDN documentation doesn't exist any more, but the D3DSTATS
595 * structure suggests that the amount of drawn primitives and processed
596 * vertices is returned.
598 * Exists in Version 1, 2 and 3
600 * Parameters:
601 * Stats: Pointer to a D3DSTATS structure to be filled
603 * Returns:
604 * D3D_OK on success
605 * DDERR_INVALIDPARAMS if Stats == NULL
607 *****************************************************************************/
608 static HRESULT WINAPI
609 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
610 D3DSTATS *Stats)
612 FIXME("iface %p, stats %p stub!\n", iface, Stats);
614 if(!Stats)
615 return DDERR_INVALIDPARAMS;
617 /* Fill the Stats with 0 */
618 Stats->dwTrianglesDrawn = 0;
619 Stats->dwLinesDrawn = 0;
620 Stats->dwPointsDrawn = 0;
621 Stats->dwSpansDrawn = 0;
622 Stats->dwVerticesProcessed = 0;
624 return D3D_OK;
627 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *Stats)
629 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
631 TRACE("iface %p, stats %p.\n", iface, Stats);
633 return IDirect3DDevice3_GetStats(&This->IDirect3DDevice3_iface, Stats);
636 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface, D3DSTATS *Stats)
638 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
640 TRACE("iface %p, stats %p.\n", iface, Stats);
642 return IDirect3DDevice3_GetStats(&This->IDirect3DDevice3_iface, Stats);
645 /*****************************************************************************
646 * IDirect3DDevice::CreateExecuteBuffer
648 * Creates an IDirect3DExecuteBuffer, used for rendering with a
649 * Direct3DDevice.
651 * Version 1 only.
653 * Params:
654 * Desc: Buffer description
655 * ExecuteBuffer: Address to return the Interface pointer at
656 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
657 * support
659 * Returns:
660 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
661 * DDERR_OUTOFMEMORY if we ran out of memory
662 * D3D_OK on success
664 *****************************************************************************/
665 static HRESULT WINAPI
666 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
667 D3DEXECUTEBUFFERDESC *Desc,
668 IDirect3DExecuteBuffer **ExecuteBuffer,
669 IUnknown *UnkOuter)
671 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
672 IDirect3DExecuteBufferImpl* object;
673 HRESULT hr;
675 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
676 iface, Desc, ExecuteBuffer, UnkOuter);
678 if(UnkOuter)
679 return CLASS_E_NOAGGREGATION;
681 /* Allocate the new Execute Buffer */
682 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
683 if(!object)
685 ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
686 return DDERR_OUTOFMEMORY;
689 hr = d3d_execute_buffer_init(object, This, Desc);
690 if (FAILED(hr))
692 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
693 HeapFree(GetProcessHeap(), 0, object);
694 return hr;
697 *ExecuteBuffer = &object->IDirect3DExecuteBuffer_iface;
699 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
701 return D3D_OK;
704 /*****************************************************************************
705 * IDirect3DDevice::Execute
707 * Executes all the stuff in an execute buffer.
709 * Params:
710 * ExecuteBuffer: The buffer to execute
711 * Viewport: The viewport used for rendering
712 * Flags: Some flags
714 * Returns:
715 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
716 * D3D_OK on success
718 *****************************************************************************/
719 static HRESULT WINAPI IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
720 IDirect3DExecuteBuffer *ExecuteBuffer, IDirect3DViewport *Viewport, DWORD Flags)
722 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
723 IDirect3DExecuteBufferImpl *buffer = unsafe_impl_from_IDirect3DExecuteBuffer(ExecuteBuffer);
724 IDirect3DViewportImpl *Direct3DViewportImpl = unsafe_impl_from_IDirect3DViewport(Viewport);
725 HRESULT hr;
727 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, Viewport, Flags);
729 if(!buffer)
730 return DDERR_INVALIDPARAMS;
732 /* Execute... */
733 wined3d_mutex_lock();
734 hr = d3d_execute_buffer_execute(buffer, This, Direct3DViewportImpl);
735 wined3d_mutex_unlock();
737 return hr;
740 /*****************************************************************************
741 * IDirect3DDevice3::AddViewport
743 * Add a Direct3DViewport to the device's viewport list. These viewports
744 * are wrapped to IDirect3DDevice7 viewports in viewport.c
746 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
747 * are the same interfaces.
749 * Params:
750 * Viewport: The viewport to add
752 * Returns:
753 * DDERR_INVALIDPARAMS if Viewport == NULL
754 * D3D_OK on success
756 *****************************************************************************/
757 static HRESULT WINAPI
758 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
759 IDirect3DViewport3 *Viewport)
761 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
762 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(Viewport);
764 TRACE("iface %p, viewport %p.\n", iface, Viewport);
766 /* Sanity check */
767 if(!vp)
768 return DDERR_INVALIDPARAMS;
770 wined3d_mutex_lock();
771 list_add_head(&This->viewport_list, &vp->entry);
772 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
773 so set active_device here. */
774 wined3d_mutex_unlock();
776 return D3D_OK;
779 static HRESULT WINAPI IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
780 IDirect3DViewport2 *Direct3DViewport2)
782 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
783 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
785 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
787 return IDirect3DDevice3_AddViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
790 static HRESULT WINAPI IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
791 IDirect3DViewport *Direct3DViewport)
793 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
794 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport(Direct3DViewport);
796 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
798 return IDirect3DDevice3_AddViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
801 /*****************************************************************************
802 * IDirect3DDevice3::DeleteViewport
804 * Deletes a Direct3DViewport from the device's viewport list.
806 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
807 * are equal.
809 * Params:
810 * Viewport: The viewport to delete
812 * Returns:
813 * D3D_OK on success
814 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
816 *****************************************************************************/
817 static HRESULT WINAPI IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
819 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
820 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
822 TRACE("iface %p, viewport %p.\n", iface, viewport);
824 wined3d_mutex_lock();
826 if (vp->active_device != This)
828 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
829 wined3d_mutex_unlock();
830 return DDERR_INVALIDPARAMS;
833 vp->active_device = NULL;
834 list_remove(&vp->entry);
836 wined3d_mutex_unlock();
838 return D3D_OK;
841 static HRESULT WINAPI IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
842 IDirect3DViewport2 *Direct3DViewport2)
844 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
845 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
847 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
849 return IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
852 static HRESULT WINAPI IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
853 IDirect3DViewport *Direct3DViewport)
855 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
856 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport(Direct3DViewport);
858 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
860 return IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
863 /*****************************************************************************
864 * IDirect3DDevice3::NextViewport
866 * Returns a viewport from the viewport list, depending on the
867 * passed viewport and the flags.
869 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
870 * are equal.
872 * Params:
873 * Viewport: Viewport to use for beginning the search
874 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
876 * Returns:
877 * D3D_OK on success
878 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
880 *****************************************************************************/
881 static HRESULT WINAPI
882 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
883 IDirect3DViewport3 *Viewport3,
884 IDirect3DViewport3 **lplpDirect3DViewport3,
885 DWORD Flags)
887 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
888 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(Viewport3);
889 IDirect3DViewportImpl *next;
890 struct list *entry;
892 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
893 iface, Viewport3, lplpDirect3DViewport3, Flags);
895 if(!vp)
897 *lplpDirect3DViewport3 = NULL;
898 return DDERR_INVALIDPARAMS;
902 wined3d_mutex_lock();
903 switch (Flags)
905 case D3DNEXT_NEXT:
906 entry = list_next(&This->viewport_list, &vp->entry);
907 break;
909 case D3DNEXT_HEAD:
910 entry = list_head(&This->viewport_list);
911 break;
913 case D3DNEXT_TAIL:
914 entry = list_tail(&This->viewport_list);
915 break;
917 default:
918 WARN("Invalid flags %#x.\n", Flags);
919 *lplpDirect3DViewport3 = NULL;
920 wined3d_mutex_unlock();
921 return DDERR_INVALIDPARAMS;
924 if (entry)
926 next = LIST_ENTRY(entry, IDirect3DViewportImpl, entry);
927 *lplpDirect3DViewport3 = &next->IDirect3DViewport3_iface;
929 else
930 *lplpDirect3DViewport3 = NULL;
932 wined3d_mutex_unlock();
934 return D3D_OK;
937 static HRESULT WINAPI IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
938 IDirect3DViewport2 *Viewport2, IDirect3DViewport2 **lplpDirect3DViewport2, DWORD Flags)
940 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
941 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Viewport2);
942 IDirect3DViewport3 *res;
943 HRESULT hr;
945 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
946 iface, Viewport2, lplpDirect3DViewport2, Flags);
948 hr = IDirect3DDevice3_NextViewport(&This->IDirect3DDevice3_iface,
949 &vp->IDirect3DViewport3_iface, &res, Flags);
950 *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
951 return hr;
954 static HRESULT WINAPI IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
955 IDirect3DViewport *Viewport, IDirect3DViewport **lplpDirect3DViewport, DWORD Flags)
957 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
958 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport(Viewport);
959 IDirect3DViewport3 *res;
960 HRESULT hr;
962 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
963 iface, Viewport, lplpDirect3DViewport, Flags);
965 hr = IDirect3DDevice3_NextViewport(&This->IDirect3DDevice3_iface,
966 &vp->IDirect3DViewport3_iface, &res, Flags);
967 *lplpDirect3DViewport = (IDirect3DViewport *)res;
968 return hr;
971 /*****************************************************************************
972 * IDirect3DDevice::Pick
974 * Executes an execute buffer without performing rendering. Instead, a
975 * list of primitives that intersect with (x1,y1) of the passed rectangle
976 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
977 * this list.
979 * Version 1 only
981 * Params:
982 * ExecuteBuffer: Buffer to execute
983 * Viewport: Viewport to use for execution
984 * Flags: None are defined, according to the SDK
985 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
986 * x2 and y2 are ignored.
988 * Returns:
989 * D3D_OK because it's a stub
991 *****************************************************************************/
992 static HRESULT WINAPI
993 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
994 IDirect3DExecuteBuffer *ExecuteBuffer,
995 IDirect3DViewport *Viewport,
996 DWORD Flags,
997 D3DRECT *Rect)
999 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
1000 iface, ExecuteBuffer, Viewport, Flags, wine_dbgstr_rect((RECT *)Rect));
1002 return D3D_OK;
1005 /*****************************************************************************
1006 * IDirect3DDevice::GetPickRecords
1008 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1010 * Version 1 only
1012 * Params:
1013 * Count: Pointer to a DWORD containing the numbers of pick records to
1014 * retrieve
1015 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1017 * Returns:
1018 * D3D_OK, because it's a stub
1020 *****************************************************************************/
1021 static HRESULT WINAPI
1022 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1023 DWORD *Count,
1024 D3DPICKRECORD *D3DPickRec)
1026 FIXME("iface %p, count %p, records %p stub!\n", iface, Count, D3DPickRec);
1028 return D3D_OK;
1031 /*****************************************************************************
1032 * IDirect3DDevice7::EnumTextureformats
1034 * Enumerates the supported texture formats. It has a list of all possible
1035 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1036 * WineD3D supports it. If so, then it is passed to the app.
1038 * This is for Version 7 and 3, older versions have a different
1039 * callback function and their own implementation
1041 * Params:
1042 * Callback: Callback to call for each enumerated format
1043 * Arg: Argument to pass to the callback
1045 * Returns:
1046 * D3D_OK on success
1047 * DDERR_INVALIDPARAMS if Callback == NULL
1049 *****************************************************************************/
1050 static HRESULT
1051 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1052 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1053 void *Arg)
1055 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1056 HRESULT hr;
1057 WINED3DDISPLAYMODE mode;
1058 unsigned int i;
1060 static const enum wined3d_format_id FormatList[] =
1062 /* 32 bit */
1063 WINED3DFMT_B8G8R8A8_UNORM,
1064 WINED3DFMT_B8G8R8X8_UNORM,
1065 /* 24 bit */
1066 WINED3DFMT_B8G8R8_UNORM,
1067 /* 16 Bit */
1068 WINED3DFMT_B5G5R5A1_UNORM,
1069 WINED3DFMT_B4G4R4A4_UNORM,
1070 WINED3DFMT_B5G6R5_UNORM,
1071 WINED3DFMT_B5G5R5X1_UNORM,
1072 /* 8 Bit */
1073 WINED3DFMT_B2G3R3_UNORM,
1074 WINED3DFMT_P8_UINT,
1075 /* FOURCC codes */
1076 WINED3DFMT_DXT1,
1077 WINED3DFMT_DXT3,
1078 WINED3DFMT_DXT5,
1081 static const enum wined3d_format_id BumpFormatList[] =
1083 WINED3DFMT_R8G8_SNORM,
1084 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1085 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1086 WINED3DFMT_R16G16_SNORM,
1087 WINED3DFMT_R10G11B11_SNORM,
1088 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1091 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1093 if(!Callback)
1094 return DDERR_INVALIDPARAMS;
1096 wined3d_mutex_lock();
1098 memset(&mode, 0, sizeof(mode));
1099 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1100 if (FAILED(hr))
1102 wined3d_mutex_unlock();
1103 WARN("Cannot get the current adapter format\n");
1104 return hr;
1107 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1109 hr = wined3d_check_device_format(This->ddraw->wineD3D, WINED3DADAPTER_DEFAULT, WINED3DDEVTYPE_HAL,
1110 mode.Format, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1111 if (hr == D3D_OK)
1113 DDPIXELFORMAT pformat;
1115 memset(&pformat, 0, sizeof(pformat));
1116 pformat.dwSize = sizeof(pformat);
1117 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1119 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1120 hr = Callback(&pformat, Arg);
1121 if(hr != DDENUMRET_OK)
1123 TRACE("Format enumeration cancelled by application\n");
1124 wined3d_mutex_unlock();
1125 return D3D_OK;
1130 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1132 hr = wined3d_check_device_format(This->ddraw->wineD3D, WINED3DADAPTER_DEFAULT,
1133 WINED3DDEVTYPE_HAL, mode.Format, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1134 WINED3DRTYPE_TEXTURE, BumpFormatList[i], SURFACE_OPENGL);
1135 if (hr == D3D_OK)
1137 DDPIXELFORMAT pformat;
1139 memset(&pformat, 0, sizeof(pformat));
1140 pformat.dwSize = sizeof(pformat);
1141 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1143 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1144 hr = Callback(&pformat, Arg);
1145 if(hr != DDENUMRET_OK)
1147 TRACE("Format enumeration cancelled by application\n");
1148 wined3d_mutex_unlock();
1149 return D3D_OK;
1153 TRACE("End of enumeration\n");
1154 wined3d_mutex_unlock();
1156 return D3D_OK;
1159 static HRESULT WINAPI
1160 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1161 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1162 void *Arg)
1164 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1167 static HRESULT WINAPI
1168 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1169 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1170 void *Arg)
1172 HRESULT hr;
1173 WORD old_fpucw;
1175 old_fpucw = d3d_fpu_setup();
1176 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1177 set_fpu_control_word(old_fpucw);
1179 return hr;
1182 static HRESULT WINAPI IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1183 LPD3DENUMPIXELFORMATSCALLBACK Callback, void *Arg)
1185 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1187 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1189 return IDirect3DDevice7_EnumTextureFormats(&This->IDirect3DDevice7_iface, Callback, Arg);
1192 /*****************************************************************************
1193 * IDirect3DDevice2::EnumTextureformats
1195 * EnumTextureFormats for Version 1 and 2, see
1196 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1198 * This version has a different callback and does not enumerate FourCC
1199 * formats
1201 *****************************************************************************/
1202 static HRESULT WINAPI
1203 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1204 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1205 void *Arg)
1207 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1208 HRESULT hr;
1209 unsigned int i;
1210 WINED3DDISPLAYMODE mode;
1212 static const enum wined3d_format_id FormatList[] =
1214 /* 32 bit */
1215 WINED3DFMT_B8G8R8A8_UNORM,
1216 WINED3DFMT_B8G8R8X8_UNORM,
1217 /* 24 bit */
1218 WINED3DFMT_B8G8R8_UNORM,
1219 /* 16 Bit */
1220 WINED3DFMT_B5G5R5A1_UNORM,
1221 WINED3DFMT_B4G4R4A4_UNORM,
1222 WINED3DFMT_B5G6R5_UNORM,
1223 WINED3DFMT_B5G5R5X1_UNORM,
1224 /* 8 Bit */
1225 WINED3DFMT_B2G3R3_UNORM,
1226 WINED3DFMT_P8_UINT,
1227 /* FOURCC codes - Not in this version*/
1230 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1232 if(!Callback)
1233 return DDERR_INVALIDPARAMS;
1235 wined3d_mutex_lock();
1237 memset(&mode, 0, sizeof(mode));
1238 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1239 if (FAILED(hr))
1241 wined3d_mutex_unlock();
1242 WARN("Cannot get the current adapter format\n");
1243 return hr;
1246 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1248 hr = wined3d_check_device_format(This->ddraw->wineD3D, 0, WINED3DDEVTYPE_HAL,
1249 mode.Format, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1250 if (hr == D3D_OK)
1252 DDSURFACEDESC sdesc;
1254 memset(&sdesc, 0, sizeof(sdesc));
1255 sdesc.dwSize = sizeof(sdesc);
1256 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1257 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1258 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1259 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1261 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1262 hr = Callback(&sdesc, Arg);
1263 if(hr != DDENUMRET_OK)
1265 TRACE("Format enumeration cancelled by application\n");
1266 wined3d_mutex_unlock();
1267 return D3D_OK;
1271 TRACE("End of enumeration\n");
1272 wined3d_mutex_unlock();
1274 return D3D_OK;
1277 static HRESULT WINAPI IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1278 LPD3DENUMTEXTUREFORMATSCALLBACK Callback, void *Arg)
1280 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1282 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1284 return IDirect3DDevice2_EnumTextureFormats(&This->IDirect3DDevice2_iface, Callback, Arg);
1287 /*****************************************************************************
1288 * IDirect3DDevice::CreateMatrix
1290 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1291 * allocated for the handle.
1293 * Version 1 only
1295 * Params
1296 * D3DMatHandle: Address to return the handle at
1298 * Returns:
1299 * D3D_OK on success
1300 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1302 *****************************************************************************/
1303 static HRESULT WINAPI
1304 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1306 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1307 D3DMATRIX *Matrix;
1308 DWORD h;
1310 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1312 if(!D3DMatHandle)
1313 return DDERR_INVALIDPARAMS;
1315 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1316 if(!Matrix)
1318 ERR("Out of memory when allocating a D3DMATRIX\n");
1319 return DDERR_OUTOFMEMORY;
1322 wined3d_mutex_lock();
1324 h = ddraw_allocate_handle(&This->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1325 if (h == DDRAW_INVALID_HANDLE)
1327 ERR("Failed to allocate a matrix handle.\n");
1328 HeapFree(GetProcessHeap(), 0, Matrix);
1329 wined3d_mutex_unlock();
1330 return DDERR_OUTOFMEMORY;
1333 *D3DMatHandle = h + 1;
1335 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1337 wined3d_mutex_unlock();
1339 return D3D_OK;
1342 /*****************************************************************************
1343 * IDirect3DDevice::SetMatrix
1345 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1346 * allocated for the handle
1348 * Version 1 only
1350 * Params:
1351 * D3DMatHandle: Handle to set the matrix to
1352 * D3DMatrix: Matrix to set
1354 * Returns:
1355 * D3D_OK on success
1356 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1357 * to set is NULL
1359 *****************************************************************************/
1360 static HRESULT WINAPI
1361 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1362 D3DMATRIXHANDLE D3DMatHandle,
1363 D3DMATRIX *D3DMatrix)
1365 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1366 D3DMATRIX *m;
1368 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1370 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1372 wined3d_mutex_lock();
1374 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1375 if (!m)
1377 WARN("Invalid matrix handle.\n");
1378 wined3d_mutex_unlock();
1379 return DDERR_INVALIDPARAMS;
1382 if (TRACE_ON(ddraw))
1383 dump_D3DMATRIX(D3DMatrix);
1385 *m = *D3DMatrix;
1387 if (D3DMatHandle == This->world)
1388 wined3d_device_set_transform(This->wined3d_device, WINED3DTS_WORLDMATRIX(0), (WINED3DMATRIX *)D3DMatrix);
1390 if (D3DMatHandle == This->view)
1391 wined3d_device_set_transform(This->wined3d_device, WINED3DTS_VIEW, (WINED3DMATRIX *)D3DMatrix);
1393 if (D3DMatHandle == This->proj)
1394 wined3d_device_set_transform(This->wined3d_device, WINED3DTS_PROJECTION, (WINED3DMATRIX *)D3DMatrix);
1396 wined3d_mutex_unlock();
1398 return D3D_OK;
1401 /*****************************************************************************
1402 * IDirect3DDevice::GetMatrix
1404 * Returns the content of a D3DMATRIX handle
1406 * Version 1 only
1408 * Params:
1409 * D3DMatHandle: Matrix handle to read the content from
1410 * D3DMatrix: Address to store the content at
1412 * Returns:
1413 * D3D_OK on success
1414 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1416 *****************************************************************************/
1417 static HRESULT WINAPI
1418 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1419 D3DMATRIXHANDLE D3DMatHandle,
1420 D3DMATRIX *D3DMatrix)
1422 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1423 D3DMATRIX *m;
1425 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1427 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1429 wined3d_mutex_lock();
1431 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1432 if (!m)
1434 WARN("Invalid matrix handle.\n");
1435 wined3d_mutex_unlock();
1436 return DDERR_INVALIDPARAMS;
1439 *D3DMatrix = *m;
1441 wined3d_mutex_unlock();
1443 return D3D_OK;
1446 /*****************************************************************************
1447 * IDirect3DDevice::DeleteMatrix
1449 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1451 * Version 1 only
1453 * Params:
1454 * D3DMatHandle: Handle to destroy
1456 * Returns:
1457 * D3D_OK on success
1458 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1460 *****************************************************************************/
1461 static HRESULT WINAPI
1462 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1463 D3DMATRIXHANDLE D3DMatHandle)
1465 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1466 D3DMATRIX *m;
1468 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1470 wined3d_mutex_lock();
1472 m = ddraw_free_handle(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1473 if (!m)
1475 WARN("Invalid matrix handle.\n");
1476 wined3d_mutex_unlock();
1477 return DDERR_INVALIDPARAMS;
1480 wined3d_mutex_unlock();
1482 HeapFree(GetProcessHeap(), 0, m);
1484 return D3D_OK;
1487 /*****************************************************************************
1488 * IDirect3DDevice7::BeginScene
1490 * This method must be called before any rendering is performed.
1491 * IDirect3DDevice::EndScene has to be called after the scene is complete
1493 * Version 1, 2, 3 and 7
1495 * Returns:
1496 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1497 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1498 * started scene).
1500 *****************************************************************************/
1501 static HRESULT
1502 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1504 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1505 HRESULT hr;
1507 TRACE("iface %p.\n", iface);
1509 wined3d_mutex_lock();
1510 hr = wined3d_device_begin_scene(This->wined3d_device);
1511 wined3d_mutex_unlock();
1513 if(hr == WINED3D_OK) return D3D_OK;
1514 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1517 static HRESULT WINAPI
1518 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1520 return IDirect3DDeviceImpl_7_BeginScene(iface);
1523 static HRESULT WINAPI
1524 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1526 HRESULT hr;
1527 WORD old_fpucw;
1529 old_fpucw = d3d_fpu_setup();
1530 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1531 set_fpu_control_word(old_fpucw);
1533 return hr;
1536 static HRESULT WINAPI IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1538 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1539 TRACE("iface %p.\n", iface);
1541 return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
1544 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1546 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1547 TRACE("iface %p.\n", iface);
1549 return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
1552 static HRESULT WINAPI IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1554 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1555 TRACE("iface %p.\n", iface);
1557 return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
1560 /*****************************************************************************
1561 * IDirect3DDevice7::EndScene
1563 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1564 * This method must be called after rendering is finished.
1566 * Version 1, 2, 3 and 7
1568 * Returns:
1569 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1570 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1571 * that only if the scene was already ended.
1573 *****************************************************************************/
1574 static HRESULT
1575 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1577 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1578 HRESULT hr;
1580 TRACE("iface %p.\n", iface);
1582 wined3d_mutex_lock();
1583 hr = wined3d_device_end_scene(This->wined3d_device);
1584 wined3d_mutex_unlock();
1586 if(hr == WINED3D_OK) return D3D_OK;
1587 else return D3DERR_SCENE_NOT_IN_SCENE;
1590 static HRESULT WINAPI DECLSPEC_HOTPATCH
1591 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1593 return IDirect3DDeviceImpl_7_EndScene(iface);
1596 static HRESULT WINAPI DECLSPEC_HOTPATCH
1597 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1599 HRESULT hr;
1600 WORD old_fpucw;
1602 old_fpucw = d3d_fpu_setup();
1603 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1604 set_fpu_control_word(old_fpucw);
1606 return hr;
1609 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1611 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1612 TRACE("iface %p.\n", iface);
1614 return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
1617 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1619 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1620 TRACE("iface %p.\n", iface);
1622 return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
1625 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1627 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1628 TRACE("iface %p.\n", iface);
1630 return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
1633 /*****************************************************************************
1634 * IDirect3DDevice7::GetDirect3D
1636 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1637 * this device.
1639 * Params:
1640 * Direct3D7: Address to store the interface pointer at
1642 * Returns:
1643 * D3D_OK on success
1644 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1646 *****************************************************************************/
1647 static HRESULT WINAPI
1648 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1649 IDirect3D7 **Direct3D7)
1651 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1653 TRACE("iface %p, d3d %p.\n", iface, Direct3D7);
1655 if(!Direct3D7)
1656 return DDERR_INVALIDPARAMS;
1658 *Direct3D7 = &This->ddraw->IDirect3D7_iface;
1659 IDirect3D7_AddRef(*Direct3D7);
1661 TRACE(" returning interface %p\n", *Direct3D7);
1662 return D3D_OK;
1665 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1666 IDirect3D3 **Direct3D3)
1668 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1670 TRACE("iface %p, d3d %p.\n", iface, Direct3D3);
1672 if(!Direct3D3)
1673 return DDERR_INVALIDPARAMS;
1675 IDirect3D3_AddRef(&This->ddraw->IDirect3D3_iface);
1676 *Direct3D3 = &This->ddraw->IDirect3D3_iface;
1677 TRACE(" returning interface %p\n", *Direct3D3);
1678 return D3D_OK;
1681 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1682 IDirect3D2 **Direct3D2)
1684 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1686 TRACE("iface %p, d3d %p.\n", iface, Direct3D2);
1688 if(!Direct3D2)
1689 return DDERR_INVALIDPARAMS;
1691 IDirect3D2_AddRef(&This->ddraw->IDirect3D2_iface);
1692 *Direct3D2 = &This->ddraw->IDirect3D2_iface;
1693 TRACE(" returning interface %p\n", *Direct3D2);
1694 return D3D_OK;
1697 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1698 IDirect3D **Direct3D)
1700 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1702 TRACE("iface %p, d3d %p.\n", iface, Direct3D);
1704 if(!Direct3D)
1705 return DDERR_INVALIDPARAMS;
1707 IDirect3D_AddRef(&This->ddraw->IDirect3D_iface);
1708 *Direct3D = &This->ddraw->IDirect3D_iface;
1709 TRACE(" returning interface %p\n", *Direct3D);
1710 return D3D_OK;
1713 /*****************************************************************************
1714 * IDirect3DDevice3::SetCurrentViewport
1716 * Sets a Direct3DViewport as the current viewport.
1717 * For the thunks note that all viewport interface versions are equal
1719 * Params:
1720 * Direct3DViewport3: The viewport to set
1722 * Version 2 and 3
1724 * Returns:
1725 * D3D_OK on success
1726 * (Is a NULL viewport valid?)
1728 *****************************************************************************/
1729 static HRESULT WINAPI
1730 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1731 IDirect3DViewport3 *Direct3DViewport3)
1733 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1734 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(Direct3DViewport3);
1736 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1738 wined3d_mutex_lock();
1739 /* Do nothing if the specified viewport is the same as the current one */
1740 if (This->current_viewport == vp )
1742 wined3d_mutex_unlock();
1743 return D3D_OK;
1746 if (vp->active_device != This)
1748 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1749 wined3d_mutex_unlock();
1750 return DDERR_INVALIDPARAMS;
1753 /* Release previous viewport and AddRef the new one */
1754 if (This->current_viewport)
1756 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1757 &This->current_viewport->IDirect3DViewport3_iface);
1758 IDirect3DViewport3_Release(&This->current_viewport->IDirect3DViewport3_iface);
1760 IDirect3DViewport3_AddRef(Direct3DViewport3);
1762 /* Set this viewport as the current viewport */
1763 This->current_viewport = vp;
1765 /* Activate this viewport */
1766 viewport_activate(This->current_viewport, FALSE);
1768 wined3d_mutex_unlock();
1770 return D3D_OK;
1773 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1774 IDirect3DViewport2 *Direct3DViewport2)
1776 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1777 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
1779 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1781 return IDirect3DDevice3_SetCurrentViewport(&This->IDirect3DDevice3_iface,
1782 &vp->IDirect3DViewport3_iface);
1785 /*****************************************************************************
1786 * IDirect3DDevice3::GetCurrentViewport
1788 * Returns the currently active viewport.
1790 * Version 2 and 3
1792 * Params:
1793 * Direct3DViewport3: Address to return the interface pointer at
1795 * Returns:
1796 * D3D_OK on success
1797 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1799 *****************************************************************************/
1800 static HRESULT WINAPI
1801 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1802 IDirect3DViewport3 **Direct3DViewport3)
1804 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1806 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1808 if(!Direct3DViewport3)
1809 return DDERR_INVALIDPARAMS;
1811 wined3d_mutex_lock();
1812 *Direct3DViewport3 = &This->current_viewport->IDirect3DViewport3_iface;
1814 /* AddRef the returned viewport */
1815 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1817 TRACE(" returning interface %p\n", *Direct3DViewport3);
1819 wined3d_mutex_unlock();
1821 return D3D_OK;
1824 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1825 IDirect3DViewport2 **Direct3DViewport2)
1827 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1828 HRESULT hr;
1830 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1832 hr = IDirect3DDevice3_GetCurrentViewport(&This->IDirect3DDevice3_iface,
1833 (IDirect3DViewport3 **)Direct3DViewport2);
1834 if(hr != D3D_OK) return hr;
1835 return D3D_OK;
1838 /*****************************************************************************
1839 * IDirect3DDevice7::SetRenderTarget
1841 * Sets the render target for the Direct3DDevice.
1842 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1843 * IDirectDrawSurface3 == IDirectDrawSurface
1845 * Version 2, 3 and 7
1847 * Params:
1848 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1849 * render target
1850 * Flags: Some flags
1852 * Returns:
1853 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1855 *****************************************************************************/
1856 static HRESULT d3d_device_set_render_target(IDirect3DDeviceImpl *This, IDirectDrawSurfaceImpl *Target)
1858 HRESULT hr;
1860 wined3d_mutex_lock();
1862 if(This->target == Target)
1864 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1865 wined3d_mutex_unlock();
1866 return D3D_OK;
1868 This->target = Target;
1869 hr = wined3d_device_set_render_target(This->wined3d_device, 0,
1870 Target ? Target->wined3d_surface : NULL, FALSE);
1871 if(hr != D3D_OK)
1873 wined3d_mutex_unlock();
1874 return hr;
1876 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1878 wined3d_mutex_unlock();
1880 return D3D_OK;
1883 static HRESULT
1884 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1885 IDirectDrawSurface7 *NewTarget,
1886 DWORD Flags)
1888 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1889 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface7(NewTarget);
1891 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, Flags);
1892 /* Flags: Not used */
1894 IDirectDrawSurface7_AddRef(NewTarget);
1895 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
1896 return d3d_device_set_render_target(This, Target);
1899 static HRESULT WINAPI
1900 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1901 IDirectDrawSurface7 *NewTarget,
1902 DWORD Flags)
1904 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1907 static HRESULT WINAPI
1908 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1909 IDirectDrawSurface7 *NewTarget,
1910 DWORD Flags)
1912 HRESULT hr;
1913 WORD old_fpucw;
1915 old_fpucw = d3d_fpu_setup();
1916 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1917 set_fpu_control_word(old_fpucw);
1919 return hr;
1922 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
1923 IDirectDrawSurface4 *NewRenderTarget, DWORD Flags)
1925 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1926 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface4(NewRenderTarget);
1928 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1930 IDirectDrawSurface4_AddRef(NewRenderTarget);
1931 IDirectDrawSurface4_Release(&This->target->IDirectDrawSurface4_iface);
1932 return d3d_device_set_render_target(This, Target);
1935 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
1936 IDirectDrawSurface *NewRenderTarget, DWORD Flags)
1938 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1939 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface(NewRenderTarget);
1941 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1943 IDirectDrawSurface_AddRef(NewRenderTarget);
1944 IDirectDrawSurface_Release(&This->target->IDirectDrawSurface_iface);
1945 return d3d_device_set_render_target(This, Target);
1948 /*****************************************************************************
1949 * IDirect3DDevice7::GetRenderTarget
1951 * Returns the current render target.
1952 * This is handled locally, because the WineD3D render target's parent
1953 * is an IParent
1955 * Version 2, 3 and 7
1957 * Params:
1958 * RenderTarget: Address to store the surface interface pointer
1960 * Returns:
1961 * D3D_OK on success
1962 * DDERR_INVALIDPARAMS if RenderTarget == NULL
1964 *****************************************************************************/
1965 static HRESULT WINAPI
1966 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
1967 IDirectDrawSurface7 **RenderTarget)
1969 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1971 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1973 if(!RenderTarget)
1974 return DDERR_INVALIDPARAMS;
1976 wined3d_mutex_lock();
1977 *RenderTarget = &This->target->IDirectDrawSurface7_iface;
1978 IDirectDrawSurface7_AddRef(*RenderTarget);
1979 wined3d_mutex_unlock();
1981 return D3D_OK;
1984 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
1985 IDirectDrawSurface4 **RenderTarget)
1987 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1988 IDirectDrawSurface7 *RenderTarget7;
1989 IDirectDrawSurfaceImpl *RenderTargetImpl;
1990 HRESULT hr;
1992 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1994 if(!RenderTarget)
1995 return DDERR_INVALIDPARAMS;
1997 hr = IDirect3DDevice7_GetRenderTarget(&This->IDirect3DDevice7_iface, &RenderTarget7);
1998 if(hr != D3D_OK) return hr;
1999 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2000 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface;
2001 IDirectDrawSurface4_AddRef(*RenderTarget);
2002 IDirectDrawSurface7_Release(RenderTarget7);
2003 return D3D_OK;
2006 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
2007 IDirectDrawSurface **RenderTarget)
2009 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2010 IDirectDrawSurface7 *RenderTarget7;
2011 IDirectDrawSurfaceImpl *RenderTargetImpl;
2012 HRESULT hr;
2014 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2016 if(!RenderTarget)
2017 return DDERR_INVALIDPARAMS;
2019 hr = IDirect3DDevice7_GetRenderTarget(&This->IDirect3DDevice7_iface, &RenderTarget7);
2020 if(hr != D3D_OK) return hr;
2021 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2022 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
2023 IDirectDrawSurface_AddRef(*RenderTarget);
2024 IDirectDrawSurface7_Release(RenderTarget7);
2025 return D3D_OK;
2028 /*****************************************************************************
2029 * IDirect3DDevice3::Begin
2031 * Begins a description block of vertices. This is similar to glBegin()
2032 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2033 * described with IDirect3DDevice::Vertex are drawn.
2035 * Version 2 and 3
2037 * Params:
2038 * PrimitiveType: The type of primitives to draw
2039 * VertexTypeDesc: A flexible vertex format description of the vertices
2040 * Flags: Some flags..
2042 * Returns:
2043 * D3D_OK on success
2045 *****************************************************************************/
2046 static HRESULT WINAPI
2047 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2048 D3DPRIMITIVETYPE PrimitiveType,
2049 DWORD VertexTypeDesc,
2050 DWORD Flags)
2052 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2054 TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
2055 iface, PrimitiveType, VertexTypeDesc, Flags);
2057 wined3d_mutex_lock();
2058 This->primitive_type = PrimitiveType;
2059 This->vertex_type = VertexTypeDesc;
2060 This->render_flags = Flags;
2061 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2062 This->nb_vertices = 0;
2063 wined3d_mutex_unlock();
2065 return D3D_OK;
2068 static HRESULT WINAPI IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface, D3DPRIMITIVETYPE d3dpt,
2069 D3DVERTEXTYPE dwVertexTypeDesc, DWORD dwFlags)
2071 DWORD FVF;
2072 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2074 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2075 iface, d3dpt, dwVertexTypeDesc, dwFlags);
2077 switch(dwVertexTypeDesc)
2079 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2080 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2081 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2082 default:
2083 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2084 return DDERR_INVALIDPARAMS; /* Should never happen */
2087 return IDirect3DDevice3_Begin(&This->IDirect3DDevice3_iface, d3dpt, FVF, dwFlags);
2090 /*****************************************************************************
2091 * IDirect3DDevice3::BeginIndexed
2093 * Draws primitives based on vertices in a vertex array which are specified
2094 * by indices.
2096 * Version 2 and 3
2098 * Params:
2099 * PrimitiveType: Primitive type to draw
2100 * VertexType: A FVF description of the vertex format
2101 * Vertices: pointer to an array containing the vertices
2102 * NumVertices: The number of vertices in the vertex array
2103 * Flags: Some flags ...
2105 * Returns:
2106 * D3D_OK, because it's a stub
2108 *****************************************************************************/
2109 static HRESULT WINAPI
2110 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2111 D3DPRIMITIVETYPE PrimitiveType,
2112 DWORD VertexType,
2113 void *Vertices,
2114 DWORD NumVertices,
2115 DWORD Flags)
2117 FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2118 iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2120 return D3D_OK;
2124 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2125 D3DPRIMITIVETYPE d3dptPrimitiveType, D3DVERTEXTYPE d3dvtVertexType,
2126 void *lpvVertices, DWORD dwNumVertices, DWORD dwFlags)
2128 DWORD FVF;
2129 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2131 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2132 iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2134 switch(d3dvtVertexType)
2136 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2137 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2138 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2139 default:
2140 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2141 return DDERR_INVALIDPARAMS; /* Should never happen */
2144 return IDirect3DDevice3_BeginIndexed(&This->IDirect3DDevice3_iface,
2145 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2148 /*****************************************************************************
2149 * IDirect3DDevice3::Vertex
2151 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2152 * drawn vertices in a vertex buffer. If the buffer is too small, its
2153 * size is increased.
2155 * Version 2 and 3
2157 * Params:
2158 * Vertex: Pointer to the vertex
2160 * Returns:
2161 * D3D_OK, on success
2162 * DDERR_INVALIDPARAMS if Vertex is NULL
2164 *****************************************************************************/
2165 static HRESULT WINAPI
2166 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2167 void *Vertex)
2169 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2171 TRACE("iface %p, vertex %p.\n", iface, Vertex);
2173 if(!Vertex)
2174 return DDERR_INVALIDPARAMS;
2176 wined3d_mutex_lock();
2177 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2179 BYTE *old_buffer;
2180 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2181 old_buffer = This->vertex_buffer;
2182 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2183 if (old_buffer)
2185 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2186 HeapFree(GetProcessHeap(), 0, old_buffer);
2190 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2191 wined3d_mutex_unlock();
2193 return D3D_OK;
2196 static HRESULT WINAPI IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface, void *lpVertexType)
2198 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2200 TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
2202 return IDirect3DDevice3_Vertex(&This->IDirect3DDevice3_iface, lpVertexType);
2205 /*****************************************************************************
2206 * IDirect3DDevice3::Index
2208 * Specifies an index to a vertex to be drawn. The vertex array has to
2209 * be specified with BeginIndexed first.
2211 * Parameters:
2212 * VertexIndex: The index of the vertex to draw
2214 * Returns:
2215 * D3D_OK because it's a stub
2217 *****************************************************************************/
2218 static HRESULT WINAPI
2219 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2220 WORD VertexIndex)
2222 FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
2224 return D3D_OK;
2227 static HRESULT WINAPI IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface, WORD wVertexIndex)
2229 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2231 TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
2233 return IDirect3DDevice3_Index(&This->IDirect3DDevice3_iface, wVertexIndex);
2236 /*****************************************************************************
2237 * IDirect3DDevice3::End
2239 * Ends a draw begun with IDirect3DDevice3::Begin or
2240 * IDirect3DDevice::BeginIndexed. The vertices specified with
2241 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2242 * the IDirect3DDevice7::DrawPrimitive method. So far only
2243 * non-indexed mode is supported
2245 * Version 2 and 3
2247 * Params:
2248 * Flags: Some flags, as usual. Don't know which are defined
2250 * Returns:
2251 * The return value of IDirect3DDevice7::DrawPrimitive
2253 *****************************************************************************/
2254 static HRESULT WINAPI
2255 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2256 DWORD Flags)
2258 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2260 TRACE("iface %p, flags %#x.\n", iface, Flags);
2262 return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface, This->primitive_type,
2263 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2266 static HRESULT WINAPI IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface, DWORD dwFlags)
2268 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2270 TRACE("iface %p, flags %#x.\n", iface, dwFlags);
2272 return IDirect3DDevice3_End(&This->IDirect3DDevice3_iface, dwFlags);
2275 /*****************************************************************************
2276 * IDirect3DDevice7::GetRenderState
2278 * Returns the value of a render state. The possible render states are
2279 * defined in include/d3dtypes.h
2281 * Version 2, 3 and 7
2283 * Params:
2284 * RenderStateType: Render state to return the current setting of
2285 * Value: Address to store the value at
2287 * Returns:
2288 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2289 * DDERR_INVALIDPARAMS if Value == NULL
2291 *****************************************************************************/
2292 static HRESULT IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2293 D3DRENDERSTATETYPE RenderStateType, DWORD *Value)
2295 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
2296 HRESULT hr;
2298 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2300 if(!Value)
2301 return DDERR_INVALIDPARAMS;
2303 wined3d_mutex_lock();
2304 switch(RenderStateType)
2306 case D3DRENDERSTATE_TEXTUREMAG:
2308 WINED3DTEXTUREFILTERTYPE tex_mag;
2310 hr = wined3d_device_get_sampler_state(This->wined3d_device, 0, WINED3DSAMP_MAGFILTER, &tex_mag);
2312 switch (tex_mag)
2314 case WINED3DTEXF_POINT:
2315 *Value = D3DFILTER_NEAREST;
2316 break;
2317 case WINED3DTEXF_LINEAR:
2318 *Value = D3DFILTER_LINEAR;
2319 break;
2320 default:
2321 ERR("Unhandled texture mag %d !\n",tex_mag);
2322 *Value = 0;
2324 break;
2327 case D3DRENDERSTATE_TEXTUREMIN:
2329 WINED3DTEXTUREFILTERTYPE tex_min;
2330 WINED3DTEXTUREFILTERTYPE tex_mip;
2332 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2333 0, WINED3DSAMP_MINFILTER, &tex_min);
2334 if (FAILED(hr))
2336 wined3d_mutex_unlock();
2337 return hr;
2339 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2340 0, WINED3DSAMP_MIPFILTER, &tex_mip);
2342 switch (tex_min)
2344 case WINED3DTEXF_POINT:
2345 switch (tex_mip)
2347 case WINED3DTEXF_NONE:
2348 *Value = D3DFILTER_NEAREST;
2349 break;
2350 case WINED3DTEXF_POINT:
2351 *Value = D3DFILTER_MIPNEAREST;
2352 break;
2353 case WINED3DTEXF_LINEAR:
2354 *Value = D3DFILTER_LINEARMIPNEAREST;
2355 break;
2356 default:
2357 ERR("Unhandled mip filter %#x.\n", tex_mip);
2358 *Value = D3DFILTER_NEAREST;
2359 break;
2361 break;
2362 case WINED3DTEXF_LINEAR:
2363 switch (tex_mip)
2365 case WINED3DTEXF_NONE:
2366 *Value = D3DFILTER_LINEAR;
2367 break;
2368 case WINED3DTEXF_POINT:
2369 *Value = D3DFILTER_MIPLINEAR;
2370 break;
2371 case WINED3DTEXF_LINEAR:
2372 *Value = D3DFILTER_LINEARMIPLINEAR;
2373 break;
2374 default:
2375 ERR("Unhandled mip filter %#x.\n", tex_mip);
2376 *Value = D3DFILTER_LINEAR;
2377 break;
2379 break;
2380 default:
2381 ERR("Unhandled texture min filter %#x.\n",tex_min);
2382 *Value = D3DFILTER_NEAREST;
2383 break;
2385 break;
2388 case D3DRENDERSTATE_TEXTUREADDRESS:
2389 case D3DRENDERSTATE_TEXTUREADDRESSU:
2390 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2391 0, WINED3DSAMP_ADDRESSU, Value);
2392 break;
2393 case D3DRENDERSTATE_TEXTUREADDRESSV:
2394 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2395 0, WINED3DSAMP_ADDRESSV, Value);
2396 break;
2398 case D3DRENDERSTATE_BORDERCOLOR:
2399 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2400 hr = E_NOTIMPL;
2401 break;
2403 case D3DRENDERSTATE_TEXTUREHANDLE:
2404 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2405 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2406 hr = DDERR_INVALIDPARAMS;
2407 break;
2409 case D3DRENDERSTATE_ZBIAS:
2410 hr = wined3d_device_get_render_state(This->wined3d_device, WINED3DRS_DEPTHBIAS, Value);
2411 break;
2413 default:
2414 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2415 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2417 FIXME("Unhandled stipple pattern render state (%#x).\n",
2418 RenderStateType);
2419 hr = E_NOTIMPL;
2420 break;
2422 hr = wined3d_device_get_render_state(This->wined3d_device, RenderStateType, Value);
2424 wined3d_mutex_unlock();
2426 return hr;
2429 static HRESULT WINAPI
2430 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2431 D3DRENDERSTATETYPE RenderStateType,
2432 DWORD *Value)
2434 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2437 static HRESULT WINAPI
2438 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2439 D3DRENDERSTATETYPE RenderStateType,
2440 DWORD *Value)
2442 HRESULT hr;
2443 WORD old_fpucw;
2445 old_fpucw = d3d_fpu_setup();
2446 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2447 set_fpu_control_word(old_fpucw);
2449 return hr;
2452 static HRESULT WINAPI
2453 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2454 D3DRENDERSTATETYPE dwRenderStateType,
2455 DWORD *lpdwRenderState)
2457 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2458 HRESULT hr;
2460 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2462 switch(dwRenderStateType)
2464 case D3DRENDERSTATE_TEXTUREHANDLE:
2466 /* This state is wrapped to SetTexture in SetRenderState, so
2467 * it has to be wrapped to GetTexture here. */
2468 struct wined3d_texture *tex = NULL;
2469 *lpdwRenderState = 0;
2471 wined3d_mutex_lock();
2472 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2473 if (SUCCEEDED(hr) && tex)
2475 /* The parent of the texture is the IDirectDrawSurface7
2476 * interface of the ddraw surface. */
2477 IDirectDrawSurfaceImpl *parent = wined3d_texture_get_parent(tex);
2478 if (parent) *lpdwRenderState = parent->Handle;
2479 wined3d_texture_decref(tex);
2481 wined3d_mutex_unlock();
2483 return hr;
2486 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2488 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2489 the mapping to get the value. */
2490 DWORD colorop, colorarg1, colorarg2;
2491 DWORD alphaop, alphaarg1, alphaarg2;
2493 wined3d_mutex_lock();
2495 This->legacyTextureBlending = TRUE;
2497 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLOROP, &colorop);
2498 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLORARG1, &colorarg1);
2499 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLORARG2, &colorarg2);
2500 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, &alphaop);
2501 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2502 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2504 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2505 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2507 *lpdwRenderState = D3DTBLEND_DECAL;
2509 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2510 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2512 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2514 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2515 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2517 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2519 else
2521 struct wined3d_texture *tex = NULL;
2522 HRESULT hr;
2523 BOOL tex_alpha = FALSE;
2524 DDPIXELFORMAT ddfmt;
2526 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2528 if(hr == WINED3D_OK && tex)
2530 struct wined3d_resource *sub_resource;
2532 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2534 struct wined3d_resource_desc desc;
2536 wined3d_resource_get_desc(sub_resource, &desc);
2537 ddfmt.dwSize = sizeof(ddfmt);
2538 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2539 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2542 wined3d_texture_decref(tex);
2545 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2546 alphaop == (tex_alpha ? WINED3DTOP_SELECTARG1 : WINED3DTOP_SELECTARG2) &&
2547 alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2549 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2552 *lpdwRenderState = D3DTBLEND_MODULATE;
2555 wined3d_mutex_unlock();
2557 return D3D_OK;
2560 default:
2561 return IDirect3DDevice7_GetRenderState(&This->IDirect3DDevice7_iface, dwRenderStateType, lpdwRenderState);
2565 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2566 D3DRENDERSTATETYPE dwRenderStateType, DWORD *lpdwRenderState)
2568 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2570 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2572 return IDirect3DDevice3_GetRenderState(&This->IDirect3DDevice3_iface,
2573 dwRenderStateType, lpdwRenderState);
2576 /*****************************************************************************
2577 * IDirect3DDevice7::SetRenderState
2579 * Sets a render state. The possible render states are defined in
2580 * include/d3dtypes.h
2582 * Version 2, 3 and 7
2584 * Params:
2585 * RenderStateType: State to set
2586 * Value: Value to assign to that state
2588 * Returns:
2589 * D3D_OK on success,
2590 * for details see IWineD3DDevice::SetRenderState
2592 *****************************************************************************/
2593 static HRESULT
2594 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2595 D3DRENDERSTATETYPE RenderStateType,
2596 DWORD Value)
2598 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
2599 HRESULT hr;
2601 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2603 wined3d_mutex_lock();
2604 /* Some render states need special care */
2605 switch(RenderStateType)
2608 * The ddraw texture filter mapping works like this:
2609 * D3DFILTER_NEAREST Point min/mag, no mip
2610 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2611 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2613 * D3DFILTER_LINEAR Linear min/mag, no mip
2614 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2615 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2617 * This is the opposite of the GL naming convention,
2618 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2620 case D3DRENDERSTATE_TEXTUREMAG:
2622 WINED3DTEXTUREFILTERTYPE tex_mag;
2624 switch (Value)
2626 case D3DFILTER_NEAREST:
2627 case D3DFILTER_MIPNEAREST:
2628 case D3DFILTER_LINEARMIPNEAREST:
2629 tex_mag = WINED3DTEXF_POINT;
2630 break;
2631 case D3DFILTER_LINEAR:
2632 case D3DFILTER_MIPLINEAR:
2633 case D3DFILTER_LINEARMIPLINEAR:
2634 tex_mag = WINED3DTEXF_LINEAR;
2635 break;
2636 default:
2637 tex_mag = WINED3DTEXF_POINT;
2638 ERR("Unhandled texture mag %d !\n",Value);
2639 break;
2642 hr = wined3d_device_set_sampler_state(This->wined3d_device, 0, WINED3DSAMP_MAGFILTER, tex_mag);
2643 break;
2646 case D3DRENDERSTATE_TEXTUREMIN:
2648 WINED3DTEXTUREFILTERTYPE tex_min;
2649 WINED3DTEXTUREFILTERTYPE tex_mip;
2651 switch ((D3DTEXTUREFILTER) Value)
2653 case D3DFILTER_NEAREST:
2654 tex_min = WINED3DTEXF_POINT;
2655 tex_mip = WINED3DTEXF_NONE;
2656 break;
2657 case D3DFILTER_LINEAR:
2658 tex_min = WINED3DTEXF_LINEAR;
2659 tex_mip = WINED3DTEXF_NONE;
2660 break;
2661 case D3DFILTER_MIPNEAREST:
2662 tex_min = WINED3DTEXF_POINT;
2663 tex_mip = WINED3DTEXF_POINT;
2664 break;
2665 case D3DFILTER_MIPLINEAR:
2666 tex_min = WINED3DTEXF_LINEAR;
2667 tex_mip = WINED3DTEXF_POINT;
2668 break;
2669 case D3DFILTER_LINEARMIPNEAREST:
2670 tex_min = WINED3DTEXF_POINT;
2671 tex_mip = WINED3DTEXF_LINEAR;
2672 break;
2673 case D3DFILTER_LINEARMIPLINEAR:
2674 tex_min = WINED3DTEXF_LINEAR;
2675 tex_mip = WINED3DTEXF_LINEAR;
2676 break;
2678 default:
2679 ERR("Unhandled texture min %d !\n",Value);
2680 tex_min = WINED3DTEXF_POINT;
2681 tex_mip = WINED3DTEXF_NONE;
2682 break;
2685 wined3d_device_set_sampler_state(This->wined3d_device,
2686 0, WINED3DSAMP_MIPFILTER, tex_mip);
2687 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2688 0, WINED3DSAMP_MINFILTER, tex_min);
2689 break;
2692 case D3DRENDERSTATE_TEXTUREADDRESS:
2693 wined3d_device_set_sampler_state(This->wined3d_device,
2694 0, WINED3DSAMP_ADDRESSV, Value);
2695 /* Drop through */
2696 case D3DRENDERSTATE_TEXTUREADDRESSU:
2697 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2698 0, WINED3DSAMP_ADDRESSU, Value);
2699 break;
2700 case D3DRENDERSTATE_TEXTUREADDRESSV:
2701 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2702 0, WINED3DSAMP_ADDRESSV, Value);
2703 break;
2705 case D3DRENDERSTATE_BORDERCOLOR:
2706 /* This should probably just forward to the corresponding sampler
2707 * state. Needs tests. */
2708 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2709 hr = E_NOTIMPL;
2710 break;
2712 case D3DRENDERSTATE_TEXTUREHANDLE:
2713 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2714 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2715 hr = DDERR_INVALIDPARAMS;
2716 break;
2718 case D3DRENDERSTATE_ZBIAS:
2719 hr = wined3d_device_set_render_state(This->wined3d_device, WINED3DRS_DEPTHBIAS, Value);
2720 break;
2722 default:
2723 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2724 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2726 FIXME("Unhandled stipple pattern render state (%#x).\n",
2727 RenderStateType);
2728 hr = E_NOTIMPL;
2729 break;
2732 hr = wined3d_device_set_render_state(This->wined3d_device, RenderStateType, Value);
2733 break;
2735 wined3d_mutex_unlock();
2737 return hr;
2740 static HRESULT WINAPI
2741 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2742 D3DRENDERSTATETYPE RenderStateType,
2743 DWORD Value)
2745 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2748 static HRESULT WINAPI
2749 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2750 D3DRENDERSTATETYPE RenderStateType,
2751 DWORD Value)
2753 HRESULT hr;
2754 WORD old_fpucw;
2756 old_fpucw = d3d_fpu_setup();
2757 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2758 set_fpu_control_word(old_fpucw);
2760 return hr;
2763 static HRESULT WINAPI
2764 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2765 D3DRENDERSTATETYPE RenderStateType,
2766 DWORD Value)
2768 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2769 for this state can be directly mapped to texture stage colorop and alphaop, but
2770 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2771 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2772 alphaarg when needed.
2774 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2776 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2777 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2778 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2779 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2780 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2781 in device - TRUE if the app is using TEXTUREMAPBLEND.
2783 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2784 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2785 unless some broken game will be found that cares. */
2787 HRESULT hr;
2788 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2790 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2792 wined3d_mutex_lock();
2794 switch(RenderStateType)
2796 case D3DRENDERSTATE_TEXTUREHANDLE:
2798 IDirectDrawSurfaceImpl *surf;
2800 if(Value == 0)
2802 hr = wined3d_device_set_texture(This->wined3d_device, 0, NULL);
2803 break;
2806 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2807 if (!surf)
2809 WARN("Invalid texture handle.\n");
2810 hr = DDERR_INVALIDPARAMS;
2811 break;
2814 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2815 break;
2818 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2820 This->legacyTextureBlending = TRUE;
2822 switch ( (D3DTEXTUREBLEND) Value)
2824 case D3DTBLEND_MODULATE:
2826 struct wined3d_texture *tex = NULL;
2827 BOOL tex_alpha = FALSE;
2828 DDPIXELFORMAT ddfmt;
2830 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2832 if(hr == WINED3D_OK && tex)
2834 struct wined3d_resource *sub_resource;
2836 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2838 struct wined3d_resource_desc desc;
2840 wined3d_resource_get_desc(sub_resource, &desc);
2841 ddfmt.dwSize = sizeof(ddfmt);
2842 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2843 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2846 wined3d_texture_decref(tex);
2849 if (tex_alpha)
2850 wined3d_device_set_texture_stage_state(This->wined3d_device,
2851 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2852 else
2853 wined3d_device_set_texture_stage_state(This->wined3d_device,
2854 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2855 wined3d_device_set_texture_stage_state(This->wined3d_device,
2856 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2857 wined3d_device_set_texture_stage_state(This->wined3d_device,
2858 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2859 wined3d_device_set_texture_stage_state(This->wined3d_device,
2860 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2861 wined3d_device_set_texture_stage_state(This->wined3d_device,
2862 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2863 wined3d_device_set_texture_stage_state(This->wined3d_device,
2864 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2865 break;
2868 case D3DTBLEND_ADD:
2869 wined3d_device_set_texture_stage_state(This->wined3d_device,
2870 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2871 wined3d_device_set_texture_stage_state(This->wined3d_device,
2872 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2873 wined3d_device_set_texture_stage_state(This->wined3d_device,
2874 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2875 wined3d_device_set_texture_stage_state(This->wined3d_device,
2876 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2877 wined3d_device_set_texture_stage_state(This->wined3d_device,
2878 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2879 break;
2881 case D3DTBLEND_MODULATEALPHA:
2882 wined3d_device_set_texture_stage_state(This->wined3d_device,
2883 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2884 wined3d_device_set_texture_stage_state(This->wined3d_device,
2885 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2886 wined3d_device_set_texture_stage_state(This->wined3d_device,
2887 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2888 wined3d_device_set_texture_stage_state(This->wined3d_device,
2889 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2890 wined3d_device_set_texture_stage_state(This->wined3d_device,
2891 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2892 wined3d_device_set_texture_stage_state(This->wined3d_device,
2893 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2894 break;
2896 case D3DTBLEND_COPY:
2897 case D3DTBLEND_DECAL:
2898 wined3d_device_set_texture_stage_state(This->wined3d_device,
2899 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2900 wined3d_device_set_texture_stage_state(This->wined3d_device,
2901 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2902 wined3d_device_set_texture_stage_state(This->wined3d_device,
2903 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2904 wined3d_device_set_texture_stage_state(This->wined3d_device,
2905 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2906 break;
2908 case D3DTBLEND_DECALALPHA:
2909 wined3d_device_set_texture_stage_state(This->wined3d_device,
2910 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2911 wined3d_device_set_texture_stage_state(This->wined3d_device,
2912 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2913 wined3d_device_set_texture_stage_state(This->wined3d_device,
2914 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2915 wined3d_device_set_texture_stage_state(This->wined3d_device,
2916 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2917 wined3d_device_set_texture_stage_state(This->wined3d_device,
2918 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2919 break;
2921 default:
2922 ERR("Unhandled texture environment %d !\n",Value);
2925 hr = D3D_OK;
2926 break;
2929 default:
2930 hr = IDirect3DDevice7_SetRenderState(&This->IDirect3DDevice7_iface, RenderStateType, Value);
2931 break;
2933 wined3d_mutex_unlock();
2935 return hr;
2938 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2939 D3DRENDERSTATETYPE RenderStateType, DWORD Value)
2941 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2943 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2945 return IDirect3DDevice3_SetRenderState(&This->IDirect3DDevice3_iface, RenderStateType, Value);
2948 /*****************************************************************************
2949 * Direct3DDevice3::SetLightState
2951 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2952 * light states are forwarded to Direct3DDevice7 render states
2954 * Version 2 and 3
2956 * Params:
2957 * LightStateType: The light state to change
2958 * Value: The value to assign to that light state
2960 * Returns:
2961 * D3D_OK on success
2962 * DDERR_INVALIDPARAMS if the parameters were incorrect
2963 * Also check IDirect3DDevice7::SetRenderState
2965 *****************************************************************************/
2966 static HRESULT WINAPI
2967 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
2968 D3DLIGHTSTATETYPE LightStateType,
2969 DWORD Value)
2971 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2972 HRESULT hr;
2974 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
2976 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2978 TRACE("Unexpected Light State Type\n");
2979 return DDERR_INVALIDPARAMS;
2982 wined3d_mutex_lock();
2983 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
2985 IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
2986 if (!m)
2988 WARN("Invalid material handle.\n");
2989 wined3d_mutex_unlock();
2990 return DDERR_INVALIDPARAMS;
2993 TRACE(" activating material %p.\n", m);
2994 material_activate(m);
2996 This->material = Value;
2998 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3000 switch (Value)
3002 case D3DCOLOR_MONO:
3003 ERR("DDCOLOR_MONO should not happen!\n");
3004 break;
3005 case D3DCOLOR_RGB:
3006 /* We are already in this mode */
3007 TRACE("Setting color model to RGB (no-op).\n");
3008 break;
3009 default:
3010 ERR("Unknown color model!\n");
3011 wined3d_mutex_unlock();
3012 return DDERR_INVALIDPARAMS;
3015 else
3017 D3DRENDERSTATETYPE rs;
3018 switch (LightStateType)
3020 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3021 rs = D3DRENDERSTATE_AMBIENT;
3022 break;
3023 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3024 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3025 break;
3026 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3027 rs = D3DRENDERSTATE_FOGSTART;
3028 break;
3029 case D3DLIGHTSTATE_FOGEND: /* 6 */
3030 rs = D3DRENDERSTATE_FOGEND;
3031 break;
3032 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3033 rs = D3DRENDERSTATE_FOGDENSITY;
3034 break;
3035 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3036 rs = D3DRENDERSTATE_COLORVERTEX;
3037 break;
3038 default:
3039 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3040 wined3d_mutex_unlock();
3041 return DDERR_INVALIDPARAMS;
3044 hr = IDirect3DDevice7_SetRenderState(&This->IDirect3DDevice7_iface, rs, Value);
3045 wined3d_mutex_unlock();
3046 return hr;
3048 wined3d_mutex_unlock();
3050 return D3D_OK;
3053 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3054 D3DLIGHTSTATETYPE LightStateType, DWORD Value)
3056 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3058 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3060 return IDirect3DDevice3_SetLightState(&This->IDirect3DDevice3_iface, LightStateType, Value);
3063 /*****************************************************************************
3064 * IDirect3DDevice3::GetLightState
3066 * Returns the current setting of a light state. The state is read from
3067 * the Direct3DDevice7 render state.
3069 * Version 2 and 3
3071 * Params:
3072 * LightStateType: The light state to return
3073 * Value: The address to store the light state setting at
3075 * Returns:
3076 * D3D_OK on success
3077 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3078 * Also see IDirect3DDevice7::GetRenderState
3080 *****************************************************************************/
3081 static HRESULT WINAPI
3082 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3083 D3DLIGHTSTATETYPE LightStateType,
3084 DWORD *Value)
3086 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3087 HRESULT hr;
3089 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3091 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3093 TRACE("Unexpected Light State Type\n");
3094 return DDERR_INVALIDPARAMS;
3097 if(!Value)
3098 return DDERR_INVALIDPARAMS;
3100 wined3d_mutex_lock();
3101 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3103 *Value = This->material;
3105 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3107 *Value = D3DCOLOR_RGB;
3109 else
3111 D3DRENDERSTATETYPE rs;
3112 switch (LightStateType)
3114 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3115 rs = D3DRENDERSTATE_AMBIENT;
3116 break;
3117 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3118 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3119 break;
3120 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3121 rs = D3DRENDERSTATE_FOGSTART;
3122 break;
3123 case D3DLIGHTSTATE_FOGEND: /* 6 */
3124 rs = D3DRENDERSTATE_FOGEND;
3125 break;
3126 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3127 rs = D3DRENDERSTATE_FOGDENSITY;
3128 break;
3129 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3130 rs = D3DRENDERSTATE_COLORVERTEX;
3131 break;
3132 default:
3133 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3134 wined3d_mutex_unlock();
3135 return DDERR_INVALIDPARAMS;
3138 hr = IDirect3DDevice7_GetRenderState(&This->IDirect3DDevice7_iface, rs, Value);
3139 wined3d_mutex_unlock();
3140 return hr;
3142 wined3d_mutex_unlock();
3144 return D3D_OK;
3147 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3148 D3DLIGHTSTATETYPE LightStateType, DWORD *Value)
3150 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3152 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3154 return IDirect3DDevice3_GetLightState(&This->IDirect3DDevice3_iface, LightStateType, Value);
3157 /*****************************************************************************
3158 * IDirect3DDevice7::SetTransform
3160 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3161 * in include/d3dtypes.h.
3162 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3163 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3164 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3166 * Version 2, 3 and 7
3168 * Params:
3169 * TransformStateType: transform state to set
3170 * Matrix: Matrix to assign to the state
3172 * Returns:
3173 * D3D_OK on success
3174 * DDERR_INVALIDPARAMS if Matrix == NULL
3175 * For details see IWineD3DDevice::SetTransform
3177 *****************************************************************************/
3178 static HRESULT
3179 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3180 D3DTRANSFORMSTATETYPE TransformStateType,
3181 D3DMATRIX *Matrix)
3183 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3184 D3DTRANSFORMSTATETYPE type;
3185 HRESULT hr;
3187 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3189 switch(TransformStateType)
3191 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3192 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3193 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3194 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3195 default: type = TransformStateType;
3198 if (!Matrix)
3199 return DDERR_INVALIDPARAMS;
3201 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3202 wined3d_mutex_lock();
3203 hr = wined3d_device_set_transform(This->wined3d_device, type, (WINED3DMATRIX *)Matrix);
3204 wined3d_mutex_unlock();
3206 return hr;
3209 static HRESULT WINAPI
3210 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3211 D3DTRANSFORMSTATETYPE TransformStateType,
3212 D3DMATRIX *Matrix)
3214 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3217 static HRESULT WINAPI
3218 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3219 D3DTRANSFORMSTATETYPE TransformStateType,
3220 D3DMATRIX *Matrix)
3222 HRESULT hr;
3223 WORD old_fpucw;
3225 old_fpucw = d3d_fpu_setup();
3226 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3227 set_fpu_control_word(old_fpucw);
3229 return hr;
3232 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3233 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3235 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3237 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3239 return IDirect3DDevice7_SetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3242 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3243 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3245 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3247 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3249 return IDirect3DDevice7_SetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3252 /*****************************************************************************
3253 * IDirect3DDevice7::GetTransform
3255 * Returns the matrix assigned to a transform state
3256 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3257 * SetTransform
3259 * Params:
3260 * TransformStateType: State to read the matrix from
3261 * Matrix: Address to store the matrix at
3263 * Returns:
3264 * D3D_OK on success
3265 * DDERR_INVALIDPARAMS if Matrix == NULL
3266 * For details, see IWineD3DDevice::GetTransform
3268 *****************************************************************************/
3269 static HRESULT
3270 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3271 D3DTRANSFORMSTATETYPE TransformStateType,
3272 D3DMATRIX *Matrix)
3274 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3275 D3DTRANSFORMSTATETYPE type;
3276 HRESULT hr;
3278 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3280 switch(TransformStateType)
3282 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3283 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3284 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3285 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3286 default: type = TransformStateType;
3289 if(!Matrix)
3290 return DDERR_INVALIDPARAMS;
3292 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3293 wined3d_mutex_lock();
3294 hr = wined3d_device_get_transform(This->wined3d_device, type, (WINED3DMATRIX *)Matrix);
3295 wined3d_mutex_unlock();
3297 return hr;
3300 static HRESULT WINAPI
3301 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3302 D3DTRANSFORMSTATETYPE TransformStateType,
3303 D3DMATRIX *Matrix)
3305 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3308 static HRESULT WINAPI
3309 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3310 D3DTRANSFORMSTATETYPE TransformStateType,
3311 D3DMATRIX *Matrix)
3313 HRESULT hr;
3314 WORD old_fpucw;
3316 old_fpucw = d3d_fpu_setup();
3317 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3318 set_fpu_control_word(old_fpucw);
3320 return hr;
3323 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3324 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3326 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3328 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3330 return IDirect3DDevice7_GetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3333 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3334 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3336 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3338 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3340 return IDirect3DDevice7_GetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3343 /*****************************************************************************
3344 * IDirect3DDevice7::MultiplyTransform
3346 * Multiplies the already-set transform matrix of a transform state
3347 * with another matrix. For the world matrix, see SetTransform
3349 * Version 2, 3 and 7
3351 * Params:
3352 * TransformStateType: Transform state to multiply
3353 * D3DMatrix Matrix to multiply with.
3355 * Returns
3356 * D3D_OK on success
3357 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3358 * For details, see IWineD3DDevice::MultiplyTransform
3360 *****************************************************************************/
3361 static HRESULT
3362 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3363 D3DTRANSFORMSTATETYPE TransformStateType,
3364 D3DMATRIX *D3DMatrix)
3366 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3367 HRESULT hr;
3368 D3DTRANSFORMSTATETYPE type;
3370 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3372 switch(TransformStateType)
3374 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3375 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3376 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3377 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3378 default: type = TransformStateType;
3381 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3382 wined3d_mutex_lock();
3383 hr = wined3d_device_multiply_transform(This->wined3d_device,
3384 type, (WINED3DMATRIX *)D3DMatrix);
3385 wined3d_mutex_unlock();
3387 return hr;
3390 static HRESULT WINAPI
3391 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3392 D3DTRANSFORMSTATETYPE TransformStateType,
3393 D3DMATRIX *D3DMatrix)
3395 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3398 static HRESULT WINAPI
3399 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3400 D3DTRANSFORMSTATETYPE TransformStateType,
3401 D3DMATRIX *D3DMatrix)
3403 HRESULT hr;
3404 WORD old_fpucw;
3406 old_fpucw = d3d_fpu_setup();
3407 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3408 set_fpu_control_word(old_fpucw);
3410 return hr;
3413 static HRESULT WINAPI IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3414 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3416 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3418 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3420 return IDirect3DDevice7_MultiplyTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3423 static HRESULT WINAPI IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3424 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3426 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3428 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3430 return IDirect3DDevice7_MultiplyTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3433 /*****************************************************************************
3434 * IDirect3DDevice7::DrawPrimitive
3436 * Draws primitives based on vertices in an application-provided pointer
3438 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3439 * an FVF format for D3D7
3441 * Params:
3442 * PrimitiveType: The type of the primitives to draw
3443 * Vertex type: Flexible vertex format vertex description
3444 * Vertices: Pointer to the vertex array
3445 * VertexCount: The number of vertices to draw
3446 * Flags: As usual a few flags
3448 * Returns:
3449 * D3D_OK on success
3450 * DDERR_INVALIDPARAMS if Vertices is NULL
3451 * For details, see IWineD3DDevice::DrawPrimitiveUP
3453 *****************************************************************************/
3454 static HRESULT
3455 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3456 D3DPRIMITIVETYPE PrimitiveType,
3457 DWORD VertexType,
3458 void *Vertices,
3459 DWORD VertexCount,
3460 DWORD Flags)
3462 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3463 UINT stride;
3464 HRESULT hr;
3466 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3467 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3469 if(!Vertices)
3470 return DDERR_INVALIDPARAMS;
3472 /* Get the stride */
3473 stride = get_flexible_vertex_size(VertexType);
3475 /* Set the FVF */
3476 wined3d_mutex_lock();
3477 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3478 if(hr != D3D_OK)
3480 wined3d_mutex_unlock();
3481 return hr;
3484 /* This method translates to the user pointer draw of WineD3D */
3485 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3486 hr = wined3d_device_draw_primitive_up(This->wined3d_device, VertexCount, Vertices, stride);
3487 wined3d_mutex_unlock();
3489 return hr;
3492 static HRESULT WINAPI
3493 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3494 D3DPRIMITIVETYPE PrimitiveType,
3495 DWORD VertexType,
3496 void *Vertices,
3497 DWORD VertexCount,
3498 DWORD Flags)
3500 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3503 static HRESULT WINAPI
3504 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3505 D3DPRIMITIVETYPE PrimitiveType,
3506 DWORD VertexType,
3507 void *Vertices,
3508 DWORD VertexCount,
3509 DWORD Flags)
3511 HRESULT hr;
3512 WORD old_fpucw;
3514 old_fpucw = d3d_fpu_setup();
3515 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3516 set_fpu_control_word(old_fpucw);
3518 return hr;
3521 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3522 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3523 DWORD Flags)
3525 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3526 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3527 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3529 return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface,
3530 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3533 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3534 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3535 DWORD VertexCount, DWORD Flags)
3537 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3538 DWORD FVF;
3540 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3541 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3543 switch(VertexType)
3545 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3546 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3547 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3548 default:
3549 ERR("Unexpected vertex type %d\n", VertexType);
3550 return DDERR_INVALIDPARAMS; /* Should never happen */
3553 return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface,
3554 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3557 /*****************************************************************************
3558 * IDirect3DDevice7::DrawIndexedPrimitive
3560 * Draws vertices from an application-provided pointer, based on the index
3561 * numbers in a WORD array.
3563 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3564 * an FVF format for D3D7
3566 * Params:
3567 * PrimitiveType: The primitive type to draw
3568 * VertexType: The FVF vertex description
3569 * Vertices: Pointer to the vertex array
3570 * VertexCount: ?
3571 * Indices: Pointer to the index array
3572 * IndexCount: Number of indices = Number of vertices to draw
3573 * Flags: As usual, some flags
3575 * Returns:
3576 * D3D_OK on success
3577 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3578 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3580 *****************************************************************************/
3581 static HRESULT
3582 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3583 D3DPRIMITIVETYPE PrimitiveType,
3584 DWORD VertexType,
3585 void *Vertices,
3586 DWORD VertexCount,
3587 WORD *Indices,
3588 DWORD IndexCount,
3589 DWORD Flags)
3591 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3592 HRESULT hr;
3594 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3595 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3597 /* Set the D3DDevice's FVF */
3598 wined3d_mutex_lock();
3599 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3600 if(FAILED(hr))
3602 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3603 wined3d_mutex_unlock();
3604 return hr;
3607 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3608 hr = wined3d_device_draw_indexed_primitive_up(This->wined3d_device, IndexCount, Indices,
3609 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3610 wined3d_mutex_unlock();
3612 return hr;
3615 static HRESULT WINAPI
3616 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3617 D3DPRIMITIVETYPE PrimitiveType,
3618 DWORD VertexType,
3619 void *Vertices,
3620 DWORD VertexCount,
3621 WORD *Indices,
3622 DWORD IndexCount,
3623 DWORD Flags)
3625 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3628 static HRESULT WINAPI
3629 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3630 D3DPRIMITIVETYPE PrimitiveType,
3631 DWORD VertexType,
3632 void *Vertices,
3633 DWORD VertexCount,
3634 WORD *Indices,
3635 DWORD IndexCount,
3636 DWORD Flags)
3638 HRESULT hr;
3639 WORD old_fpucw;
3641 old_fpucw = d3d_fpu_setup();
3642 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3643 set_fpu_control_word(old_fpucw);
3645 return hr;
3648 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3649 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3650 WORD *Indices, DWORD IndexCount, DWORD Flags)
3652 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3653 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3654 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3656 return IDirect3DDevice7_DrawIndexedPrimitive(&This->IDirect3DDevice7_iface,
3657 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3660 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3661 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3662 DWORD VertexCount, WORD *Indices, DWORD IndexCount, DWORD Flags)
3664 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3665 DWORD FVF;
3667 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3668 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3670 switch(VertexType)
3672 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3673 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3674 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3675 default:
3676 ERR("Unexpected vertex type %d\n", VertexType);
3677 return DDERR_INVALIDPARAMS; /* Should never happen */
3680 return IDirect3DDevice7_DrawIndexedPrimitive(&This->IDirect3DDevice7_iface,
3681 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3684 /*****************************************************************************
3685 * IDirect3DDevice7::SetClipStatus
3687 * Sets the clip status. This defines things as clipping conditions and
3688 * the extents of the clipping region.
3690 * Version 2, 3 and 7
3692 * Params:
3693 * ClipStatus:
3695 * Returns:
3696 * D3D_OK because it's a stub
3697 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3699 *****************************************************************************/
3700 static HRESULT WINAPI
3701 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3702 D3DCLIPSTATUS *ClipStatus)
3704 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3706 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3707 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3709 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3710 return D3D_OK;
3713 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3714 D3DCLIPSTATUS *ClipStatus)
3716 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3717 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3719 return IDirect3DDevice7_SetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3722 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3723 D3DCLIPSTATUS *ClipStatus)
3725 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3726 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3728 return IDirect3DDevice7_SetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3731 /*****************************************************************************
3732 * IDirect3DDevice7::GetClipStatus
3734 * Returns the clip status
3736 * Params:
3737 * ClipStatus: Address to write the clip status to
3739 * Returns:
3740 * D3D_OK because it's a stub
3742 *****************************************************************************/
3743 static HRESULT WINAPI
3744 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3745 D3DCLIPSTATUS *ClipStatus)
3747 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3749 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3750 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3751 return D3D_OK;
3754 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3755 D3DCLIPSTATUS *ClipStatus)
3757 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3758 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3760 return IDirect3DDevice7_GetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3763 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3764 D3DCLIPSTATUS *ClipStatus)
3766 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3767 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3769 return IDirect3DDevice7_GetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3772 /*****************************************************************************
3773 * IDirect3DDevice::DrawPrimitiveStrided
3775 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3777 * Version 3 and 7
3779 * Params:
3780 * PrimitiveType: The primitive type to draw
3781 * VertexType: The FVF description of the vertices to draw (for the stride??)
3782 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3783 * the vertex data locations
3784 * VertexCount: The number of vertices to draw
3785 * Flags: Some flags
3787 * Returns:
3788 * D3D_OK, because it's a stub
3789 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3790 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3792 *****************************************************************************/
3793 static HRESULT
3794 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3795 D3DPRIMITIVETYPE PrimitiveType,
3796 DWORD VertexType,
3797 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3798 DWORD VertexCount,
3799 DWORD Flags)
3801 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3802 WineDirect3DVertexStridedData WineD3DStrided;
3803 DWORD i;
3804 HRESULT hr;
3806 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3807 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3809 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3810 /* Get the strided data right. the wined3d structure is a bit bigger
3811 * Watch out: The contents of the strided data are determined by the fvf,
3812 * not by the members set in D3DDrawPrimStrideData. So it's valid
3813 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3814 * not set in the fvf.
3816 if(VertexType & D3DFVF_POSITION_MASK)
3818 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3819 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3820 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3821 if (VertexType & D3DFVF_XYZRHW)
3823 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3824 WineD3DStrided.position_transformed = TRUE;
3825 } else
3826 WineD3DStrided.position_transformed = FALSE;
3829 if(VertexType & D3DFVF_NORMAL)
3831 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3832 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3833 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3836 if(VertexType & D3DFVF_DIFFUSE)
3838 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3839 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3840 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3843 if(VertexType & D3DFVF_SPECULAR)
3845 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3846 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3847 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3850 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3852 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3854 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3855 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3856 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3857 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3858 default: ERR("Unexpected texture coordinate size %d\n",
3859 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3861 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3862 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3865 /* WineD3D doesn't need the FVF here */
3866 wined3d_mutex_lock();
3867 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3868 hr = wined3d_device_draw_primitive_strided(This->wined3d_device, VertexCount, &WineD3DStrided);
3869 wined3d_mutex_unlock();
3871 return hr;
3874 static HRESULT WINAPI
3875 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3876 D3DPRIMITIVETYPE PrimitiveType,
3877 DWORD VertexType,
3878 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3879 DWORD VertexCount,
3880 DWORD Flags)
3882 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3885 static HRESULT WINAPI
3886 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3887 D3DPRIMITIVETYPE PrimitiveType,
3888 DWORD VertexType,
3889 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3890 DWORD VertexCount,
3891 DWORD Flags)
3893 HRESULT hr;
3894 WORD old_fpucw;
3896 old_fpucw = d3d_fpu_setup();
3897 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3898 set_fpu_control_word(old_fpucw);
3900 return hr;
3903 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3904 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3905 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3907 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3909 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3910 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3912 return IDirect3DDevice7_DrawPrimitiveStrided(&This->IDirect3DDevice7_iface,
3913 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3916 /*****************************************************************************
3917 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3919 * Draws primitives specified by strided data locations based on indices
3921 * Version 3 and 7
3923 * Params:
3924 * PrimitiveType:
3926 * Returns:
3927 * D3D_OK, because it's a stub
3928 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3929 * (DDERR_INVALIDPARAMS if Indices is NULL)
3930 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3932 *****************************************************************************/
3933 static HRESULT
3934 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3935 D3DPRIMITIVETYPE PrimitiveType,
3936 DWORD VertexType,
3937 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3938 DWORD VertexCount,
3939 WORD *Indices,
3940 DWORD IndexCount,
3941 DWORD Flags)
3943 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3944 WineDirect3DVertexStridedData WineD3DStrided;
3945 DWORD i;
3946 HRESULT hr;
3948 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3949 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3951 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3952 /* Get the strided data right. the wined3d structure is a bit bigger
3953 * Watch out: The contents of the strided data are determined by the fvf,
3954 * not by the members set in D3DDrawPrimStrideData. So it's valid
3955 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3956 * not set in the fvf.
3958 if(VertexType & D3DFVF_POSITION_MASK)
3960 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3961 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3962 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3963 if (VertexType & D3DFVF_XYZRHW)
3965 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3966 WineD3DStrided.position_transformed = TRUE;
3967 } else
3968 WineD3DStrided.position_transformed = FALSE;
3971 if(VertexType & D3DFVF_NORMAL)
3973 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3974 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3975 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3978 if(VertexType & D3DFVF_DIFFUSE)
3980 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3981 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3982 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3985 if(VertexType & D3DFVF_SPECULAR)
3987 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3988 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3989 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3992 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3994 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3996 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3997 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3998 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3999 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
4000 default: ERR("Unexpected texture coordinate size %d\n",
4001 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4003 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4004 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4007 /* WineD3D doesn't need the FVF here */
4008 wined3d_mutex_lock();
4009 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4010 hr = wined3d_device_draw_indexed_primitive_strided(This->wined3d_device,
4011 IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
4012 wined3d_mutex_unlock();
4014 return hr;
4017 static HRESULT WINAPI
4018 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4019 D3DPRIMITIVETYPE PrimitiveType,
4020 DWORD VertexType,
4021 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4022 DWORD VertexCount,
4023 WORD *Indices,
4024 DWORD IndexCount,
4025 DWORD Flags)
4027 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4030 static HRESULT WINAPI
4031 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4032 D3DPRIMITIVETYPE PrimitiveType,
4033 DWORD VertexType,
4034 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4035 DWORD VertexCount,
4036 WORD *Indices,
4037 DWORD IndexCount,
4038 DWORD Flags)
4040 HRESULT hr;
4041 WORD old_fpucw;
4043 old_fpucw = d3d_fpu_setup();
4044 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4045 set_fpu_control_word(old_fpucw);
4047 return hr;
4050 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4051 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4052 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4053 DWORD IndexCount, DWORD Flags)
4055 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4057 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4058 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4060 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&This->IDirect3DDevice7_iface,
4061 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4064 /*****************************************************************************
4065 * IDirect3DDevice7::DrawPrimitiveVB
4067 * Draws primitives from a vertex buffer to the screen.
4069 * Version 3 and 7
4071 * Params:
4072 * PrimitiveType: Type of primitive to be rendered.
4073 * D3DVertexBuf: Source Vertex Buffer
4074 * StartVertex: Index of the first vertex from the buffer to be rendered
4075 * NumVertices: Number of vertices to be rendered
4076 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4078 * Return values
4079 * D3D_OK on success
4080 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4082 *****************************************************************************/
4083 static HRESULT
4084 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4085 D3DPRIMITIVETYPE PrimitiveType,
4086 IDirect3DVertexBuffer7 *D3DVertexBuf,
4087 DWORD StartVertex,
4088 DWORD NumVertices,
4089 DWORD Flags)
4091 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4092 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4093 HRESULT hr;
4094 DWORD stride;
4096 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4097 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4099 /* Sanity checks */
4100 if(!vb)
4102 ERR("(%p) No Vertex buffer specified\n", This);
4103 return DDERR_INVALIDPARAMS;
4105 stride = get_flexible_vertex_size(vb->fvf);
4107 wined3d_mutex_lock();
4108 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4109 if (FAILED(hr))
4111 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4112 wined3d_mutex_unlock();
4113 return hr;
4116 /* Set the vertex stream source */
4117 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4118 if(hr != D3D_OK)
4120 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4121 wined3d_mutex_unlock();
4122 return hr;
4125 /* Now draw the primitives */
4126 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4127 hr = wined3d_device_draw_primitive(This->wined3d_device, StartVertex, NumVertices);
4128 wined3d_mutex_unlock();
4130 return hr;
4133 static HRESULT WINAPI
4134 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4135 D3DPRIMITIVETYPE PrimitiveType,
4136 IDirect3DVertexBuffer7 *D3DVertexBuf,
4137 DWORD StartVertex,
4138 DWORD NumVertices,
4139 DWORD Flags)
4141 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4144 static HRESULT WINAPI
4145 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4146 D3DPRIMITIVETYPE PrimitiveType,
4147 IDirect3DVertexBuffer7 *D3DVertexBuf,
4148 DWORD StartVertex,
4149 DWORD NumVertices,
4150 DWORD Flags)
4152 HRESULT hr;
4153 WORD old_fpucw;
4155 old_fpucw = d3d_fpu_setup();
4156 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4157 set_fpu_control_word(old_fpucw);
4159 return hr;
4162 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4163 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex,
4164 DWORD NumVertices, DWORD Flags)
4166 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4167 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4169 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4170 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4172 return IDirect3DDevice7_DrawPrimitiveVB(&This->IDirect3DDevice7_iface,
4173 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4177 /*****************************************************************************
4178 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4180 * Draws primitives from a vertex buffer to the screen
4182 * Params:
4183 * PrimitiveType: Type of primitive to be rendered.
4184 * D3DVertexBuf: Source Vertex Buffer
4185 * StartVertex: Index of the first vertex from the buffer to be rendered
4186 * NumVertices: Number of vertices to be rendered
4187 * Indices: Array of DWORDs used to index into the Vertices
4188 * IndexCount: Number of indices in Indices
4189 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4191 * Return values
4193 *****************************************************************************/
4194 static HRESULT
4195 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4196 D3DPRIMITIVETYPE PrimitiveType,
4197 IDirect3DVertexBuffer7 *D3DVertexBuf,
4198 DWORD StartVertex,
4199 DWORD NumVertices,
4200 WORD *Indices,
4201 DWORD IndexCount,
4202 DWORD Flags)
4204 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4205 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4206 DWORD stride = get_flexible_vertex_size(vb->fvf);
4207 struct wined3d_resource *wined3d_resource;
4208 struct wined3d_resource_desc desc;
4209 WORD *LockedIndices;
4210 HRESULT hr;
4212 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4213 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4215 /* Steps:
4216 * 1) Upload the Indices to the index buffer
4217 * 2) Set the index source
4218 * 3) Set the Vertex Buffer as the Stream source
4219 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4222 wined3d_mutex_lock();
4224 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4225 if (FAILED(hr))
4227 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4228 wined3d_mutex_unlock();
4229 return hr;
4232 /* check that the buffer is large enough to hold the indices,
4233 * reallocate if necessary. */
4234 wined3d_resource = wined3d_buffer_get_resource(This->indexbuffer);
4235 wined3d_resource_get_desc(wined3d_resource, &desc);
4236 if (desc.size < IndexCount * sizeof(WORD))
4238 UINT size = max(desc.size * 2, IndexCount * sizeof(WORD));
4239 struct wined3d_buffer *buffer;
4241 TRACE("Growing index buffer to %u bytes\n", size);
4243 hr = wined3d_buffer_create_ib(This->wined3d_device, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4244 WINED3DPOOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
4245 if (FAILED(hr))
4247 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4248 wined3d_mutex_unlock();
4249 return hr;
4252 wined3d_buffer_decref(This->indexbuffer);
4253 This->indexbuffer = buffer;
4256 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4257 * method could be created which takes an user pointer containing the
4258 * indices or a SetData-Method for the index buffer, which overrides the
4259 * index buffer data with our pointer. */
4260 hr = wined3d_buffer_map(This->indexbuffer, 0, IndexCount * sizeof(WORD),
4261 (BYTE **)&LockedIndices, 0);
4262 if (FAILED(hr))
4264 ERR("Failed to map buffer, hr %#x.\n", hr);
4265 wined3d_mutex_unlock();
4266 return hr;
4268 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4269 wined3d_buffer_unmap(This->indexbuffer);
4271 /* Set the index stream */
4272 wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4273 hr = wined3d_device_set_index_buffer(This->wined3d_device, This->indexbuffer, WINED3DFMT_R16_UINT);
4275 /* Set the vertex stream source */
4276 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4277 if (FAILED(hr))
4279 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4280 wined3d_mutex_unlock();
4281 return hr;
4285 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4286 hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, 0, IndexCount);
4288 wined3d_mutex_unlock();
4290 return hr;
4293 static HRESULT WINAPI
4294 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4295 D3DPRIMITIVETYPE PrimitiveType,
4296 IDirect3DVertexBuffer7 *D3DVertexBuf,
4297 DWORD StartVertex,
4298 DWORD NumVertices,
4299 WORD *Indices,
4300 DWORD IndexCount,
4301 DWORD Flags)
4303 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4306 static HRESULT WINAPI
4307 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4308 D3DPRIMITIVETYPE PrimitiveType,
4309 IDirect3DVertexBuffer7 *D3DVertexBuf,
4310 DWORD StartVertex,
4311 DWORD NumVertices,
4312 WORD *Indices,
4313 DWORD IndexCount,
4314 DWORD Flags)
4316 HRESULT hr;
4317 WORD old_fpucw;
4319 old_fpucw = d3d_fpu_setup();
4320 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4321 set_fpu_control_word(old_fpucw);
4323 return hr;
4326 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4327 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4328 DWORD IndexCount, DWORD Flags)
4330 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4331 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4333 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4334 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4336 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&This->IDirect3DDevice7_iface,
4337 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount,
4338 Flags);
4341 /*****************************************************************************
4342 * IDirect3DDevice7::ComputeSphereVisibility
4344 * Calculates the visibility of spheres in the current viewport. The spheres
4345 * are passed in the Centers and Radii arrays, the results are passed back
4346 * in the ReturnValues array. Return values are either completely visible,
4347 * partially visible or completely invisible.
4348 * The return value consist of a combination of D3DCLIP_* flags, or it's
4349 * 0 if the sphere is completely visible(according to the SDK, not checked)
4351 * Version 3 and 7
4353 * Params:
4354 * Centers: Array containing the sphere centers
4355 * Radii: Array containing the sphere radii
4356 * NumSpheres: The number of centers and radii in the arrays
4357 * Flags: Some flags
4358 * ReturnValues: Array to write the results to
4360 * Returns:
4361 * D3D_OK
4362 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4363 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4364 * is singular)
4366 *****************************************************************************/
4368 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4370 float distance, norm;
4372 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4373 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4375 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4376 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4377 return 0;
4380 static HRESULT WINAPI
4381 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4382 D3DVECTOR *Centers,
4383 D3DVALUE *Radii,
4384 DWORD NumSpheres,
4385 DWORD Flags,
4386 DWORD *ReturnValues)
4388 D3DMATRIX m, temp;
4389 D3DVALUE origin_plane[6];
4390 D3DVECTOR vec[6];
4391 HRESULT hr;
4392 UINT i, j;
4394 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4395 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4397 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4398 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4399 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4400 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4401 multiply_matrix(&m, &temp, &m);
4403 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4404 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4405 multiply_matrix(&m, &temp, &m);
4407 /* Left plane */
4408 vec[0].u1.x = m._14 + m._11;
4409 vec[0].u2.y = m._24 + m._21;
4410 vec[0].u3.z = m._34 + m._31;
4411 origin_plane[0] = m._44 + m._41;
4413 /* Right plane */
4414 vec[1].u1.x = m._14 - m._11;
4415 vec[1].u2.y = m._24 - m._21;
4416 vec[1].u3.z = m._34 - m._31;
4417 origin_plane[1] = m._44 - m._41;
4419 /* Top plane */
4420 vec[2].u1.x = m._14 - m._12;
4421 vec[2].u2.y = m._24 - m._22;
4422 vec[2].u3.z = m._34 - m._32;
4423 origin_plane[2] = m._44 - m._42;
4425 /* Bottom plane */
4426 vec[3].u1.x = m._14 + m._12;
4427 vec[3].u2.y = m._24 + m._22;
4428 vec[3].u3.z = m._34 + m._32;
4429 origin_plane[3] = m._44 + m._42;
4431 /* Front plane */
4432 vec[4].u1.x = m._13;
4433 vec[4].u2.y = m._23;
4434 vec[4].u3.z = m._33;
4435 origin_plane[4] = m._43;
4437 /* Back plane*/
4438 vec[5].u1.x = m._14 - m._13;
4439 vec[5].u2.y = m._24 - m._23;
4440 vec[5].u3.z = m._34 - m._33;
4441 origin_plane[5] = m._44 - m._43;
4443 for(i=0; i<NumSpheres; i++)
4445 ReturnValues[i] = 0;
4446 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4449 return D3D_OK;
4452 static HRESULT WINAPI IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4453 D3DVECTOR *Centers, D3DVALUE *Radii, DWORD NumSpheres, DWORD Flags, DWORD *ReturnValues)
4455 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4457 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4458 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4460 return IDirect3DDevice7_ComputeSphereVisibility(&This->IDirect3DDevice7_iface,
4461 Centers, Radii, NumSpheres, Flags, ReturnValues);
4464 /*****************************************************************************
4465 * IDirect3DDevice7::GetTexture
4467 * Returns the texture interface handle assigned to a texture stage.
4468 * The returned texture is AddRefed. This is taken from old ddraw,
4469 * not checked in Windows.
4471 * Version 3 and 7
4473 * Params:
4474 * Stage: Texture stage to read the texture from
4475 * Texture: Address to store the interface pointer at
4477 * Returns:
4478 * D3D_OK on success
4479 * DDERR_INVALIDPARAMS if Texture is NULL
4480 * For details, see IWineD3DDevice::GetTexture
4482 *****************************************************************************/
4483 static HRESULT
4484 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4485 DWORD Stage,
4486 IDirectDrawSurface7 **Texture)
4488 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4489 struct wined3d_texture *wined3d_texture;
4490 HRESULT hr;
4492 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4494 if(!Texture)
4496 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4497 return DDERR_INVALIDPARAMS;
4500 wined3d_mutex_lock();
4501 hr = wined3d_device_get_texture(This->wined3d_device, Stage, &wined3d_texture);
4502 if (FAILED(hr) || !wined3d_texture)
4504 *Texture = NULL;
4505 wined3d_mutex_unlock();
4506 return hr;
4509 *Texture = wined3d_texture_get_parent(wined3d_texture);
4510 IDirectDrawSurface7_AddRef(*Texture);
4511 wined3d_texture_decref(wined3d_texture);
4512 wined3d_mutex_unlock();
4514 return hr;
4517 static HRESULT WINAPI
4518 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4519 DWORD Stage,
4520 IDirectDrawSurface7 **Texture)
4522 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4525 static HRESULT WINAPI
4526 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4527 DWORD Stage,
4528 IDirectDrawSurface7 **Texture)
4530 HRESULT hr;
4531 WORD old_fpucw;
4533 old_fpucw = d3d_fpu_setup();
4534 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4535 set_fpu_control_word(old_fpucw);
4537 return hr;
4540 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface, DWORD Stage,
4541 IDirect3DTexture2 **Texture2)
4543 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4544 HRESULT ret;
4545 IDirectDrawSurface7 *ret_val;
4546 IDirectDrawSurfaceImpl *ret_val_impl;
4548 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4550 ret = IDirect3DDevice7_GetTexture(&This->IDirect3DDevice7_iface, Stage, &ret_val);
4552 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4553 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4555 TRACE("Returning texture %p.\n", *Texture2);
4557 return ret;
4560 /*****************************************************************************
4561 * IDirect3DDevice7::SetTexture
4563 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4565 * Version 3 and 7
4567 * Params:
4568 * Stage: The stage to assign the texture to
4569 * Texture: Interface pointer to the texture surface
4571 * Returns
4572 * D3D_OK on success
4573 * For details, see IWineD3DDevice::SetTexture
4575 *****************************************************************************/
4576 static HRESULT
4577 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4578 DWORD Stage,
4579 IDirectDrawSurface7 *Texture)
4581 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4582 IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
4583 HRESULT hr;
4585 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4587 /* Texture may be NULL here */
4588 wined3d_mutex_lock();
4589 hr = wined3d_device_set_texture(This->wined3d_device,
4590 Stage, surf ? surf->wined3d_texture : NULL);
4591 wined3d_mutex_unlock();
4593 return hr;
4596 static HRESULT WINAPI
4597 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4598 DWORD Stage,
4599 IDirectDrawSurface7 *Texture)
4601 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4604 static HRESULT WINAPI
4605 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4606 DWORD Stage,
4607 IDirectDrawSurface7 *Texture)
4609 HRESULT hr;
4610 WORD old_fpucw;
4612 old_fpucw = d3d_fpu_setup();
4613 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4614 set_fpu_control_word(old_fpucw);
4616 return hr;
4619 static HRESULT WINAPI
4620 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4621 DWORD Stage,
4622 IDirect3DTexture2 *Texture2)
4624 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4625 IDirectDrawSurfaceImpl *tex = unsafe_impl_from_IDirect3DTexture2(Texture2);
4626 DWORD texmapblend;
4627 HRESULT hr;
4629 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4631 wined3d_mutex_lock();
4633 if (This->legacyTextureBlending)
4634 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4636 hr = IDirect3DDevice7_SetTexture(&This->IDirect3DDevice7_iface, Stage, &tex->IDirectDrawSurface7_iface);
4638 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4640 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4641 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4642 struct wined3d_texture *tex = NULL;
4643 BOOL tex_alpha = FALSE;
4644 DDPIXELFORMAT ddfmt;
4645 HRESULT result;
4647 result = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
4648 if (result == WINED3D_OK && tex)
4650 struct wined3d_resource *sub_resource;
4652 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4654 struct wined3d_resource_desc desc;
4656 wined3d_resource_get_desc(sub_resource, &desc);
4657 ddfmt.dwSize = sizeof(ddfmt);
4658 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4659 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4662 wined3d_texture_decref(tex);
4665 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4666 if (tex_alpha)
4667 wined3d_device_set_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4668 else
4669 wined3d_device_set_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4672 wined3d_mutex_unlock();
4674 return hr;
4677 static const struct tss_lookup
4679 BOOL sampler_state;
4680 DWORD state;
4682 tss_lookup[] =
4684 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
4685 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
4686 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
4687 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
4688 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
4689 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
4690 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
4691 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4692 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4693 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4694 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4695 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4696 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
4697 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
4698 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
4699 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
4700 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
4701 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
4702 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
4703 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4704 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4705 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4706 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4707 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4708 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4711 /*****************************************************************************
4712 * IDirect3DDevice7::GetTextureStageState
4714 * Retrieves a state from a texture stage.
4716 * Version 3 and 7
4718 * Params:
4719 * Stage: The stage to retrieve the state from
4720 * TexStageStateType: The state type to retrieve
4721 * State: Address to store the state's value at
4723 * Returns:
4724 * D3D_OK on success
4725 * DDERR_INVALIDPARAMS if State is NULL
4726 * For details, see IWineD3DDevice::GetTextureStageState
4728 *****************************************************************************/
4729 static HRESULT
4730 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4731 DWORD Stage,
4732 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4733 DWORD *State)
4735 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4736 HRESULT hr;
4737 const struct tss_lookup *l;
4739 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4740 iface, Stage, TexStageStateType, State);
4742 if(!State)
4743 return DDERR_INVALIDPARAMS;
4745 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4747 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4748 return DD_OK;
4751 l = &tss_lookup[TexStageStateType];
4753 wined3d_mutex_lock();
4755 if (l->sampler_state)
4757 hr = wined3d_device_get_sampler_state(This->wined3d_device, Stage, l->state, State);
4759 switch(TexStageStateType)
4761 /* Mipfilter is a sampler state with different values */
4762 case D3DTSS_MIPFILTER:
4764 switch(*State)
4766 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4767 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4768 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4769 default:
4770 ERR("Unexpected mipfilter value %#x\n", *State);
4771 *State = D3DTFP_NONE;
4772 break;
4774 break;
4777 /* Magfilter has slightly different values */
4778 case D3DTSS_MAGFILTER:
4780 switch(*State)
4782 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4783 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4784 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4785 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4786 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4787 default:
4788 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4789 *State = D3DTFG_POINT;
4790 break;
4792 break;
4795 default:
4796 break;
4799 else
4801 hr = wined3d_device_get_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4804 wined3d_mutex_unlock();
4806 return hr;
4809 static HRESULT WINAPI
4810 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4811 DWORD Stage,
4812 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4813 DWORD *State)
4815 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4818 static HRESULT WINAPI
4819 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4820 DWORD Stage,
4821 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4822 DWORD *State)
4824 HRESULT hr;
4825 WORD old_fpucw;
4827 old_fpucw = d3d_fpu_setup();
4828 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4829 set_fpu_control_word(old_fpucw);
4831 return hr;
4834 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4835 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD *State)
4837 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4839 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4840 iface, Stage, TexStageStateType, State);
4842 return IDirect3DDevice7_GetTextureStageState(&This->IDirect3DDevice7_iface,
4843 Stage, TexStageStateType, State);
4846 /*****************************************************************************
4847 * IDirect3DDevice7::SetTextureStageState
4849 * Sets a texture stage state. Some stage types need to be handled specially,
4850 * because they do not exist in WineD3D and were moved to another place
4852 * Version 3 and 7
4854 * Params:
4855 * Stage: The stage to modify
4856 * TexStageStateType: The state to change
4857 * State: The new value for the state
4859 * Returns:
4860 * D3D_OK on success
4861 * For details, see IWineD3DDevice::SetTextureStageState
4863 *****************************************************************************/
4864 static HRESULT
4865 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4866 DWORD Stage,
4867 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4868 DWORD State)
4870 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4871 const struct tss_lookup *l;
4872 HRESULT hr;
4874 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4875 iface, Stage, TexStageStateType, State);
4877 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4879 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4880 return DD_OK;
4883 l = &tss_lookup[TexStageStateType];
4885 wined3d_mutex_lock();
4887 if (l->sampler_state)
4889 switch(TexStageStateType)
4891 /* Mipfilter is a sampler state with different values */
4892 case D3DTSS_MIPFILTER:
4894 switch(State)
4896 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
4897 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
4898 case 0: /* Unchecked */
4899 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
4900 default:
4901 ERR("Unexpected mipfilter value %d\n", State);
4902 State = WINED3DTEXF_NONE;
4903 break;
4905 break;
4908 /* Magfilter has slightly different values */
4909 case D3DTSS_MAGFILTER:
4911 switch(State)
4913 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
4914 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
4915 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
4916 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
4917 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
4918 default:
4919 ERR("Unexpected d3d7 mag filter type %d\n", State);
4920 State = WINED3DTEXF_POINT;
4921 break;
4923 break;
4926 case D3DTSS_ADDRESS:
4927 wined3d_device_set_sampler_state(This->wined3d_device, Stage, WINED3DSAMP_ADDRESSV, State);
4928 break;
4930 default:
4931 break;
4934 hr = wined3d_device_set_sampler_state(This->wined3d_device, Stage, l->state, State);
4936 else
4938 hr = wined3d_device_set_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4941 wined3d_mutex_unlock();
4943 return hr;
4946 static HRESULT WINAPI
4947 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4948 DWORD Stage,
4949 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4950 DWORD State)
4952 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4955 static HRESULT WINAPI
4956 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4957 DWORD Stage,
4958 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4959 DWORD State)
4961 HRESULT hr;
4962 WORD old_fpucw;
4964 old_fpucw = d3d_fpu_setup();
4965 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4966 set_fpu_control_word(old_fpucw);
4968 return hr;
4971 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
4972 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD State)
4974 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4976 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4977 iface, Stage, TexStageStateType, State);
4979 return IDirect3DDevice7_SetTextureStageState(&This->IDirect3DDevice7_iface,
4980 Stage, TexStageStateType, State);
4983 /*****************************************************************************
4984 * IDirect3DDevice7::ValidateDevice
4986 * SDK: "Reports the device's ability to render the currently set
4987 * texture-blending operations in a single pass". Whatever that means
4988 * exactly...
4990 * Version 3 and 7
4992 * Params:
4993 * NumPasses: Address to write the number of necessary passes for the
4994 * desired effect to.
4996 * Returns:
4997 * D3D_OK on success
4998 * See IWineD3DDevice::ValidateDevice for more details
5000 *****************************************************************************/
5001 static HRESULT
5002 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
5003 DWORD *NumPasses)
5005 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5006 HRESULT hr;
5008 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
5010 wined3d_mutex_lock();
5011 hr = wined3d_device_validate_device(This->wined3d_device, NumPasses);
5012 wined3d_mutex_unlock();
5014 return hr;
5017 static HRESULT WINAPI
5018 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
5019 DWORD *NumPasses)
5021 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5024 static HRESULT WINAPI
5025 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
5026 DWORD *NumPasses)
5028 HRESULT hr;
5029 WORD old_fpucw;
5031 old_fpucw = d3d_fpu_setup();
5032 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5033 set_fpu_control_word(old_fpucw);
5035 return hr;
5038 static HRESULT WINAPI IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *Passes)
5040 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
5042 TRACE("iface %p, pass_count %p.\n", iface, Passes);
5044 return IDirect3DDevice7_ValidateDevice(&This->IDirect3DDevice7_iface, Passes);
5047 /*****************************************************************************
5048 * IDirect3DDevice7::Clear
5050 * Fills the render target, the z buffer and the stencil buffer with a
5051 * clear color / value
5053 * Version 7 only
5055 * Params:
5056 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5057 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5058 * Flags: Some flags, as usual
5059 * Color: Clear color for the render target
5060 * Z: Clear value for the Z buffer
5061 * Stencil: Clear value to store in each stencil buffer entry
5063 * Returns:
5064 * D3D_OK on success
5065 * For details, see IWineD3DDevice::Clear
5067 *****************************************************************************/
5068 static HRESULT IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface, DWORD count,
5069 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5071 const struct wined3d_color c =
5073 ((color >> 16) & 0xff) / 255.0f,
5074 ((color >> 8) & 0xff) / 255.0f,
5075 (color & 0xff) / 255.0f,
5076 ((color >> 24) & 0xff) / 255.0f,
5078 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5079 HRESULT hr;
5081 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5082 iface, count, rects, flags, color, z, stencil);
5084 wined3d_mutex_lock();
5085 hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
5086 wined3d_mutex_unlock();
5088 return hr;
5091 static HRESULT WINAPI
5092 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5093 DWORD Count,
5094 D3DRECT *Rects,
5095 DWORD Flags,
5096 D3DCOLOR Color,
5097 D3DVALUE Z,
5098 DWORD Stencil)
5100 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5103 static HRESULT WINAPI
5104 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5105 DWORD Count,
5106 D3DRECT *Rects,
5107 DWORD Flags,
5108 D3DCOLOR Color,
5109 D3DVALUE Z,
5110 DWORD Stencil)
5112 HRESULT hr;
5113 WORD old_fpucw;
5115 old_fpucw = d3d_fpu_setup();
5116 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5117 set_fpu_control_word(old_fpucw);
5119 return hr;
5122 /*****************************************************************************
5123 * IDirect3DDevice7::SetViewport
5125 * Sets the current viewport.
5127 * Version 7 only, but IDirect3DViewport uses this call for older
5128 * versions
5130 * Params:
5131 * Data: The new viewport to set
5133 * Returns:
5134 * D3D_OK on success
5135 * DDERR_INVALIDPARAMS if Data is NULL
5136 * For more details, see IWineDDDevice::SetViewport
5138 *****************************************************************************/
5139 static HRESULT
5140 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5141 D3DVIEWPORT7 *Data)
5143 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5144 HRESULT hr;
5146 TRACE("iface %p, viewport %p.\n", iface, Data);
5148 if(!Data)
5149 return DDERR_INVALIDPARAMS;
5151 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5152 wined3d_mutex_lock();
5153 hr = wined3d_device_set_viewport(This->wined3d_device, (WINED3DVIEWPORT *)Data);
5154 wined3d_mutex_unlock();
5156 return hr;
5159 static HRESULT WINAPI
5160 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5161 D3DVIEWPORT7 *Data)
5163 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5166 static HRESULT WINAPI
5167 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5168 D3DVIEWPORT7 *Data)
5170 HRESULT hr;
5171 WORD old_fpucw;
5173 old_fpucw = d3d_fpu_setup();
5174 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5175 set_fpu_control_word(old_fpucw);
5177 return hr;
5180 /*****************************************************************************
5181 * IDirect3DDevice::GetViewport
5183 * Returns the current viewport
5185 * Version 7
5187 * Params:
5188 * Data: D3D7Viewport structure to write the viewport information to
5190 * Returns:
5191 * D3D_OK on success
5192 * DDERR_INVALIDPARAMS if Data is NULL
5193 * For more details, see IWineD3DDevice::GetViewport
5195 *****************************************************************************/
5196 static HRESULT
5197 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5198 D3DVIEWPORT7 *Data)
5200 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5201 HRESULT hr;
5203 TRACE("iface %p, viewport %p.\n", iface, Data);
5205 if(!Data)
5206 return DDERR_INVALIDPARAMS;
5208 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5209 wined3d_mutex_lock();
5210 hr = wined3d_device_get_viewport(This->wined3d_device, (WINED3DVIEWPORT *)Data);
5211 wined3d_mutex_unlock();
5213 return hr_ddraw_from_wined3d(hr);
5216 static HRESULT WINAPI
5217 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5218 D3DVIEWPORT7 *Data)
5220 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5223 static HRESULT WINAPI
5224 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5225 D3DVIEWPORT7 *Data)
5227 HRESULT hr;
5228 WORD old_fpucw;
5230 old_fpucw = d3d_fpu_setup();
5231 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5232 set_fpu_control_word(old_fpucw);
5234 return hr;
5237 /*****************************************************************************
5238 * IDirect3DDevice7::SetMaterial
5240 * Sets the Material
5242 * Version 7
5244 * Params:
5245 * Mat: The material to set
5247 * Returns:
5248 * D3D_OK on success
5249 * DDERR_INVALIDPARAMS if Mat is NULL.
5250 * For more details, see IWineD3DDevice::SetMaterial
5252 *****************************************************************************/
5253 static HRESULT
5254 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5255 D3DMATERIAL7 *Mat)
5257 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5258 HRESULT hr;
5260 TRACE("iface %p, material %p.\n", iface, Mat);
5262 if (!Mat) return DDERR_INVALIDPARAMS;
5264 wined3d_mutex_lock();
5265 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5266 hr = wined3d_device_set_material(This->wined3d_device, (WINED3DMATERIAL *)Mat);
5267 wined3d_mutex_unlock();
5269 return hr_ddraw_from_wined3d(hr);
5272 static HRESULT WINAPI
5273 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5274 D3DMATERIAL7 *Mat)
5276 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5279 static HRESULT WINAPI
5280 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5281 D3DMATERIAL7 *Mat)
5283 HRESULT hr;
5284 WORD old_fpucw;
5286 old_fpucw = d3d_fpu_setup();
5287 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5288 set_fpu_control_word(old_fpucw);
5290 return hr;
5293 /*****************************************************************************
5294 * IDirect3DDevice7::GetMaterial
5296 * Returns the current material
5298 * Version 7
5300 * Params:
5301 * Mat: D3DMATERIAL7 structure to write the material parameters to
5303 * Returns:
5304 * D3D_OK on success
5305 * DDERR_INVALIDPARAMS if Mat is NULL
5306 * For more details, see IWineD3DDevice::GetMaterial
5308 *****************************************************************************/
5309 static HRESULT
5310 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5311 D3DMATERIAL7 *Mat)
5313 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5314 HRESULT hr;
5316 TRACE("iface %p, material %p.\n", iface, Mat);
5318 wined3d_mutex_lock();
5319 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5320 hr = wined3d_device_get_material(This->wined3d_device, (WINED3DMATERIAL *)Mat);
5321 wined3d_mutex_unlock();
5323 return hr_ddraw_from_wined3d(hr);
5326 static HRESULT WINAPI
5327 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5328 D3DMATERIAL7 *Mat)
5330 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5333 static HRESULT WINAPI
5334 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5335 D3DMATERIAL7 *Mat)
5337 HRESULT hr;
5338 WORD old_fpucw;
5340 old_fpucw = d3d_fpu_setup();
5341 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5342 set_fpu_control_word(old_fpucw);
5344 return hr;
5347 /*****************************************************************************
5348 * IDirect3DDevice7::SetLight
5350 * Assigns a light to a light index, but doesn't activate it yet.
5352 * Version 7, IDirect3DLight uses this method for older versions
5354 * Params:
5355 * LightIndex: The index of the new light
5356 * Light: A D3DLIGHT7 structure describing the light
5358 * Returns:
5359 * D3D_OK on success
5360 * For more details, see IWineD3DDevice::SetLight
5362 *****************************************************************************/
5363 static HRESULT
5364 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5365 DWORD LightIndex,
5366 D3DLIGHT7 *Light)
5368 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5369 HRESULT hr;
5371 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5373 wined3d_mutex_lock();
5374 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5375 hr = wined3d_device_set_light(This->wined3d_device, LightIndex, (WINED3DLIGHT *)Light);
5376 wined3d_mutex_unlock();
5378 return hr_ddraw_from_wined3d(hr);
5381 static HRESULT WINAPI
5382 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5383 DWORD LightIndex,
5384 D3DLIGHT7 *Light)
5386 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5389 static HRESULT WINAPI
5390 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5391 DWORD LightIndex,
5392 D3DLIGHT7 *Light)
5394 HRESULT hr;
5395 WORD old_fpucw;
5397 old_fpucw = d3d_fpu_setup();
5398 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5399 set_fpu_control_word(old_fpucw);
5401 return hr;
5404 /*****************************************************************************
5405 * IDirect3DDevice7::GetLight
5407 * Returns the light assigned to a light index
5409 * Params:
5410 * Light: Structure to write the light information to
5412 * Returns:
5413 * D3D_OK on success
5414 * DDERR_INVALIDPARAMS if Light is NULL
5415 * For details, see IWineD3DDevice::GetLight
5417 *****************************************************************************/
5418 static HRESULT
5419 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5420 DWORD LightIndex,
5421 D3DLIGHT7 *Light)
5423 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5424 HRESULT rc;
5426 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5428 wined3d_mutex_lock();
5429 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5430 rc = wined3d_device_get_light(This->wined3d_device, LightIndex, (WINED3DLIGHT *)Light);
5431 wined3d_mutex_unlock();
5433 /* Translate the result. WineD3D returns other values than D3D7 */
5434 return hr_ddraw_from_wined3d(rc);
5437 static HRESULT WINAPI
5438 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5439 DWORD LightIndex,
5440 D3DLIGHT7 *Light)
5442 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5445 static HRESULT WINAPI
5446 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5447 DWORD LightIndex,
5448 D3DLIGHT7 *Light)
5450 HRESULT hr;
5451 WORD old_fpucw;
5453 old_fpucw = d3d_fpu_setup();
5454 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5455 set_fpu_control_word(old_fpucw);
5457 return hr;
5460 /*****************************************************************************
5461 * IDirect3DDevice7::BeginStateBlock
5463 * Begins recording to a stateblock
5465 * Version 7
5467 * Returns:
5468 * D3D_OK on success
5469 * For details see IWineD3DDevice::BeginStateBlock
5471 *****************************************************************************/
5472 static HRESULT
5473 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5475 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5476 HRESULT hr;
5478 TRACE("iface %p.\n", iface);
5480 wined3d_mutex_lock();
5481 hr = wined3d_device_begin_stateblock(This->wined3d_device);
5482 wined3d_mutex_unlock();
5484 return hr_ddraw_from_wined3d(hr);
5487 static HRESULT WINAPI
5488 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5490 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5493 static HRESULT WINAPI
5494 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5496 HRESULT hr;
5497 WORD old_fpucw;
5499 old_fpucw = d3d_fpu_setup();
5500 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5501 set_fpu_control_word(old_fpucw);
5503 return hr;
5506 /*****************************************************************************
5507 * IDirect3DDevice7::EndStateBlock
5509 * Stops recording to a state block and returns the created stateblock
5510 * handle.
5512 * Version 7
5514 * Params:
5515 * BlockHandle: Address to store the stateblock's handle to
5517 * Returns:
5518 * D3D_OK on success
5519 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5520 * See IWineD3DDevice::EndStateBlock for more details
5522 *****************************************************************************/
5523 static HRESULT
5524 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5525 DWORD *BlockHandle)
5527 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5528 struct wined3d_stateblock *wined3d_sb;
5529 HRESULT hr;
5530 DWORD h;
5532 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5534 if(!BlockHandle)
5536 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5537 return DDERR_INVALIDPARAMS;
5540 wined3d_mutex_lock();
5542 hr = wined3d_device_end_stateblock(This->wined3d_device, &wined3d_sb);
5543 if (FAILED(hr))
5545 WARN("Failed to end stateblock, hr %#x.\n", hr);
5546 wined3d_mutex_unlock();
5547 *BlockHandle = 0;
5548 return hr_ddraw_from_wined3d(hr);
5551 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5552 if (h == DDRAW_INVALID_HANDLE)
5554 ERR("Failed to allocate a stateblock handle.\n");
5555 wined3d_stateblock_decref(wined3d_sb);
5556 wined3d_mutex_unlock();
5557 *BlockHandle = 0;
5558 return DDERR_OUTOFMEMORY;
5561 wined3d_mutex_unlock();
5562 *BlockHandle = h + 1;
5564 return hr_ddraw_from_wined3d(hr);
5567 static HRESULT WINAPI
5568 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5569 DWORD *BlockHandle)
5571 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5574 static HRESULT WINAPI
5575 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5576 DWORD *BlockHandle)
5578 HRESULT hr;
5579 WORD old_fpucw;
5581 old_fpucw = d3d_fpu_setup();
5582 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5583 set_fpu_control_word(old_fpucw);
5585 return hr;
5588 /*****************************************************************************
5589 * IDirect3DDevice7::PreLoad
5591 * Allows the app to signal that a texture will be used soon, to allow
5592 * the Direct3DDevice to load it to the video card in the meantime.
5594 * Version 7
5596 * Params:
5597 * Texture: The texture to preload
5599 * Returns:
5600 * D3D_OK on success
5601 * DDERR_INVALIDPARAMS if Texture is NULL
5602 * See IWineD3DSurface::PreLoad for details
5604 *****************************************************************************/
5605 static HRESULT
5606 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5607 IDirectDrawSurface7 *Texture)
5609 IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
5611 TRACE("iface %p, texture %p.\n", iface, Texture);
5613 if(!Texture)
5614 return DDERR_INVALIDPARAMS;
5616 wined3d_mutex_lock();
5617 wined3d_surface_preload(surf->wined3d_surface);
5618 wined3d_mutex_unlock();
5620 return D3D_OK;
5623 static HRESULT WINAPI
5624 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5625 IDirectDrawSurface7 *Texture)
5627 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5630 static HRESULT WINAPI
5631 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5632 IDirectDrawSurface7 *Texture)
5634 HRESULT hr;
5635 WORD old_fpucw;
5637 old_fpucw = d3d_fpu_setup();
5638 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5639 set_fpu_control_word(old_fpucw);
5641 return hr;
5644 /*****************************************************************************
5645 * IDirect3DDevice7::ApplyStateBlock
5647 * Activates the state stored in a state block handle.
5649 * Params:
5650 * BlockHandle: The stateblock handle to activate
5652 * Returns:
5653 * D3D_OK on success
5654 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5656 *****************************************************************************/
5657 static HRESULT
5658 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5659 DWORD BlockHandle)
5661 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5662 struct wined3d_stateblock *wined3d_sb;
5663 HRESULT hr;
5665 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5667 wined3d_mutex_lock();
5668 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5669 if (!wined3d_sb)
5671 WARN("Invalid stateblock handle.\n");
5672 wined3d_mutex_unlock();
5673 return D3DERR_INVALIDSTATEBLOCK;
5676 hr = wined3d_stateblock_apply(wined3d_sb);
5677 wined3d_mutex_unlock();
5679 return hr_ddraw_from_wined3d(hr);
5682 static HRESULT WINAPI
5683 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5684 DWORD BlockHandle)
5686 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5689 static HRESULT WINAPI
5690 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5691 DWORD BlockHandle)
5693 HRESULT hr;
5694 WORD old_fpucw;
5696 old_fpucw = d3d_fpu_setup();
5697 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5698 set_fpu_control_word(old_fpucw);
5700 return hr;
5703 /*****************************************************************************
5704 * IDirect3DDevice7::CaptureStateBlock
5706 * Updates a stateblock's values to the values currently set for the device
5708 * Version 7
5710 * Params:
5711 * BlockHandle: Stateblock to update
5713 * Returns:
5714 * D3D_OK on success
5715 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5716 * See IWineD3DDevice::CaptureStateBlock for more details
5718 *****************************************************************************/
5719 static HRESULT
5720 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5721 DWORD BlockHandle)
5723 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5724 struct wined3d_stateblock *wined3d_sb;
5725 HRESULT hr;
5727 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5729 wined3d_mutex_lock();
5730 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5731 if (!wined3d_sb)
5733 WARN("Invalid stateblock handle.\n");
5734 wined3d_mutex_unlock();
5735 return D3DERR_INVALIDSTATEBLOCK;
5738 hr = wined3d_stateblock_capture(wined3d_sb);
5739 wined3d_mutex_unlock();
5741 return hr_ddraw_from_wined3d(hr);
5744 static HRESULT WINAPI
5745 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5746 DWORD BlockHandle)
5748 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5751 static HRESULT WINAPI
5752 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5753 DWORD BlockHandle)
5755 HRESULT hr;
5756 WORD old_fpucw;
5758 old_fpucw = d3d_fpu_setup();
5759 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5760 set_fpu_control_word(old_fpucw);
5762 return hr;
5765 /*****************************************************************************
5766 * IDirect3DDevice7::DeleteStateBlock
5768 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5770 * Version 7
5772 * Params:
5773 * BlockHandle: Stateblock handle to delete
5775 * Returns:
5776 * D3D_OK on success
5777 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5779 *****************************************************************************/
5780 static HRESULT
5781 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5782 DWORD BlockHandle)
5784 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5785 struct wined3d_stateblock *wined3d_sb;
5786 ULONG ref;
5788 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5790 wined3d_mutex_lock();
5792 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5793 if (!wined3d_sb)
5795 WARN("Invalid stateblock handle.\n");
5796 wined3d_mutex_unlock();
5797 return D3DERR_INVALIDSTATEBLOCK;
5800 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5802 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5805 wined3d_mutex_unlock();
5807 return D3D_OK;
5810 static HRESULT WINAPI
5811 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5812 DWORD BlockHandle)
5814 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5817 static HRESULT WINAPI
5818 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5819 DWORD BlockHandle)
5821 HRESULT hr;
5822 WORD old_fpucw;
5824 old_fpucw = d3d_fpu_setup();
5825 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5826 set_fpu_control_word(old_fpucw);
5828 return hr;
5831 /*****************************************************************************
5832 * IDirect3DDevice7::CreateStateBlock
5834 * Creates a new state block handle.
5836 * Version 7
5838 * Params:
5839 * Type: The state block type
5840 * BlockHandle: Address to write the created handle to
5842 * Returns:
5843 * D3D_OK on success
5844 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5846 *****************************************************************************/
5847 static HRESULT
5848 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5849 D3DSTATEBLOCKTYPE Type,
5850 DWORD *BlockHandle)
5852 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5853 struct wined3d_stateblock *wined3d_sb;
5854 HRESULT hr;
5855 DWORD h;
5857 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5859 if(!BlockHandle)
5861 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5862 return DDERR_INVALIDPARAMS;
5864 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5865 Type != D3DSBT_VERTEXSTATE ) {
5866 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5867 return DDERR_INVALIDPARAMS;
5870 wined3d_mutex_lock();
5872 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5873 hr = wined3d_stateblock_create(This->wined3d_device, Type, &wined3d_sb);
5874 if (FAILED(hr))
5876 WARN("Failed to create stateblock, hr %#x.\n", hr);
5877 wined3d_mutex_unlock();
5878 return hr_ddraw_from_wined3d(hr);
5881 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5882 if (h == DDRAW_INVALID_HANDLE)
5884 ERR("Failed to allocate stateblock handle.\n");
5885 wined3d_stateblock_decref(wined3d_sb);
5886 wined3d_mutex_unlock();
5887 return DDERR_OUTOFMEMORY;
5890 *BlockHandle = h + 1;
5891 wined3d_mutex_unlock();
5893 return hr_ddraw_from_wined3d(hr);
5896 static HRESULT WINAPI
5897 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5898 D3DSTATEBLOCKTYPE Type,
5899 DWORD *BlockHandle)
5901 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5904 static HRESULT WINAPI
5905 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5906 D3DSTATEBLOCKTYPE Type,
5907 DWORD *BlockHandle)
5909 HRESULT hr;
5910 WORD old_fpucw;
5912 old_fpucw = d3d_fpu_setup();
5913 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5914 set_fpu_control_word(old_fpucw);
5916 return hr;
5919 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5920 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
5921 IDirectDrawSurfaceImpl *src)
5923 IDirectDrawSurfaceImpl *src_level, *dest_level;
5924 IDirectDrawSurface7 *temp;
5925 DDSURFACEDESC2 ddsd;
5926 BOOL levelFound; /* at least one suitable sublevel in dest found */
5928 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5929 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5930 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5932 levelFound = FALSE;
5934 src_level = src;
5935 dest_level = dest;
5937 for (;src_level && dest_level;)
5939 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5940 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5942 levelFound = TRUE;
5944 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5945 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5946 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5948 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5950 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5953 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5954 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5955 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5957 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5959 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5962 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5963 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5965 return !dest_level && levelFound;
5968 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5969 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
5970 IDirectDrawSurfaceImpl *dest,
5971 IDirectDrawSurfaceImpl *src,
5972 const POINT *DestPoint,
5973 const RECT *SrcRect)
5975 IDirectDrawSurfaceImpl *src_level, *dest_level;
5976 IDirectDrawSurface7 *temp;
5977 DDSURFACEDESC2 ddsd;
5978 POINT point;
5979 RECT src_rect;
5980 HRESULT hr;
5981 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5982 DWORD ckeyflag;
5983 DDCOLORKEY ddckey;
5985 /* Copy palette, if possible. */
5986 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
5987 IDirectDrawSurface7_GetPalette(&dest->IDirectDrawSurface7_iface, &pal);
5989 if (pal_src != NULL && pal != NULL)
5991 PALETTEENTRY palent[256];
5993 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5994 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5997 if (pal) IDirectDrawPalette_Release(pal);
5998 if (pal_src) IDirectDrawPalette_Release(pal_src);
6000 /* Copy colorkeys, if present. */
6001 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6003 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6005 if (SUCCEEDED(hr))
6007 IDirectDrawSurface7_SetColorKey(&dest->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6011 src_level = src;
6012 dest_level = dest;
6014 point = *DestPoint;
6015 src_rect = *SrcRect;
6017 for (;src_level && dest_level;)
6019 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6020 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6022 UINT src_w = src_rect.right - src_rect.left;
6023 UINT src_h = src_rect.bottom - src_rect.top;
6024 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
6026 if (FAILED(hr = wined3d_surface_blt(dest_level->wined3d_surface, &dst_rect,
6027 src_level->wined3d_surface, &src_rect, 0, NULL, WINED3DTEXF_POINT)))
6028 ERR("Blit failed, hr %#x.\n", hr);
6030 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6031 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6032 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6034 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6036 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6039 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6040 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6041 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6043 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6045 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6047 point.x /= 2;
6048 point.y /= 2;
6050 src_rect.top /= 2;
6051 src_rect.left /= 2;
6052 src_rect.right = (src_rect.right + 1) / 2;
6053 src_rect.bottom = (src_rect.bottom + 1) / 2;
6056 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6057 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6060 /*****************************************************************************
6061 * IDirect3DDevice7::Load
6063 * Loads a rectangular area from the source into the destination texture.
6064 * It can also copy the source to the faces of a cubic environment map
6066 * Version 7
6068 * Params:
6069 * DestTex: Destination texture
6070 * DestPoint: Point in the destination where the source image should be
6071 * written to
6072 * SrcTex: Source texture
6073 * SrcRect: Source rectangle
6074 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6075 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6076 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6078 * Returns:
6079 * D3D_OK on success
6080 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6083 *****************************************************************************/
6085 static HRESULT
6086 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6087 IDirectDrawSurface7 *DestTex,
6088 POINT *DestPoint,
6089 IDirectDrawSurface7 *SrcTex,
6090 RECT *SrcRect,
6091 DWORD Flags)
6093 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6094 IDirectDrawSurfaceImpl *dest = unsafe_impl_from_IDirectDrawSurface7(DestTex);
6095 IDirectDrawSurfaceImpl *src = unsafe_impl_from_IDirectDrawSurface7(SrcTex);
6096 POINT destpoint;
6097 RECT srcrect;
6099 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6100 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6102 if( (!src) || (!dest) )
6103 return DDERR_INVALIDPARAMS;
6105 wined3d_mutex_lock();
6107 if (SrcRect) srcrect = *SrcRect;
6108 else
6110 srcrect.left = srcrect.top = 0;
6111 srcrect.right = src->surface_desc.dwWidth;
6112 srcrect.bottom = src->surface_desc.dwHeight;
6115 if (DestPoint) destpoint = *DestPoint;
6116 else
6118 destpoint.x = destpoint.y = 0;
6120 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6121 * destination can be a subset of mip levels, in which case actual coordinates used
6122 * for it may be divided. If any dimension of dest is larger than source, it can't be
6123 * mip level subset, so an error can be returned early.
6125 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6126 srcrect.right > src->surface_desc.dwWidth ||
6127 srcrect.bottom > src->surface_desc.dwHeight ||
6128 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6129 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6130 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6131 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6133 wined3d_mutex_unlock();
6134 return DDERR_INVALIDPARAMS;
6137 /* Must be top level surfaces. */
6138 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6139 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6141 wined3d_mutex_unlock();
6142 return DDERR_INVALIDPARAMS;
6145 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6147 DWORD src_face_flag, dest_face_flag;
6148 IDirectDrawSurfaceImpl *src_face, *dest_face;
6149 IDirectDrawSurface7 *temp;
6150 DDSURFACEDESC2 ddsd;
6151 int i;
6153 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6155 wined3d_mutex_unlock();
6156 return DDERR_INVALIDPARAMS;
6159 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6160 * time it's actual surface loading. */
6161 for (i = 0; i < 2; i++)
6163 dest_face = dest;
6164 src_face = src;
6166 for (;dest_face && src_face;)
6168 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6169 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6171 if (src_face_flag == dest_face_flag)
6173 if (i == 0)
6175 /* Destination mip levels must be subset of source mip levels. */
6176 if (!is_mip_level_subset(dest_face, src_face))
6178 wined3d_mutex_unlock();
6179 return DDERR_INVALIDPARAMS;
6182 else if (Flags & dest_face_flag)
6184 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6187 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6189 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6190 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6191 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6193 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6195 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6197 else
6199 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6201 src_face = NULL;
6205 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6207 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6208 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6209 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6211 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6213 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6215 else
6217 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6219 dest_face = NULL;
6223 if (i == 0)
6225 /* Native returns error if src faces are not subset of dest faces. */
6226 if (src_face)
6228 wined3d_mutex_unlock();
6229 return DDERR_INVALIDPARAMS;
6234 wined3d_mutex_unlock();
6235 return D3D_OK;
6237 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6239 wined3d_mutex_unlock();
6240 return DDERR_INVALIDPARAMS;
6243 /* Handle non cube map textures. */
6245 /* Destination mip levels must be subset of source mip levels. */
6246 if (!is_mip_level_subset(dest, src))
6248 wined3d_mutex_unlock();
6249 return DDERR_INVALIDPARAMS;
6252 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6254 wined3d_mutex_unlock();
6256 return D3D_OK;
6259 static HRESULT WINAPI
6260 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6261 IDirectDrawSurface7 *DestTex,
6262 POINT *DestPoint,
6263 IDirectDrawSurface7 *SrcTex,
6264 RECT *SrcRect,
6265 DWORD Flags)
6267 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6270 static HRESULT WINAPI
6271 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6272 IDirectDrawSurface7 *DestTex,
6273 POINT *DestPoint,
6274 IDirectDrawSurface7 *SrcTex,
6275 RECT *SrcRect,
6276 DWORD Flags)
6278 HRESULT hr;
6279 WORD old_fpucw;
6281 old_fpucw = d3d_fpu_setup();
6282 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6283 set_fpu_control_word(old_fpucw);
6285 return hr;
6288 /*****************************************************************************
6289 * IDirect3DDevice7::LightEnable
6291 * Enables or disables a light
6293 * Version 7, IDirect3DLight uses this method too.
6295 * Params:
6296 * LightIndex: The index of the light to enable / disable
6297 * Enable: Enable or disable the light
6299 * Returns:
6300 * D3D_OK on success
6301 * For more details, see IWineD3DDevice::SetLightEnable
6303 *****************************************************************************/
6304 static HRESULT
6305 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6306 DWORD LightIndex,
6307 BOOL Enable)
6309 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6310 HRESULT hr;
6312 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6314 wined3d_mutex_lock();
6315 hr = wined3d_device_set_light_enable(This->wined3d_device, LightIndex, Enable);
6316 wined3d_mutex_unlock();
6318 return hr_ddraw_from_wined3d(hr);
6321 static HRESULT WINAPI
6322 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6323 DWORD LightIndex,
6324 BOOL Enable)
6326 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6329 static HRESULT WINAPI
6330 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6331 DWORD LightIndex,
6332 BOOL Enable)
6334 HRESULT hr;
6335 WORD old_fpucw;
6337 old_fpucw = d3d_fpu_setup();
6338 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6339 set_fpu_control_word(old_fpucw);
6341 return hr;
6344 /*****************************************************************************
6345 * IDirect3DDevice7::GetLightEnable
6347 * Retrieves if the light with the given index is enabled or not
6349 * Version 7
6351 * Params:
6352 * LightIndex: Index of desired light
6353 * Enable: Pointer to a BOOL which contains the result
6355 * Returns:
6356 * D3D_OK on success
6357 * DDERR_INVALIDPARAMS if Enable is NULL
6358 * See IWineD3DDevice::GetLightEnable for more details
6360 *****************************************************************************/
6361 static HRESULT
6362 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6363 DWORD LightIndex,
6364 BOOL* Enable)
6366 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6367 HRESULT hr;
6369 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6371 if(!Enable)
6372 return DDERR_INVALIDPARAMS;
6374 wined3d_mutex_lock();
6375 hr = wined3d_device_get_light_enable(This->wined3d_device, LightIndex, Enable);
6376 wined3d_mutex_unlock();
6378 return hr_ddraw_from_wined3d(hr);
6381 static HRESULT WINAPI
6382 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6383 DWORD LightIndex,
6384 BOOL* Enable)
6386 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6389 static HRESULT WINAPI
6390 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6391 DWORD LightIndex,
6392 BOOL* Enable)
6394 HRESULT hr;
6395 WORD old_fpucw;
6397 old_fpucw = d3d_fpu_setup();
6398 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6399 set_fpu_control_word(old_fpucw);
6401 return hr;
6404 /*****************************************************************************
6405 * IDirect3DDevice7::SetClipPlane
6407 * Sets custom clipping plane
6409 * Version 7
6411 * Params:
6412 * Index: The index of the clipping plane
6413 * PlaneEquation: An equation defining the clipping plane
6415 * Returns:
6416 * D3D_OK on success
6417 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6418 * See IWineD3DDevice::SetClipPlane for more details
6420 *****************************************************************************/
6421 static HRESULT
6422 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6423 DWORD Index,
6424 D3DVALUE* PlaneEquation)
6426 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6427 HRESULT hr;
6429 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6431 if(!PlaneEquation)
6432 return DDERR_INVALIDPARAMS;
6434 wined3d_mutex_lock();
6435 hr = wined3d_device_set_clip_plane(This->wined3d_device, Index, PlaneEquation);
6436 wined3d_mutex_unlock();
6438 return hr;
6441 static HRESULT WINAPI
6442 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6443 DWORD Index,
6444 D3DVALUE* PlaneEquation)
6446 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6449 static HRESULT WINAPI
6450 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6451 DWORD Index,
6452 D3DVALUE* PlaneEquation)
6454 HRESULT hr;
6455 WORD old_fpucw;
6457 old_fpucw = d3d_fpu_setup();
6458 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6459 set_fpu_control_word(old_fpucw);
6461 return hr;
6464 /*****************************************************************************
6465 * IDirect3DDevice7::GetClipPlane
6467 * Returns the clipping plane with a specific index
6469 * Params:
6470 * Index: The index of the desired plane
6471 * PlaneEquation: Address to store the plane equation to
6473 * Returns:
6474 * D3D_OK on success
6475 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6476 * See IWineD3DDevice::GetClipPlane for more details
6478 *****************************************************************************/
6479 static HRESULT
6480 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6481 DWORD Index,
6482 D3DVALUE* PlaneEquation)
6484 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6485 HRESULT hr;
6487 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6489 if(!PlaneEquation)
6490 return DDERR_INVALIDPARAMS;
6492 wined3d_mutex_lock();
6493 hr = wined3d_device_get_clip_plane(This->wined3d_device, Index, PlaneEquation);
6494 wined3d_mutex_unlock();
6496 return hr;
6499 static HRESULT WINAPI
6500 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6501 DWORD Index,
6502 D3DVALUE* PlaneEquation)
6504 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6507 static HRESULT WINAPI
6508 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6509 DWORD Index,
6510 D3DVALUE* PlaneEquation)
6512 HRESULT hr;
6513 WORD old_fpucw;
6515 old_fpucw = d3d_fpu_setup();
6516 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6517 set_fpu_control_word(old_fpucw);
6519 return hr;
6522 /*****************************************************************************
6523 * IDirect3DDevice7::GetInfo
6525 * Retrieves some information about the device. The DirectX sdk says that
6526 * this version returns S_FALSE for all retail builds of DirectX, that's what
6527 * this implementation does.
6529 * Params:
6530 * DevInfoID: Information type requested
6531 * DevInfoStruct: Pointer to a structure to store the info to
6532 * Size: Size of the structure
6534 * Returns:
6535 * S_FALSE, because it's a non-debug driver
6537 *****************************************************************************/
6538 static HRESULT WINAPI
6539 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6540 DWORD DevInfoID,
6541 void *DevInfoStruct,
6542 DWORD Size)
6544 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6545 iface, DevInfoID, DevInfoStruct, Size);
6547 if (TRACE_ON(ddraw))
6549 TRACE(" info requested : ");
6550 switch (DevInfoID)
6552 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6553 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6554 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6555 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6559 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6562 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6563 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6564 * are not duplicated.
6566 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6567 * has already been setup for optimal d3d operation.
6569 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6570 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6571 * by Sacrifice (game). */
6572 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6574 /*** IUnknown Methods ***/
6575 IDirect3DDeviceImpl_7_QueryInterface,
6576 IDirect3DDeviceImpl_7_AddRef,
6577 IDirect3DDeviceImpl_7_Release,
6578 /*** IDirect3DDevice7 ***/
6579 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6580 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6581 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6582 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6583 IDirect3DDeviceImpl_7_GetDirect3D,
6584 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6585 IDirect3DDeviceImpl_7_GetRenderTarget,
6586 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6587 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6588 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6589 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6590 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6591 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6592 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6593 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6594 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6595 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6596 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6597 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6598 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6599 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6600 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6601 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6602 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6603 IDirect3DDeviceImpl_7_SetClipStatus,
6604 IDirect3DDeviceImpl_7_GetClipStatus,
6605 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6606 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6607 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6608 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6609 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6610 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6611 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6612 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6613 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6614 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6615 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6616 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6617 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6618 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6619 IDirect3DDeviceImpl_7_Load_FPUSetup,
6620 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6621 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6622 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6623 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6624 IDirect3DDeviceImpl_7_GetInfo
6627 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6629 /*** IUnknown Methods ***/
6630 IDirect3DDeviceImpl_7_QueryInterface,
6631 IDirect3DDeviceImpl_7_AddRef,
6632 IDirect3DDeviceImpl_7_Release,
6633 /*** IDirect3DDevice7 ***/
6634 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6635 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6636 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6637 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6638 IDirect3DDeviceImpl_7_GetDirect3D,
6639 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6640 IDirect3DDeviceImpl_7_GetRenderTarget,
6641 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6642 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6643 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6644 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6645 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6646 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6647 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6648 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6649 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6650 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6651 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6652 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6653 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6654 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6655 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6656 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6657 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6658 IDirect3DDeviceImpl_7_SetClipStatus,
6659 IDirect3DDeviceImpl_7_GetClipStatus,
6660 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6661 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6662 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6663 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6664 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6665 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6666 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6667 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6668 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6669 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6670 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6671 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6672 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6673 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6674 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6675 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6676 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6677 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6678 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6679 IDirect3DDeviceImpl_7_GetInfo
6682 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6684 /*** IUnknown Methods ***/
6685 IDirect3DDeviceImpl_3_QueryInterface,
6686 IDirect3DDeviceImpl_3_AddRef,
6687 IDirect3DDeviceImpl_3_Release,
6688 /*** IDirect3DDevice3 ***/
6689 IDirect3DDeviceImpl_3_GetCaps,
6690 IDirect3DDeviceImpl_3_GetStats,
6691 IDirect3DDeviceImpl_3_AddViewport,
6692 IDirect3DDeviceImpl_3_DeleteViewport,
6693 IDirect3DDeviceImpl_3_NextViewport,
6694 IDirect3DDeviceImpl_3_EnumTextureFormats,
6695 IDirect3DDeviceImpl_3_BeginScene,
6696 IDirect3DDeviceImpl_3_EndScene,
6697 IDirect3DDeviceImpl_3_GetDirect3D,
6698 IDirect3DDeviceImpl_3_SetCurrentViewport,
6699 IDirect3DDeviceImpl_3_GetCurrentViewport,
6700 IDirect3DDeviceImpl_3_SetRenderTarget,
6701 IDirect3DDeviceImpl_3_GetRenderTarget,
6702 IDirect3DDeviceImpl_3_Begin,
6703 IDirect3DDeviceImpl_3_BeginIndexed,
6704 IDirect3DDeviceImpl_3_Vertex,
6705 IDirect3DDeviceImpl_3_Index,
6706 IDirect3DDeviceImpl_3_End,
6707 IDirect3DDeviceImpl_3_GetRenderState,
6708 IDirect3DDeviceImpl_3_SetRenderState,
6709 IDirect3DDeviceImpl_3_GetLightState,
6710 IDirect3DDeviceImpl_3_SetLightState,
6711 IDirect3DDeviceImpl_3_SetTransform,
6712 IDirect3DDeviceImpl_3_GetTransform,
6713 IDirect3DDeviceImpl_3_MultiplyTransform,
6714 IDirect3DDeviceImpl_3_DrawPrimitive,
6715 IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6716 IDirect3DDeviceImpl_3_SetClipStatus,
6717 IDirect3DDeviceImpl_3_GetClipStatus,
6718 IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6719 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6720 IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6721 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6722 IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6723 IDirect3DDeviceImpl_3_GetTexture,
6724 IDirect3DDeviceImpl_3_SetTexture,
6725 IDirect3DDeviceImpl_3_GetTextureStageState,
6726 IDirect3DDeviceImpl_3_SetTextureStageState,
6727 IDirect3DDeviceImpl_3_ValidateDevice
6730 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6732 /*** IUnknown Methods ***/
6733 IDirect3DDeviceImpl_2_QueryInterface,
6734 IDirect3DDeviceImpl_2_AddRef,
6735 IDirect3DDeviceImpl_2_Release,
6736 /*** IDirect3DDevice2 ***/
6737 IDirect3DDeviceImpl_2_GetCaps,
6738 IDirect3DDeviceImpl_2_SwapTextureHandles,
6739 IDirect3DDeviceImpl_2_GetStats,
6740 IDirect3DDeviceImpl_2_AddViewport,
6741 IDirect3DDeviceImpl_2_DeleteViewport,
6742 IDirect3DDeviceImpl_2_NextViewport,
6743 IDirect3DDeviceImpl_2_EnumTextureFormats,
6744 IDirect3DDeviceImpl_2_BeginScene,
6745 IDirect3DDeviceImpl_2_EndScene,
6746 IDirect3DDeviceImpl_2_GetDirect3D,
6747 IDirect3DDeviceImpl_2_SetCurrentViewport,
6748 IDirect3DDeviceImpl_2_GetCurrentViewport,
6749 IDirect3DDeviceImpl_2_SetRenderTarget,
6750 IDirect3DDeviceImpl_2_GetRenderTarget,
6751 IDirect3DDeviceImpl_2_Begin,
6752 IDirect3DDeviceImpl_2_BeginIndexed,
6753 IDirect3DDeviceImpl_2_Vertex,
6754 IDirect3DDeviceImpl_2_Index,
6755 IDirect3DDeviceImpl_2_End,
6756 IDirect3DDeviceImpl_2_GetRenderState,
6757 IDirect3DDeviceImpl_2_SetRenderState,
6758 IDirect3DDeviceImpl_2_GetLightState,
6759 IDirect3DDeviceImpl_2_SetLightState,
6760 IDirect3DDeviceImpl_2_SetTransform,
6761 IDirect3DDeviceImpl_2_GetTransform,
6762 IDirect3DDeviceImpl_2_MultiplyTransform,
6763 IDirect3DDeviceImpl_2_DrawPrimitive,
6764 IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6765 IDirect3DDeviceImpl_2_SetClipStatus,
6766 IDirect3DDeviceImpl_2_GetClipStatus
6769 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6771 /*** IUnknown Methods ***/
6772 IDirect3DDeviceImpl_1_QueryInterface,
6773 IDirect3DDeviceImpl_1_AddRef,
6774 IDirect3DDeviceImpl_1_Release,
6775 /*** IDirect3DDevice1 ***/
6776 IDirect3DDeviceImpl_1_Initialize,
6777 IDirect3DDeviceImpl_1_GetCaps,
6778 IDirect3DDeviceImpl_1_SwapTextureHandles,
6779 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6780 IDirect3DDeviceImpl_1_GetStats,
6781 IDirect3DDeviceImpl_1_Execute,
6782 IDirect3DDeviceImpl_1_AddViewport,
6783 IDirect3DDeviceImpl_1_DeleteViewport,
6784 IDirect3DDeviceImpl_1_NextViewport,
6785 IDirect3DDeviceImpl_1_Pick,
6786 IDirect3DDeviceImpl_1_GetPickRecords,
6787 IDirect3DDeviceImpl_1_EnumTextureFormats,
6788 IDirect3DDeviceImpl_1_CreateMatrix,
6789 IDirect3DDeviceImpl_1_SetMatrix,
6790 IDirect3DDeviceImpl_1_GetMatrix,
6791 IDirect3DDeviceImpl_1_DeleteMatrix,
6792 IDirect3DDeviceImpl_1_BeginScene,
6793 IDirect3DDeviceImpl_1_EndScene,
6794 IDirect3DDeviceImpl_1_GetDirect3D
6797 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6799 if (!iface) return NULL;
6800 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6801 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice7_iface);
6804 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6806 if (!iface) return NULL;
6807 assert(iface->lpVtbl == &d3d_device3_vtbl);
6808 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice3_iface);
6811 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6813 if (!iface) return NULL;
6814 assert(iface->lpVtbl == &d3d_device2_vtbl);
6815 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice2_iface);
6818 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6820 if (!iface) return NULL;
6821 assert(iface->lpVtbl == &d3d_device1_vtbl);
6822 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice_iface);
6825 /*****************************************************************************
6826 * IDirect3DDeviceImpl_UpdateDepthStencil
6828 * Checks the current render target for attached depth stencils and sets the
6829 * WineD3D depth stencil accordingly.
6831 * Returns:
6832 * The depth stencil state to set if creating the device
6834 *****************************************************************************/
6835 WINED3DZBUFFERTYPE
6836 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6838 IDirectDrawSurface7 *depthStencil = NULL;
6839 IDirectDrawSurfaceImpl *dsi;
6840 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6842 IDirectDrawSurface7_GetAttachedSurface(&This->target->IDirectDrawSurface7_iface, &depthcaps, &depthStencil);
6843 if(!depthStencil)
6845 TRACE("Setting wined3d depth stencil to NULL\n");
6846 wined3d_device_set_depth_stencil(This->wined3d_device, NULL);
6847 return WINED3DZB_FALSE;
6850 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6851 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
6852 wined3d_device_set_depth_stencil(This->wined3d_device, dsi->wined3d_surface);
6854 IDirectDrawSurface7_Release(depthStencil);
6855 return WINED3DZB_TRUE;
6858 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
6860 HRESULT hr;
6862 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6863 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6864 else
6865 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
6867 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6868 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6869 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6870 device->ref = 1;
6871 device->ddraw = ddraw;
6872 device->target = target;
6873 list_init(&device->viewport_list);
6875 if (!ddraw_handle_table_init(&device->handle_table, 64))
6877 ERR("Failed to initialize handle table.\n");
6878 return DDERR_OUTOFMEMORY;
6881 device->legacyTextureBlending = FALSE;
6883 /* Create an index buffer, it's needed for indexed drawing */
6884 hr = wined3d_buffer_create_ib(ddraw->wined3d_device, 0x40000 /* Length. Don't know how long it should be */,
6885 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, NULL,
6886 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
6887 if (FAILED(hr))
6889 ERR("Failed to create an index buffer, hr %#x.\n", hr);
6890 ddraw_handle_table_destroy(&device->handle_table);
6891 return hr;
6894 /* This is for convenience. */
6895 device->wined3d_device = ddraw->wined3d_device;
6896 wined3d_device_incref(ddraw->wined3d_device);
6898 /* Render to the back buffer */
6899 hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
6900 if (FAILED(hr))
6902 ERR("Failed to set render target, hr %#x.\n", hr);
6903 wined3d_buffer_decref(device->indexbuffer);
6904 ddraw_handle_table_destroy(&device->handle_table);
6905 return hr;
6908 /* FIXME: This is broken. The target AddRef() makes some sense, because
6909 * we store a pointer during initialization, but then that's also where
6910 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6911 /* AddRef the render target. Also AddRef the render target from ddraw,
6912 * because if it is released before the app releases the D3D device, the
6913 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6915 * In most cases, those surfaces are the same anyway, but this will simply
6916 * add another ref which is released when the device is destroyed. */
6917 IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
6918 IDirectDrawSurface7_AddRef(&ddraw->d3d_target->IDirectDrawSurface7_iface);
6920 ddraw->d3ddevice = device;
6922 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3DRS_ZENABLE,
6923 IDirect3DDeviceImpl_UpdateDepthStencil(device));
6925 return D3D_OK;