credui: Convert dialogs to po files.
[wine/multimedia.git] / dlls / ddraw / device.c
blobccbdb1ac4d0e92679398ef70ae7b0350c370b7e3
1 /*
2 * Copyright (c) 1998-2004 Lionel Ulmer
3 * Copyright (c) 2002-2005 Christian Costa
4 * Copyright (c) 2006 Stefan Dösinger
5 * Copyright (c) 2008 Alexander Dorofeyev
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * IDirect3DDevice implementation, version 1, 2, 3 and 7. Rendering is relayed
22 * to WineD3D, some minimal DirectDraw specific management is handled here.
23 * The Direct3DDevice is NOT the parent of the WineD3DDevice, because d3d
24 * is initialized when DirectDraw creates the primary surface.
25 * Some type management is necessary, because some D3D types changed between
26 * D3D7 and D3D9.
30 #include "config.h"
31 #include "wine/port.h"
33 #include "ddraw_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
37 /* The device ID */
38 const GUID IID_D3DDEVICE_WineD3D = {
39 0xaef72d43,
40 0xb09a,
41 0x4b7b,
42 { 0xb7,0x98,0xc6,0x8a,0x77,0x2d,0x72,0x2a }
45 static inline void set_fpu_control_word(WORD fpucw)
47 #if defined(__i386__) && defined(__GNUC__)
48 __asm__ volatile ("fldcw %0" : : "m" (fpucw));
49 #elif defined(__i386__) && defined(_MSC_VER)
50 __asm fldcw fpucw;
51 #endif
54 static inline WORD d3d_fpu_setup(void)
56 WORD oldcw;
58 #if defined(__i386__) && defined(__GNUC__)
59 __asm__ volatile ("fnstcw %0" : "=m" (oldcw));
60 #elif defined(__i386__) && defined(_MSC_VER)
61 __asm fnstcw oldcw;
62 #else
63 static BOOL warned = FALSE;
64 if(!warned)
66 FIXME("FPUPRESERVE not implemented for this platform / compiler\n");
67 warned = TRUE;
69 return 0;
70 #endif
72 set_fpu_control_word(0x37f);
74 return oldcw;
77 /*****************************************************************************
78 * IUnknown Methods. Common for Version 1, 2, 3 and 7
79 *****************************************************************************/
81 /*****************************************************************************
82 * IDirect3DDevice7::QueryInterface
84 * Used to query other interfaces from a Direct3DDevice interface.
85 * It can return interface pointers to all Direct3DDevice versions as well
86 * as IDirectDraw and IDirect3D. For a link to QueryInterface
87 * rules see ddraw.c, IDirectDraw7::QueryInterface
89 * Exists in Version 1, 2, 3 and 7
91 * Params:
92 * refiid: Interface ID queried for
93 * obj: Used to return the interface pointer
95 * Returns:
96 * D3D_OK or E_NOINTERFACE
98 *****************************************************************************/
99 static HRESULT WINAPI
100 IDirect3DDeviceImpl_7_QueryInterface(IDirect3DDevice7 *iface,
101 REFIID refiid,
102 void **obj)
104 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
106 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(refiid), obj);
108 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
109 *obj = NULL;
111 if(!refiid)
112 return DDERR_INVALIDPARAMS;
114 if ( IsEqualGUID( &IID_IUnknown, refiid ) )
116 *obj = iface;
119 /* Check DirectDraw Interfaces. */
120 else if( IsEqualGUID( &IID_IDirectDraw7, refiid ) )
122 *obj = &This->ddraw->IDirectDraw7_iface;
123 TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
125 else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
127 *obj = &This->ddraw->IDirectDraw4_iface;
128 TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
130 else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
132 *obj = &This->ddraw->IDirectDraw2_iface;
133 TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
135 else if( IsEqualGUID( &IID_IDirectDraw, refiid ) )
137 *obj = &This->ddraw->IDirectDraw_iface;
138 TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
141 /* Direct3D */
142 else if ( IsEqualGUID( &IID_IDirect3D , refiid ) )
144 *obj = &This->ddraw->IDirect3D_iface;
145 TRACE("(%p) Returning IDirect3D interface at %p\n", This, *obj);
147 else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) )
149 *obj = &This->ddraw->IDirect3D2_iface;
150 TRACE("(%p) Returning IDirect3D2 interface at %p\n", This, *obj);
152 else if ( IsEqualGUID( &IID_IDirect3D3 , refiid ) )
154 *obj = &This->ddraw->IDirect3D3_iface;
155 TRACE("(%p) Returning IDirect3D3 interface at %p\n", This, *obj);
157 else if ( IsEqualGUID( &IID_IDirect3D7 , refiid ) )
159 *obj = &This->ddraw->IDirect3D7_iface;
160 TRACE("(%p) Returning IDirect3D7 interface at %p\n", This, *obj);
163 /* Direct3DDevice */
164 else if ( IsEqualGUID( &IID_IDirect3DDevice , refiid ) )
166 *obj = &This->IDirect3DDevice_iface;
167 TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
169 else if ( IsEqualGUID( &IID_IDirect3DDevice2 , refiid ) ) {
170 *obj = &This->IDirect3DDevice2_iface;
171 TRACE("(%p) Returning IDirect3DDevice2 interface at %p\n", This, *obj);
173 else if ( IsEqualGUID( &IID_IDirect3DDevice3 , refiid ) ) {
174 *obj = &This->IDirect3DDevice3_iface;
175 TRACE("(%p) Returning IDirect3DDevice3 interface at %p\n", This, *obj);
177 else if ( IsEqualGUID( &IID_IDirect3DDevice7 , refiid ) ) {
178 *obj = This;
179 TRACE("(%p) Returning IDirect3DDevice7 interface at %p\n", This, *obj);
182 /* Unknown interface */
183 else
185 ERR("(%p)->(%s, %p): No interface found\n", This, debugstr_guid(refiid), obj);
186 return E_NOINTERFACE;
189 /* AddRef the returned interface */
190 IUnknown_AddRef( (IUnknown *) *obj);
191 return D3D_OK;
194 static HRESULT WINAPI IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface, REFIID riid,
195 void **obj)
197 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
198 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
200 return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obj);
203 static HRESULT WINAPI IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface, REFIID riid,
204 void **obj)
206 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
207 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
209 return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obj);
212 static HRESULT WINAPI IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface, REFIID riid,
213 void **obp)
215 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
216 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
218 return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obp);
221 /*****************************************************************************
222 * IDirect3DDevice7::AddRef
224 * Increases the refcount....
225 * The most exciting Method, definitely
227 * Exists in Version 1, 2, 3 and 7
229 * Returns:
230 * The new refcount
232 *****************************************************************************/
233 static ULONG WINAPI
234 IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
236 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
237 ULONG ref = InterlockedIncrement(&This->ref);
239 TRACE("%p increasing refcount to %u.\n", This, ref);
241 return ref;
244 static ULONG WINAPI IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
246 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
247 TRACE("iface %p.\n", iface);
249 return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
252 static ULONG WINAPI IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
254 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
255 TRACE("iface %p.\n", iface);
257 return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
260 static ULONG WINAPI IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
262 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
263 TRACE("iface %p.\n", iface);
265 return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
268 /*****************************************************************************
269 * IDirect3DDevice7::Release
271 * Decreases the refcount of the interface
272 * When the refcount is reduced to 0, the object is destroyed.
274 * Exists in Version 1, 2, 3 and 7
276 * Returns:d
277 * The new refcount
279 *****************************************************************************/
280 static ULONG WINAPI
281 IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
283 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
284 ULONG ref = InterlockedDecrement(&This->ref);
286 TRACE("%p decreasing refcount to %u.\n", This, ref);
288 /* This method doesn't destroy the WineD3DDevice, because it's still in use for
289 * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
290 * when the render target is released
292 if (ref == 0)
294 DWORD i;
296 wined3d_mutex_lock();
298 /* There is no need to unset any resources here, wined3d will take
299 * care of that on Uninit3D(). */
301 /* Free the index buffer. */
302 wined3d_buffer_decref(This->indexbuffer);
304 /* Set the device up to render to the front buffer since the back
305 * buffer will vanish soon. */
306 wined3d_device_set_render_target(This->wined3d_device, 0,
307 This->ddraw->wined3d_frontbuffer, TRUE);
309 /* Release the WineD3DDevice. This won't destroy it. */
310 if (!wined3d_device_decref(This->wined3d_device))
311 ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This->wined3d_device);
313 /* The texture handles should be unset by now, but there might be some bits
314 * missing in our reference counting(needs test). Do a sanity check. */
315 for (i = 0; i < This->handle_table.entry_count; ++i)
317 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
319 switch (entry->type)
321 case DDRAW_HANDLE_FREE:
322 break;
324 case DDRAW_HANDLE_MATERIAL:
326 IDirect3DMaterialImpl *m = entry->object;
327 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
328 m->Handle = 0;
329 break;
332 case DDRAW_HANDLE_MATRIX:
334 /* No FIXME here because this might happen because of sloppy applications. */
335 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
336 IDirect3DDevice_DeleteMatrix(&This->IDirect3DDevice_iface, i + 1);
337 break;
340 case DDRAW_HANDLE_STATEBLOCK:
342 /* No FIXME here because this might happen because of sloppy applications. */
343 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
344 IDirect3DDevice7_DeleteStateBlock(iface, i + 1);
345 break;
348 case DDRAW_HANDLE_SURFACE:
350 IDirectDrawSurfaceImpl *surf = entry->object;
351 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
352 surf->Handle = 0;
353 break;
356 default:
357 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
358 break;
362 ddraw_handle_table_destroy(&This->handle_table);
364 TRACE("Releasing target %p %p\n", This->target, This->ddraw->d3d_target);
365 /* Release the render target and the WineD3D render target
366 * (See IDirect3D7::CreateDevice for more comments on this)
368 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
369 IDirectDrawSurface7_Release(&This->ddraw->d3d_target->IDirectDrawSurface7_iface);
370 TRACE("Target release done\n");
372 This->ddraw->d3ddevice = NULL;
374 /* Now free the structure */
375 HeapFree(GetProcessHeap(), 0, This);
376 wined3d_mutex_unlock();
379 TRACE("Done\n");
380 return ref;
383 static ULONG WINAPI IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
385 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
386 TRACE("iface %p.\n", iface);
388 return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
391 static ULONG WINAPI IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
393 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
394 TRACE("iface %p.\n", iface);
396 return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
399 static ULONG WINAPI IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
401 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
402 TRACE("iface %p.\n", iface);
404 return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
407 /*****************************************************************************
408 * IDirect3DDevice Methods
409 *****************************************************************************/
411 /*****************************************************************************
412 * IDirect3DDevice::Initialize
414 * Initializes a Direct3DDevice. This implementation is a no-op, as all
415 * initialization is done at create time.
417 * Exists in Version 1
419 * Parameters:
420 * No idea what they mean, as the MSDN page is gone
422 * Returns: DD_OK
424 *****************************************************************************/
425 static HRESULT WINAPI
426 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
427 IDirect3D *Direct3D, GUID *guid,
428 D3DDEVICEDESC *Desc)
430 /* It shouldn't be crucial, but print a FIXME, I'm interested if
431 * any game calls it and when. */
432 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
433 iface, Direct3D, debugstr_guid(guid), Desc);
435 return D3D_OK;
438 /*****************************************************************************
439 * IDirect3DDevice7::GetCaps
441 * Retrieves the device's capabilities
443 * This implementation is used for Version 7 only, the older versions have
444 * their own implementation.
446 * Parameters:
447 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
449 * Returns:
450 * D3D_OK on success
451 * D3DERR_* if a problem occurs. See WineD3D
453 *****************************************************************************/
454 static HRESULT
455 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
456 D3DDEVICEDESC7 *Desc)
458 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
459 D3DDEVICEDESC OldDesc;
461 TRACE("iface %p, device_desc %p.\n", iface, Desc);
463 /* Call the same function used by IDirect3D, this saves code */
464 return IDirect3DImpl_GetCaps(This->ddraw->wineD3D, &OldDesc, Desc);
467 static HRESULT WINAPI
468 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
469 D3DDEVICEDESC7 *Desc)
471 return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
474 static HRESULT WINAPI
475 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
476 D3DDEVICEDESC7 *Desc)
478 HRESULT hr;
479 WORD old_fpucw;
481 old_fpucw = d3d_fpu_setup();
482 hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
483 set_fpu_control_word(old_fpucw);
485 return hr;
487 /*****************************************************************************
488 * IDirect3DDevice3::GetCaps
490 * Retrieves the capabilities of the hardware device and the emulation
491 * device. For Wine, hardware and emulation are the same (it's all HW).
493 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
495 * Parameters:
496 * HWDesc: Structure to fill with the HW caps
497 * HelDesc: Structure to fill with the hardware emulation caps
499 * Returns:
500 * D3D_OK on success
501 * D3DERR_* if a problem occurs. See WineD3D
503 *****************************************************************************/
504 static HRESULT WINAPI
505 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
506 D3DDEVICEDESC *HWDesc,
507 D3DDEVICEDESC *HelDesc)
509 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
510 D3DDEVICEDESC7 newDesc;
511 HRESULT hr;
513 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
515 hr = IDirect3DImpl_GetCaps(This->ddraw->wineD3D, HWDesc, &newDesc);
516 if(hr != D3D_OK) return hr;
518 *HelDesc = *HWDesc;
519 return D3D_OK;
522 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
523 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
525 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
526 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
527 return IDirect3DDevice3_GetCaps(&This->IDirect3DDevice3_iface, D3DHWDevDesc, D3DHELDevDesc);
530 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
531 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
533 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
534 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
535 return IDirect3DDevice3_GetCaps(&This->IDirect3DDevice3_iface, D3DHWDevDesc, D3DHELDevDesc);
538 /*****************************************************************************
539 * IDirect3DDevice2::SwapTextureHandles
541 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
543 * Parameters:
544 * Tex1, Tex2: The 2 Textures to swap
546 * Returns:
547 * D3D_OK
549 *****************************************************************************/
550 static HRESULT WINAPI
551 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
552 IDirect3DTexture2 *Tex1,
553 IDirect3DTexture2 *Tex2)
555 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
556 IDirectDrawSurfaceImpl *surf1 = unsafe_impl_from_IDirect3DTexture2(Tex1);
557 IDirectDrawSurfaceImpl *surf2 = unsafe_impl_from_IDirect3DTexture2(Tex2);
558 DWORD h1, h2;
560 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, Tex1, Tex2);
562 wined3d_mutex_lock();
564 h1 = surf1->Handle - 1;
565 h2 = surf2->Handle - 1;
566 This->handle_table.entries[h1].object = surf2;
567 This->handle_table.entries[h2].object = surf1;
568 surf2->Handle = h1 + 1;
569 surf1->Handle = h2 + 1;
571 wined3d_mutex_unlock();
573 return D3D_OK;
576 static HRESULT WINAPI IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
577 IDirect3DTexture *D3DTex1, IDirect3DTexture *D3DTex2)
579 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
580 IDirectDrawSurfaceImpl *surf1 = unsafe_impl_from_IDirect3DTexture(D3DTex1);
581 IDirectDrawSurfaceImpl *surf2 = unsafe_impl_from_IDirect3DTexture(D3DTex2);
582 IDirect3DTexture2 *t1 = surf1 ? &surf1->IDirect3DTexture2_iface : NULL;
583 IDirect3DTexture2 *t2 = surf2 ? &surf2->IDirect3DTexture2_iface : NULL;
585 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, D3DTex1, D3DTex2);
587 return IDirect3DDevice2_SwapTextureHandles(&This->IDirect3DDevice2_iface, t1, t2);
590 /*****************************************************************************
591 * IDirect3DDevice3::GetStats
593 * This method seems to retrieve some stats from the device.
594 * The MSDN documentation doesn't exist any more, but the D3DSTATS
595 * structure suggests that the amount of drawn primitives and processed
596 * vertices is returned.
598 * Exists in Version 1, 2 and 3
600 * Parameters:
601 * Stats: Pointer to a D3DSTATS structure to be filled
603 * Returns:
604 * D3D_OK on success
605 * DDERR_INVALIDPARAMS if Stats == NULL
607 *****************************************************************************/
608 static HRESULT WINAPI
609 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
610 D3DSTATS *Stats)
612 FIXME("iface %p, stats %p stub!\n", iface, Stats);
614 if(!Stats)
615 return DDERR_INVALIDPARAMS;
617 /* Fill the Stats with 0 */
618 Stats->dwTrianglesDrawn = 0;
619 Stats->dwLinesDrawn = 0;
620 Stats->dwPointsDrawn = 0;
621 Stats->dwSpansDrawn = 0;
622 Stats->dwVerticesProcessed = 0;
624 return D3D_OK;
627 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *Stats)
629 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
631 TRACE("iface %p, stats %p.\n", iface, Stats);
633 return IDirect3DDevice3_GetStats(&This->IDirect3DDevice3_iface, Stats);
636 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface, D3DSTATS *Stats)
638 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
640 TRACE("iface %p, stats %p.\n", iface, Stats);
642 return IDirect3DDevice3_GetStats(&This->IDirect3DDevice3_iface, Stats);
645 /*****************************************************************************
646 * IDirect3DDevice::CreateExecuteBuffer
648 * Creates an IDirect3DExecuteBuffer, used for rendering with a
649 * Direct3DDevice.
651 * Version 1 only.
653 * Params:
654 * Desc: Buffer description
655 * ExecuteBuffer: Address to return the Interface pointer at
656 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
657 * support
659 * Returns:
660 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
661 * DDERR_OUTOFMEMORY if we ran out of memory
662 * D3D_OK on success
664 *****************************************************************************/
665 static HRESULT WINAPI
666 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
667 D3DEXECUTEBUFFERDESC *Desc,
668 IDirect3DExecuteBuffer **ExecuteBuffer,
669 IUnknown *UnkOuter)
671 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
672 IDirect3DExecuteBufferImpl* object;
673 HRESULT hr;
675 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
676 iface, Desc, ExecuteBuffer, UnkOuter);
678 if(UnkOuter)
679 return CLASS_E_NOAGGREGATION;
681 /* Allocate the new Execute Buffer */
682 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
683 if(!object)
685 ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
686 return DDERR_OUTOFMEMORY;
689 hr = d3d_execute_buffer_init(object, This, Desc);
690 if (FAILED(hr))
692 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
693 HeapFree(GetProcessHeap(), 0, object);
694 return hr;
697 *ExecuteBuffer = &object->IDirect3DExecuteBuffer_iface;
699 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
701 return D3D_OK;
704 /*****************************************************************************
705 * IDirect3DDevice::Execute
707 * Executes all the stuff in an execute buffer.
709 * Params:
710 * ExecuteBuffer: The buffer to execute
711 * Viewport: The viewport used for rendering
712 * Flags: Some flags
714 * Returns:
715 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
716 * D3D_OK on success
718 *****************************************************************************/
719 static HRESULT WINAPI IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
720 IDirect3DExecuteBuffer *ExecuteBuffer, IDirect3DViewport *Viewport, DWORD Flags)
722 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
723 IDirect3DExecuteBufferImpl *buffer = unsafe_impl_from_IDirect3DExecuteBuffer(ExecuteBuffer);
724 IDirect3DViewportImpl *Direct3DViewportImpl = unsafe_impl_from_IDirect3DViewport(Viewport);
725 HRESULT hr;
727 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, Viewport, Flags);
729 if(!buffer)
730 return DDERR_INVALIDPARAMS;
732 /* Execute... */
733 wined3d_mutex_lock();
734 hr = d3d_execute_buffer_execute(buffer, This, Direct3DViewportImpl);
735 wined3d_mutex_unlock();
737 return hr;
740 /*****************************************************************************
741 * IDirect3DDevice3::AddViewport
743 * Add a Direct3DViewport to the device's viewport list. These viewports
744 * are wrapped to IDirect3DDevice7 viewports in viewport.c
746 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
747 * are the same interfaces.
749 * Params:
750 * Viewport: The viewport to add
752 * Returns:
753 * DDERR_INVALIDPARAMS if Viewport == NULL
754 * D3D_OK on success
756 *****************************************************************************/
757 static HRESULT WINAPI
758 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
759 IDirect3DViewport3 *Viewport)
761 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
762 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(Viewport);
764 TRACE("iface %p, viewport %p.\n", iface, Viewport);
766 /* Sanity check */
767 if(!vp)
768 return DDERR_INVALIDPARAMS;
770 wined3d_mutex_lock();
771 list_add_head(&This->viewport_list, &vp->entry);
772 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
773 so set active_device here. */
774 wined3d_mutex_unlock();
776 return D3D_OK;
779 static HRESULT WINAPI IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
780 IDirect3DViewport2 *Direct3DViewport2)
782 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
783 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
785 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
787 return IDirect3DDevice3_AddViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
790 static HRESULT WINAPI IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
791 IDirect3DViewport *Direct3DViewport)
793 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
794 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport(Direct3DViewport);
796 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
798 return IDirect3DDevice3_AddViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
801 /*****************************************************************************
802 * IDirect3DDevice3::DeleteViewport
804 * Deletes a Direct3DViewport from the device's viewport list.
806 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
807 * are equal.
809 * Params:
810 * Viewport: The viewport to delete
812 * Returns:
813 * D3D_OK on success
814 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
816 *****************************************************************************/
817 static HRESULT WINAPI IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
819 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
820 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
822 TRACE("iface %p, viewport %p.\n", iface, viewport);
824 wined3d_mutex_lock();
826 if (vp->active_device != This)
828 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
829 wined3d_mutex_unlock();
830 return DDERR_INVALIDPARAMS;
833 vp->active_device = NULL;
834 list_remove(&vp->entry);
836 wined3d_mutex_unlock();
838 return D3D_OK;
841 static HRESULT WINAPI IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
842 IDirect3DViewport2 *Direct3DViewport2)
844 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
845 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
847 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
849 return IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
852 static HRESULT WINAPI IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
853 IDirect3DViewport *Direct3DViewport)
855 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
856 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport(Direct3DViewport);
858 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
860 return IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
863 /*****************************************************************************
864 * IDirect3DDevice3::NextViewport
866 * Returns a viewport from the viewport list, depending on the
867 * passed viewport and the flags.
869 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
870 * are equal.
872 * Params:
873 * Viewport: Viewport to use for beginning the search
874 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
876 * Returns:
877 * D3D_OK on success
878 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
880 *****************************************************************************/
881 static HRESULT WINAPI
882 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
883 IDirect3DViewport3 *Viewport3,
884 IDirect3DViewport3 **lplpDirect3DViewport3,
885 DWORD Flags)
887 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
888 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(Viewport3);
889 IDirect3DViewportImpl *next;
890 struct list *entry;
892 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
893 iface, Viewport3, lplpDirect3DViewport3, Flags);
895 if(!vp)
897 *lplpDirect3DViewport3 = NULL;
898 return DDERR_INVALIDPARAMS;
902 wined3d_mutex_lock();
903 switch (Flags)
905 case D3DNEXT_NEXT:
906 entry = list_next(&This->viewport_list, &vp->entry);
907 break;
909 case D3DNEXT_HEAD:
910 entry = list_head(&This->viewport_list);
911 break;
913 case D3DNEXT_TAIL:
914 entry = list_tail(&This->viewport_list);
915 break;
917 default:
918 WARN("Invalid flags %#x.\n", Flags);
919 *lplpDirect3DViewport3 = NULL;
920 wined3d_mutex_unlock();
921 return DDERR_INVALIDPARAMS;
924 if (entry)
926 next = LIST_ENTRY(entry, IDirect3DViewportImpl, entry);
927 *lplpDirect3DViewport3 = &next->IDirect3DViewport3_iface;
929 else
930 *lplpDirect3DViewport3 = NULL;
932 wined3d_mutex_unlock();
934 return D3D_OK;
937 static HRESULT WINAPI IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
938 IDirect3DViewport2 *Viewport2, IDirect3DViewport2 **lplpDirect3DViewport2, DWORD Flags)
940 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
941 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Viewport2);
942 IDirect3DViewport3 *res;
943 HRESULT hr;
945 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
946 iface, Viewport2, lplpDirect3DViewport2, Flags);
948 hr = IDirect3DDevice3_NextViewport(&This->IDirect3DDevice3_iface,
949 &vp->IDirect3DViewport3_iface, &res, Flags);
950 *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
951 return hr;
954 static HRESULT WINAPI IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
955 IDirect3DViewport *Viewport, IDirect3DViewport **lplpDirect3DViewport, DWORD Flags)
957 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
958 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport(Viewport);
959 IDirect3DViewport3 *res;
960 HRESULT hr;
962 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
963 iface, Viewport, lplpDirect3DViewport, Flags);
965 hr = IDirect3DDevice3_NextViewport(&This->IDirect3DDevice3_iface,
966 &vp->IDirect3DViewport3_iface, &res, Flags);
967 *lplpDirect3DViewport = (IDirect3DViewport *)res;
968 return hr;
971 /*****************************************************************************
972 * IDirect3DDevice::Pick
974 * Executes an execute buffer without performing rendering. Instead, a
975 * list of primitives that intersect with (x1,y1) of the passed rectangle
976 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
977 * this list.
979 * Version 1 only
981 * Params:
982 * ExecuteBuffer: Buffer to execute
983 * Viewport: Viewport to use for execution
984 * Flags: None are defined, according to the SDK
985 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
986 * x2 and y2 are ignored.
988 * Returns:
989 * D3D_OK because it's a stub
991 *****************************************************************************/
992 static HRESULT WINAPI
993 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
994 IDirect3DExecuteBuffer *ExecuteBuffer,
995 IDirect3DViewport *Viewport,
996 DWORD Flags,
997 D3DRECT *Rect)
999 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
1000 iface, ExecuteBuffer, Viewport, Flags, wine_dbgstr_rect((RECT *)Rect));
1002 return D3D_OK;
1005 /*****************************************************************************
1006 * IDirect3DDevice::GetPickRecords
1008 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1010 * Version 1 only
1012 * Params:
1013 * Count: Pointer to a DWORD containing the numbers of pick records to
1014 * retrieve
1015 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1017 * Returns:
1018 * D3D_OK, because it's a stub
1020 *****************************************************************************/
1021 static HRESULT WINAPI
1022 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1023 DWORD *Count,
1024 D3DPICKRECORD *D3DPickRec)
1026 FIXME("iface %p, count %p, records %p stub!\n", iface, Count, D3DPickRec);
1028 return D3D_OK;
1031 /*****************************************************************************
1032 * IDirect3DDevice7::EnumTextureformats
1034 * Enumerates the supported texture formats. It has a list of all possible
1035 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1036 * WineD3D supports it. If so, then it is passed to the app.
1038 * This is for Version 7 and 3, older versions have a different
1039 * callback function and their own implementation
1041 * Params:
1042 * Callback: Callback to call for each enumerated format
1043 * Arg: Argument to pass to the callback
1045 * Returns:
1046 * D3D_OK on success
1047 * DDERR_INVALIDPARAMS if Callback == NULL
1049 *****************************************************************************/
1050 static HRESULT
1051 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1052 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1053 void *Arg)
1055 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1056 struct wined3d_display_mode mode;
1057 HRESULT hr;
1058 unsigned int i;
1060 static const enum wined3d_format_id FormatList[] =
1062 /* 16 bit */
1063 WINED3DFMT_B5G5R5X1_UNORM,
1064 WINED3DFMT_B5G5R5A1_UNORM,
1065 WINED3DFMT_B4G4R4A4_UNORM,
1066 WINED3DFMT_B5G6R5_UNORM,
1067 /* 32 bit */
1068 WINED3DFMT_B8G8R8X8_UNORM,
1069 WINED3DFMT_B8G8R8A8_UNORM,
1070 /* 8 bit */
1071 WINED3DFMT_B2G3R3_UNORM,
1072 WINED3DFMT_P8_UINT,
1073 /* FOURCC codes */
1074 WINED3DFMT_DXT1,
1075 WINED3DFMT_DXT3,
1076 WINED3DFMT_DXT5,
1079 static const enum wined3d_format_id BumpFormatList[] =
1081 WINED3DFMT_R8G8_SNORM,
1082 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1083 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1084 WINED3DFMT_R16G16_SNORM,
1085 WINED3DFMT_R10G11B11_SNORM,
1086 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1089 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1091 if(!Callback)
1092 return DDERR_INVALIDPARAMS;
1094 wined3d_mutex_lock();
1096 memset(&mode, 0, sizeof(mode));
1097 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1098 if (FAILED(hr))
1100 wined3d_mutex_unlock();
1101 WARN("Cannot get the current adapter format\n");
1102 return hr;
1105 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1107 hr = wined3d_check_device_format(This->ddraw->wineD3D, WINED3DADAPTER_DEFAULT, WINED3DDEVTYPE_HAL,
1108 mode.format_id, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1109 if (hr == D3D_OK)
1111 DDPIXELFORMAT pformat;
1113 memset(&pformat, 0, sizeof(pformat));
1114 pformat.dwSize = sizeof(pformat);
1115 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1117 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1118 hr = Callback(&pformat, Arg);
1119 if(hr != DDENUMRET_OK)
1121 TRACE("Format enumeration cancelled by application\n");
1122 wined3d_mutex_unlock();
1123 return D3D_OK;
1128 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1130 hr = wined3d_check_device_format(This->ddraw->wineD3D, WINED3DADAPTER_DEFAULT,
1131 WINED3DDEVTYPE_HAL, mode.format_id, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1132 WINED3DRTYPE_TEXTURE, BumpFormatList[i], SURFACE_OPENGL);
1133 if (hr == D3D_OK)
1135 DDPIXELFORMAT pformat;
1137 memset(&pformat, 0, sizeof(pformat));
1138 pformat.dwSize = sizeof(pformat);
1139 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1141 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1142 hr = Callback(&pformat, Arg);
1143 if(hr != DDENUMRET_OK)
1145 TRACE("Format enumeration cancelled by application\n");
1146 wined3d_mutex_unlock();
1147 return D3D_OK;
1151 TRACE("End of enumeration\n");
1152 wined3d_mutex_unlock();
1154 return D3D_OK;
1157 static HRESULT WINAPI
1158 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1159 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1160 void *Arg)
1162 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1165 static HRESULT WINAPI
1166 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1167 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1168 void *Arg)
1170 HRESULT hr;
1171 WORD old_fpucw;
1173 old_fpucw = d3d_fpu_setup();
1174 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1175 set_fpu_control_word(old_fpucw);
1177 return hr;
1180 static HRESULT WINAPI IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1181 LPD3DENUMPIXELFORMATSCALLBACK Callback, void *Arg)
1183 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1185 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1187 return IDirect3DDevice7_EnumTextureFormats(&This->IDirect3DDevice7_iface, Callback, Arg);
1190 /*****************************************************************************
1191 * IDirect3DDevice2::EnumTextureformats
1193 * EnumTextureFormats for Version 1 and 2, see
1194 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1196 * This version has a different callback and does not enumerate FourCC
1197 * formats
1199 *****************************************************************************/
1200 static HRESULT WINAPI
1201 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1202 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1203 void *Arg)
1205 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1206 struct wined3d_display_mode mode;
1207 HRESULT hr;
1208 unsigned int i;
1210 static const enum wined3d_format_id FormatList[] =
1212 /* 16 bit */
1213 WINED3DFMT_B5G5R5X1_UNORM,
1214 WINED3DFMT_B5G5R5A1_UNORM,
1215 WINED3DFMT_B4G4R4A4_UNORM,
1216 WINED3DFMT_B5G6R5_UNORM,
1217 /* 32 bit */
1218 WINED3DFMT_B8G8R8X8_UNORM,
1219 WINED3DFMT_B8G8R8A8_UNORM,
1220 /* 8 bit */
1221 WINED3DFMT_B2G3R3_UNORM,
1222 WINED3DFMT_P8_UINT,
1223 /* FOURCC codes - Not in this version*/
1226 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1228 if(!Callback)
1229 return DDERR_INVALIDPARAMS;
1231 wined3d_mutex_lock();
1233 memset(&mode, 0, sizeof(mode));
1234 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1235 if (FAILED(hr))
1237 wined3d_mutex_unlock();
1238 WARN("Cannot get the current adapter format\n");
1239 return hr;
1242 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1244 hr = wined3d_check_device_format(This->ddraw->wineD3D, 0, WINED3DDEVTYPE_HAL,
1245 mode.format_id, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1246 if (hr == D3D_OK)
1248 DDSURFACEDESC sdesc;
1250 memset(&sdesc, 0, sizeof(sdesc));
1251 sdesc.dwSize = sizeof(sdesc);
1252 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1253 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1254 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1255 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1257 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1258 hr = Callback(&sdesc, Arg);
1259 if(hr != DDENUMRET_OK)
1261 TRACE("Format enumeration cancelled by application\n");
1262 wined3d_mutex_unlock();
1263 return D3D_OK;
1267 TRACE("End of enumeration\n");
1268 wined3d_mutex_unlock();
1270 return D3D_OK;
1273 static HRESULT WINAPI IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1274 LPD3DENUMTEXTUREFORMATSCALLBACK Callback, void *Arg)
1276 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1278 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1280 return IDirect3DDevice2_EnumTextureFormats(&This->IDirect3DDevice2_iface, Callback, Arg);
1283 /*****************************************************************************
1284 * IDirect3DDevice::CreateMatrix
1286 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1287 * allocated for the handle.
1289 * Version 1 only
1291 * Params
1292 * D3DMatHandle: Address to return the handle at
1294 * Returns:
1295 * D3D_OK on success
1296 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1298 *****************************************************************************/
1299 static HRESULT WINAPI
1300 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1302 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1303 D3DMATRIX *Matrix;
1304 DWORD h;
1306 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1308 if(!D3DMatHandle)
1309 return DDERR_INVALIDPARAMS;
1311 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1312 if(!Matrix)
1314 ERR("Out of memory when allocating a D3DMATRIX\n");
1315 return DDERR_OUTOFMEMORY;
1318 wined3d_mutex_lock();
1320 h = ddraw_allocate_handle(&This->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1321 if (h == DDRAW_INVALID_HANDLE)
1323 ERR("Failed to allocate a matrix handle.\n");
1324 HeapFree(GetProcessHeap(), 0, Matrix);
1325 wined3d_mutex_unlock();
1326 return DDERR_OUTOFMEMORY;
1329 *D3DMatHandle = h + 1;
1331 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1333 wined3d_mutex_unlock();
1335 return D3D_OK;
1338 /*****************************************************************************
1339 * IDirect3DDevice::SetMatrix
1341 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1342 * allocated for the handle
1344 * Version 1 only
1346 * Params:
1347 * D3DMatHandle: Handle to set the matrix to
1348 * D3DMatrix: Matrix to set
1350 * Returns:
1351 * D3D_OK on success
1352 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1353 * to set is NULL
1355 *****************************************************************************/
1356 static HRESULT WINAPI
1357 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1358 D3DMATRIXHANDLE D3DMatHandle,
1359 D3DMATRIX *D3DMatrix)
1361 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1362 D3DMATRIX *m;
1364 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1366 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1368 wined3d_mutex_lock();
1370 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1371 if (!m)
1373 WARN("Invalid matrix handle.\n");
1374 wined3d_mutex_unlock();
1375 return DDERR_INVALIDPARAMS;
1378 if (TRACE_ON(ddraw))
1379 dump_D3DMATRIX(D3DMatrix);
1381 *m = *D3DMatrix;
1383 if (D3DMatHandle == This->world)
1384 wined3d_device_set_transform(This->wined3d_device,
1385 WINED3DTS_WORLDMATRIX(0), (struct wined3d_matrix *)D3DMatrix);
1387 if (D3DMatHandle == This->view)
1388 wined3d_device_set_transform(This->wined3d_device,
1389 WINED3DTS_VIEW, (struct wined3d_matrix *)D3DMatrix);
1391 if (D3DMatHandle == This->proj)
1392 wined3d_device_set_transform(This->wined3d_device,
1393 WINED3DTS_PROJECTION, (struct wined3d_matrix *)D3DMatrix);
1395 wined3d_mutex_unlock();
1397 return D3D_OK;
1400 /*****************************************************************************
1401 * IDirect3DDevice::GetMatrix
1403 * Returns the content of a D3DMATRIX handle
1405 * Version 1 only
1407 * Params:
1408 * D3DMatHandle: Matrix handle to read the content from
1409 * D3DMatrix: Address to store the content at
1411 * Returns:
1412 * D3D_OK on success
1413 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1415 *****************************************************************************/
1416 static HRESULT WINAPI
1417 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1418 D3DMATRIXHANDLE D3DMatHandle,
1419 D3DMATRIX *D3DMatrix)
1421 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1422 D3DMATRIX *m;
1424 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1426 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1428 wined3d_mutex_lock();
1430 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1431 if (!m)
1433 WARN("Invalid matrix handle.\n");
1434 wined3d_mutex_unlock();
1435 return DDERR_INVALIDPARAMS;
1438 *D3DMatrix = *m;
1440 wined3d_mutex_unlock();
1442 return D3D_OK;
1445 /*****************************************************************************
1446 * IDirect3DDevice::DeleteMatrix
1448 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1450 * Version 1 only
1452 * Params:
1453 * D3DMatHandle: Handle to destroy
1455 * Returns:
1456 * D3D_OK on success
1457 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1459 *****************************************************************************/
1460 static HRESULT WINAPI
1461 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1462 D3DMATRIXHANDLE D3DMatHandle)
1464 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1465 D3DMATRIX *m;
1467 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1469 wined3d_mutex_lock();
1471 m = ddraw_free_handle(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1472 if (!m)
1474 WARN("Invalid matrix handle.\n");
1475 wined3d_mutex_unlock();
1476 return DDERR_INVALIDPARAMS;
1479 wined3d_mutex_unlock();
1481 HeapFree(GetProcessHeap(), 0, m);
1483 return D3D_OK;
1486 /*****************************************************************************
1487 * IDirect3DDevice7::BeginScene
1489 * This method must be called before any rendering is performed.
1490 * IDirect3DDevice::EndScene has to be called after the scene is complete
1492 * Version 1, 2, 3 and 7
1494 * Returns:
1495 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1496 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1497 * started scene).
1499 *****************************************************************************/
1500 static HRESULT
1501 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1503 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1504 HRESULT hr;
1506 TRACE("iface %p.\n", iface);
1508 wined3d_mutex_lock();
1509 hr = wined3d_device_begin_scene(This->wined3d_device);
1510 wined3d_mutex_unlock();
1512 if(hr == WINED3D_OK) return D3D_OK;
1513 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1516 static HRESULT WINAPI
1517 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1519 return IDirect3DDeviceImpl_7_BeginScene(iface);
1522 static HRESULT WINAPI
1523 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1525 HRESULT hr;
1526 WORD old_fpucw;
1528 old_fpucw = d3d_fpu_setup();
1529 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1530 set_fpu_control_word(old_fpucw);
1532 return hr;
1535 static HRESULT WINAPI IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1537 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1538 TRACE("iface %p.\n", iface);
1540 return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
1543 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1545 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1546 TRACE("iface %p.\n", iface);
1548 return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
1551 static HRESULT WINAPI IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1553 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1554 TRACE("iface %p.\n", iface);
1556 return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
1559 /*****************************************************************************
1560 * IDirect3DDevice7::EndScene
1562 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1563 * This method must be called after rendering is finished.
1565 * Version 1, 2, 3 and 7
1567 * Returns:
1568 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1569 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1570 * that only if the scene was already ended.
1572 *****************************************************************************/
1573 static HRESULT
1574 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1576 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1577 HRESULT hr;
1579 TRACE("iface %p.\n", iface);
1581 wined3d_mutex_lock();
1582 hr = wined3d_device_end_scene(This->wined3d_device);
1583 wined3d_mutex_unlock();
1585 if(hr == WINED3D_OK) return D3D_OK;
1586 else return D3DERR_SCENE_NOT_IN_SCENE;
1589 static HRESULT WINAPI DECLSPEC_HOTPATCH
1590 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1592 return IDirect3DDeviceImpl_7_EndScene(iface);
1595 static HRESULT WINAPI DECLSPEC_HOTPATCH
1596 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1598 HRESULT hr;
1599 WORD old_fpucw;
1601 old_fpucw = d3d_fpu_setup();
1602 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1603 set_fpu_control_word(old_fpucw);
1605 return hr;
1608 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1610 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1611 TRACE("iface %p.\n", iface);
1613 return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
1616 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1618 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1619 TRACE("iface %p.\n", iface);
1621 return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
1624 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1626 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1627 TRACE("iface %p.\n", iface);
1629 return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
1632 /*****************************************************************************
1633 * IDirect3DDevice7::GetDirect3D
1635 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1636 * this device.
1638 * Params:
1639 * Direct3D7: Address to store the interface pointer at
1641 * Returns:
1642 * D3D_OK on success
1643 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1645 *****************************************************************************/
1646 static HRESULT WINAPI
1647 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1648 IDirect3D7 **Direct3D7)
1650 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1652 TRACE("iface %p, d3d %p.\n", iface, Direct3D7);
1654 if(!Direct3D7)
1655 return DDERR_INVALIDPARAMS;
1657 *Direct3D7 = &This->ddraw->IDirect3D7_iface;
1658 IDirect3D7_AddRef(*Direct3D7);
1660 TRACE(" returning interface %p\n", *Direct3D7);
1661 return D3D_OK;
1664 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1665 IDirect3D3 **Direct3D3)
1667 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1669 TRACE("iface %p, d3d %p.\n", iface, Direct3D3);
1671 if(!Direct3D3)
1672 return DDERR_INVALIDPARAMS;
1674 IDirect3D3_AddRef(&This->ddraw->IDirect3D3_iface);
1675 *Direct3D3 = &This->ddraw->IDirect3D3_iface;
1676 TRACE(" returning interface %p\n", *Direct3D3);
1677 return D3D_OK;
1680 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1681 IDirect3D2 **Direct3D2)
1683 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1685 TRACE("iface %p, d3d %p.\n", iface, Direct3D2);
1687 if(!Direct3D2)
1688 return DDERR_INVALIDPARAMS;
1690 IDirect3D2_AddRef(&This->ddraw->IDirect3D2_iface);
1691 *Direct3D2 = &This->ddraw->IDirect3D2_iface;
1692 TRACE(" returning interface %p\n", *Direct3D2);
1693 return D3D_OK;
1696 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1697 IDirect3D **Direct3D)
1699 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1701 TRACE("iface %p, d3d %p.\n", iface, Direct3D);
1703 if(!Direct3D)
1704 return DDERR_INVALIDPARAMS;
1706 IDirect3D_AddRef(&This->ddraw->IDirect3D_iface);
1707 *Direct3D = &This->ddraw->IDirect3D_iface;
1708 TRACE(" returning interface %p\n", *Direct3D);
1709 return D3D_OK;
1712 /*****************************************************************************
1713 * IDirect3DDevice3::SetCurrentViewport
1715 * Sets a Direct3DViewport as the current viewport.
1716 * For the thunks note that all viewport interface versions are equal
1718 * Params:
1719 * Direct3DViewport3: The viewport to set
1721 * Version 2 and 3
1723 * Returns:
1724 * D3D_OK on success
1725 * (Is a NULL viewport valid?)
1727 *****************************************************************************/
1728 static HRESULT WINAPI
1729 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1730 IDirect3DViewport3 *Direct3DViewport3)
1732 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1733 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(Direct3DViewport3);
1735 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1737 wined3d_mutex_lock();
1738 /* Do nothing if the specified viewport is the same as the current one */
1739 if (This->current_viewport == vp )
1741 wined3d_mutex_unlock();
1742 return D3D_OK;
1745 if (vp->active_device != This)
1747 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1748 wined3d_mutex_unlock();
1749 return DDERR_INVALIDPARAMS;
1752 /* Release previous viewport and AddRef the new one */
1753 if (This->current_viewport)
1755 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1756 &This->current_viewport->IDirect3DViewport3_iface);
1757 IDirect3DViewport3_Release(&This->current_viewport->IDirect3DViewport3_iface);
1759 IDirect3DViewport3_AddRef(Direct3DViewport3);
1761 /* Set this viewport as the current viewport */
1762 This->current_viewport = vp;
1764 /* Activate this viewport */
1765 viewport_activate(This->current_viewport, FALSE);
1767 wined3d_mutex_unlock();
1769 return D3D_OK;
1772 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1773 IDirect3DViewport2 *Direct3DViewport2)
1775 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1776 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
1778 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1780 return IDirect3DDevice3_SetCurrentViewport(&This->IDirect3DDevice3_iface,
1781 &vp->IDirect3DViewport3_iface);
1784 /*****************************************************************************
1785 * IDirect3DDevice3::GetCurrentViewport
1787 * Returns the currently active viewport.
1789 * Version 2 and 3
1791 * Params:
1792 * Direct3DViewport3: Address to return the interface pointer at
1794 * Returns:
1795 * D3D_OK on success
1796 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1798 *****************************************************************************/
1799 static HRESULT WINAPI
1800 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1801 IDirect3DViewport3 **Direct3DViewport3)
1803 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1805 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1807 if(!Direct3DViewport3)
1808 return DDERR_INVALIDPARAMS;
1810 wined3d_mutex_lock();
1811 *Direct3DViewport3 = &This->current_viewport->IDirect3DViewport3_iface;
1813 /* AddRef the returned viewport */
1814 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1816 TRACE(" returning interface %p\n", *Direct3DViewport3);
1818 wined3d_mutex_unlock();
1820 return D3D_OK;
1823 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1824 IDirect3DViewport2 **Direct3DViewport2)
1826 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1827 HRESULT hr;
1829 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1831 hr = IDirect3DDevice3_GetCurrentViewport(&This->IDirect3DDevice3_iface,
1832 (IDirect3DViewport3 **)Direct3DViewport2);
1833 if(hr != D3D_OK) return hr;
1834 return D3D_OK;
1837 /*****************************************************************************
1838 * IDirect3DDevice7::SetRenderTarget
1840 * Sets the render target for the Direct3DDevice.
1841 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1842 * IDirectDrawSurface3 == IDirectDrawSurface
1844 * Version 2, 3 and 7
1846 * Params:
1847 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1848 * render target
1849 * Flags: Some flags
1851 * Returns:
1852 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1854 *****************************************************************************/
1855 static HRESULT d3d_device_set_render_target(IDirect3DDeviceImpl *This, IDirectDrawSurfaceImpl *Target)
1857 HRESULT hr;
1859 wined3d_mutex_lock();
1861 if(This->target == Target)
1863 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1864 wined3d_mutex_unlock();
1865 return D3D_OK;
1867 This->target = Target;
1868 hr = wined3d_device_set_render_target(This->wined3d_device, 0,
1869 Target ? Target->wined3d_surface : NULL, FALSE);
1870 if(hr != D3D_OK)
1872 wined3d_mutex_unlock();
1873 return hr;
1875 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1877 wined3d_mutex_unlock();
1879 return D3D_OK;
1882 static HRESULT
1883 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1884 IDirectDrawSurface7 *NewTarget,
1885 DWORD Flags)
1887 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1888 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface7(NewTarget);
1890 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, Flags);
1891 /* Flags: Not used */
1893 IDirectDrawSurface7_AddRef(NewTarget);
1894 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
1895 return d3d_device_set_render_target(This, Target);
1898 static HRESULT WINAPI
1899 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1900 IDirectDrawSurface7 *NewTarget,
1901 DWORD Flags)
1903 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1906 static HRESULT WINAPI
1907 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1908 IDirectDrawSurface7 *NewTarget,
1909 DWORD Flags)
1911 HRESULT hr;
1912 WORD old_fpucw;
1914 old_fpucw = d3d_fpu_setup();
1915 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1916 set_fpu_control_word(old_fpucw);
1918 return hr;
1921 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
1922 IDirectDrawSurface4 *NewRenderTarget, DWORD Flags)
1924 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1925 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface4(NewRenderTarget);
1927 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1929 IDirectDrawSurface4_AddRef(NewRenderTarget);
1930 IDirectDrawSurface4_Release(&This->target->IDirectDrawSurface4_iface);
1931 return d3d_device_set_render_target(This, Target);
1934 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
1935 IDirectDrawSurface *NewRenderTarget, DWORD Flags)
1937 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1938 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface(NewRenderTarget);
1940 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1942 IDirectDrawSurface_AddRef(NewRenderTarget);
1943 IDirectDrawSurface_Release(&This->target->IDirectDrawSurface_iface);
1944 return d3d_device_set_render_target(This, Target);
1947 /*****************************************************************************
1948 * IDirect3DDevice7::GetRenderTarget
1950 * Returns the current render target.
1951 * This is handled locally, because the WineD3D render target's parent
1952 * is an IParent
1954 * Version 2, 3 and 7
1956 * Params:
1957 * RenderTarget: Address to store the surface interface pointer
1959 * Returns:
1960 * D3D_OK on success
1961 * DDERR_INVALIDPARAMS if RenderTarget == NULL
1963 *****************************************************************************/
1964 static HRESULT WINAPI
1965 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
1966 IDirectDrawSurface7 **RenderTarget)
1968 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1970 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1972 if(!RenderTarget)
1973 return DDERR_INVALIDPARAMS;
1975 wined3d_mutex_lock();
1976 *RenderTarget = &This->target->IDirectDrawSurface7_iface;
1977 IDirectDrawSurface7_AddRef(*RenderTarget);
1978 wined3d_mutex_unlock();
1980 return D3D_OK;
1983 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
1984 IDirectDrawSurface4 **RenderTarget)
1986 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1987 IDirectDrawSurface7 *RenderTarget7;
1988 IDirectDrawSurfaceImpl *RenderTargetImpl;
1989 HRESULT hr;
1991 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1993 if(!RenderTarget)
1994 return DDERR_INVALIDPARAMS;
1996 hr = IDirect3DDevice7_GetRenderTarget(&This->IDirect3DDevice7_iface, &RenderTarget7);
1997 if(hr != D3D_OK) return hr;
1998 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
1999 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface;
2000 IDirectDrawSurface4_AddRef(*RenderTarget);
2001 IDirectDrawSurface7_Release(RenderTarget7);
2002 return D3D_OK;
2005 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
2006 IDirectDrawSurface **RenderTarget)
2008 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2009 IDirectDrawSurface7 *RenderTarget7;
2010 IDirectDrawSurfaceImpl *RenderTargetImpl;
2011 HRESULT hr;
2013 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2015 if(!RenderTarget)
2016 return DDERR_INVALIDPARAMS;
2018 hr = IDirect3DDevice7_GetRenderTarget(&This->IDirect3DDevice7_iface, &RenderTarget7);
2019 if(hr != D3D_OK) return hr;
2020 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2021 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
2022 IDirectDrawSurface_AddRef(*RenderTarget);
2023 IDirectDrawSurface7_Release(RenderTarget7);
2024 return D3D_OK;
2027 /*****************************************************************************
2028 * IDirect3DDevice3::Begin
2030 * Begins a description block of vertices. This is similar to glBegin()
2031 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2032 * described with IDirect3DDevice::Vertex are drawn.
2034 * Version 2 and 3
2036 * Params:
2037 * PrimitiveType: The type of primitives to draw
2038 * VertexTypeDesc: A flexible vertex format description of the vertices
2039 * Flags: Some flags..
2041 * Returns:
2042 * D3D_OK on success
2044 *****************************************************************************/
2045 static HRESULT WINAPI
2046 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2047 D3DPRIMITIVETYPE PrimitiveType,
2048 DWORD VertexTypeDesc,
2049 DWORD Flags)
2051 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2053 TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
2054 iface, PrimitiveType, VertexTypeDesc, Flags);
2056 wined3d_mutex_lock();
2057 This->primitive_type = PrimitiveType;
2058 This->vertex_type = VertexTypeDesc;
2059 This->render_flags = Flags;
2060 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2061 This->nb_vertices = 0;
2062 wined3d_mutex_unlock();
2064 return D3D_OK;
2067 static HRESULT WINAPI IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface, D3DPRIMITIVETYPE d3dpt,
2068 D3DVERTEXTYPE dwVertexTypeDesc, DWORD dwFlags)
2070 DWORD FVF;
2071 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2073 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2074 iface, d3dpt, dwVertexTypeDesc, dwFlags);
2076 switch(dwVertexTypeDesc)
2078 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2079 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2080 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2081 default:
2082 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2083 return DDERR_INVALIDPARAMS; /* Should never happen */
2086 return IDirect3DDevice3_Begin(&This->IDirect3DDevice3_iface, d3dpt, FVF, dwFlags);
2089 /*****************************************************************************
2090 * IDirect3DDevice3::BeginIndexed
2092 * Draws primitives based on vertices in a vertex array which are specified
2093 * by indices.
2095 * Version 2 and 3
2097 * Params:
2098 * PrimitiveType: Primitive type to draw
2099 * VertexType: A FVF description of the vertex format
2100 * Vertices: pointer to an array containing the vertices
2101 * NumVertices: The number of vertices in the vertex array
2102 * Flags: Some flags ...
2104 * Returns:
2105 * D3D_OK, because it's a stub
2107 *****************************************************************************/
2108 static HRESULT WINAPI
2109 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2110 D3DPRIMITIVETYPE PrimitiveType,
2111 DWORD VertexType,
2112 void *Vertices,
2113 DWORD NumVertices,
2114 DWORD Flags)
2116 FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2117 iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2119 return D3D_OK;
2123 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2124 D3DPRIMITIVETYPE d3dptPrimitiveType, D3DVERTEXTYPE d3dvtVertexType,
2125 void *lpvVertices, DWORD dwNumVertices, DWORD dwFlags)
2127 DWORD FVF;
2128 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2130 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2131 iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2133 switch(d3dvtVertexType)
2135 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2136 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2137 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2138 default:
2139 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2140 return DDERR_INVALIDPARAMS; /* Should never happen */
2143 return IDirect3DDevice3_BeginIndexed(&This->IDirect3DDevice3_iface,
2144 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2147 /*****************************************************************************
2148 * IDirect3DDevice3::Vertex
2150 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2151 * drawn vertices in a vertex buffer. If the buffer is too small, its
2152 * size is increased.
2154 * Version 2 and 3
2156 * Params:
2157 * Vertex: Pointer to the vertex
2159 * Returns:
2160 * D3D_OK, on success
2161 * DDERR_INVALIDPARAMS if Vertex is NULL
2163 *****************************************************************************/
2164 static HRESULT WINAPI
2165 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2166 void *Vertex)
2168 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2170 TRACE("iface %p, vertex %p.\n", iface, Vertex);
2172 if(!Vertex)
2173 return DDERR_INVALIDPARAMS;
2175 wined3d_mutex_lock();
2176 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2178 BYTE *old_buffer;
2179 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2180 old_buffer = This->vertex_buffer;
2181 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2182 if (old_buffer)
2184 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2185 HeapFree(GetProcessHeap(), 0, old_buffer);
2189 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2190 wined3d_mutex_unlock();
2192 return D3D_OK;
2195 static HRESULT WINAPI IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface, void *lpVertexType)
2197 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2199 TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
2201 return IDirect3DDevice3_Vertex(&This->IDirect3DDevice3_iface, lpVertexType);
2204 /*****************************************************************************
2205 * IDirect3DDevice3::Index
2207 * Specifies an index to a vertex to be drawn. The vertex array has to
2208 * be specified with BeginIndexed first.
2210 * Parameters:
2211 * VertexIndex: The index of the vertex to draw
2213 * Returns:
2214 * D3D_OK because it's a stub
2216 *****************************************************************************/
2217 static HRESULT WINAPI
2218 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2219 WORD VertexIndex)
2221 FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
2223 return D3D_OK;
2226 static HRESULT WINAPI IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface, WORD wVertexIndex)
2228 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2230 TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
2232 return IDirect3DDevice3_Index(&This->IDirect3DDevice3_iface, wVertexIndex);
2235 /*****************************************************************************
2236 * IDirect3DDevice3::End
2238 * Ends a draw begun with IDirect3DDevice3::Begin or
2239 * IDirect3DDevice::BeginIndexed. The vertices specified with
2240 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2241 * the IDirect3DDevice7::DrawPrimitive method. So far only
2242 * non-indexed mode is supported
2244 * Version 2 and 3
2246 * Params:
2247 * Flags: Some flags, as usual. Don't know which are defined
2249 * Returns:
2250 * The return value of IDirect3DDevice7::DrawPrimitive
2252 *****************************************************************************/
2253 static HRESULT WINAPI
2254 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2255 DWORD Flags)
2257 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2259 TRACE("iface %p, flags %#x.\n", iface, Flags);
2261 return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface, This->primitive_type,
2262 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2265 static HRESULT WINAPI IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface, DWORD dwFlags)
2267 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2269 TRACE("iface %p, flags %#x.\n", iface, dwFlags);
2271 return IDirect3DDevice3_End(&This->IDirect3DDevice3_iface, dwFlags);
2274 /*****************************************************************************
2275 * IDirect3DDevice7::GetRenderState
2277 * Returns the value of a render state. The possible render states are
2278 * defined in include/d3dtypes.h
2280 * Version 2, 3 and 7
2282 * Params:
2283 * RenderStateType: Render state to return the current setting of
2284 * Value: Address to store the value at
2286 * Returns:
2287 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2288 * DDERR_INVALIDPARAMS if Value == NULL
2290 *****************************************************************************/
2291 static HRESULT IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2292 D3DRENDERSTATETYPE RenderStateType, DWORD *Value)
2294 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
2295 HRESULT hr;
2297 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2299 if(!Value)
2300 return DDERR_INVALIDPARAMS;
2302 wined3d_mutex_lock();
2303 switch(RenderStateType)
2305 case D3DRENDERSTATE_TEXTUREMAG:
2307 WINED3DTEXTUREFILTERTYPE tex_mag;
2309 hr = wined3d_device_get_sampler_state(This->wined3d_device, 0, WINED3DSAMP_MAGFILTER, &tex_mag);
2311 switch (tex_mag)
2313 case WINED3DTEXF_POINT:
2314 *Value = D3DFILTER_NEAREST;
2315 break;
2316 case WINED3DTEXF_LINEAR:
2317 *Value = D3DFILTER_LINEAR;
2318 break;
2319 default:
2320 ERR("Unhandled texture mag %d !\n",tex_mag);
2321 *Value = 0;
2323 break;
2326 case D3DRENDERSTATE_TEXTUREMIN:
2328 WINED3DTEXTUREFILTERTYPE tex_min;
2329 WINED3DTEXTUREFILTERTYPE tex_mip;
2331 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2332 0, WINED3DSAMP_MINFILTER, &tex_min);
2333 if (FAILED(hr))
2335 wined3d_mutex_unlock();
2336 return hr;
2338 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2339 0, WINED3DSAMP_MIPFILTER, &tex_mip);
2341 switch (tex_min)
2343 case WINED3DTEXF_POINT:
2344 switch (tex_mip)
2346 case WINED3DTEXF_NONE:
2347 *Value = D3DFILTER_NEAREST;
2348 break;
2349 case WINED3DTEXF_POINT:
2350 *Value = D3DFILTER_MIPNEAREST;
2351 break;
2352 case WINED3DTEXF_LINEAR:
2353 *Value = D3DFILTER_LINEARMIPNEAREST;
2354 break;
2355 default:
2356 ERR("Unhandled mip filter %#x.\n", tex_mip);
2357 *Value = D3DFILTER_NEAREST;
2358 break;
2360 break;
2361 case WINED3DTEXF_LINEAR:
2362 switch (tex_mip)
2364 case WINED3DTEXF_NONE:
2365 *Value = D3DFILTER_LINEAR;
2366 break;
2367 case WINED3DTEXF_POINT:
2368 *Value = D3DFILTER_MIPLINEAR;
2369 break;
2370 case WINED3DTEXF_LINEAR:
2371 *Value = D3DFILTER_LINEARMIPLINEAR;
2372 break;
2373 default:
2374 ERR("Unhandled mip filter %#x.\n", tex_mip);
2375 *Value = D3DFILTER_LINEAR;
2376 break;
2378 break;
2379 default:
2380 ERR("Unhandled texture min filter %#x.\n",tex_min);
2381 *Value = D3DFILTER_NEAREST;
2382 break;
2384 break;
2387 case D3DRENDERSTATE_TEXTUREADDRESS:
2388 case D3DRENDERSTATE_TEXTUREADDRESSU:
2389 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2390 0, WINED3DSAMP_ADDRESSU, Value);
2391 break;
2392 case D3DRENDERSTATE_TEXTUREADDRESSV:
2393 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2394 0, WINED3DSAMP_ADDRESSV, Value);
2395 break;
2397 case D3DRENDERSTATE_BORDERCOLOR:
2398 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2399 hr = E_NOTIMPL;
2400 break;
2402 case D3DRENDERSTATE_TEXTUREHANDLE:
2403 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2404 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2405 hr = DDERR_INVALIDPARAMS;
2406 break;
2408 case D3DRENDERSTATE_ZBIAS:
2409 hr = wined3d_device_get_render_state(This->wined3d_device, WINED3DRS_DEPTHBIAS, Value);
2410 break;
2412 default:
2413 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2414 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2416 FIXME("Unhandled stipple pattern render state (%#x).\n",
2417 RenderStateType);
2418 hr = E_NOTIMPL;
2419 break;
2421 hr = wined3d_device_get_render_state(This->wined3d_device, RenderStateType, Value);
2423 wined3d_mutex_unlock();
2425 return hr;
2428 static HRESULT WINAPI
2429 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2430 D3DRENDERSTATETYPE RenderStateType,
2431 DWORD *Value)
2433 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2436 static HRESULT WINAPI
2437 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2438 D3DRENDERSTATETYPE RenderStateType,
2439 DWORD *Value)
2441 HRESULT hr;
2442 WORD old_fpucw;
2444 old_fpucw = d3d_fpu_setup();
2445 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2446 set_fpu_control_word(old_fpucw);
2448 return hr;
2451 static HRESULT WINAPI
2452 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2453 D3DRENDERSTATETYPE dwRenderStateType,
2454 DWORD *lpdwRenderState)
2456 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2457 HRESULT hr;
2459 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2461 switch(dwRenderStateType)
2463 case D3DRENDERSTATE_TEXTUREHANDLE:
2465 /* This state is wrapped to SetTexture in SetRenderState, so
2466 * it has to be wrapped to GetTexture here. */
2467 struct wined3d_texture *tex = NULL;
2468 *lpdwRenderState = 0;
2470 wined3d_mutex_lock();
2471 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2472 if (SUCCEEDED(hr) && tex)
2474 /* The parent of the texture is the IDirectDrawSurface7
2475 * interface of the ddraw surface. */
2476 IDirectDrawSurfaceImpl *parent = wined3d_texture_get_parent(tex);
2477 if (parent) *lpdwRenderState = parent->Handle;
2478 wined3d_texture_decref(tex);
2480 wined3d_mutex_unlock();
2482 return hr;
2485 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2487 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2488 the mapping to get the value. */
2489 DWORD colorop, colorarg1, colorarg2;
2490 DWORD alphaop, alphaarg1, alphaarg2;
2492 wined3d_mutex_lock();
2494 This->legacyTextureBlending = TRUE;
2496 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLOROP, &colorop);
2497 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLORARG1, &colorarg1);
2498 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLORARG2, &colorarg2);
2499 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, &alphaop);
2500 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2501 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2503 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2504 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2506 *lpdwRenderState = D3DTBLEND_DECAL;
2508 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2509 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2511 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2513 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2514 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2516 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2518 else
2520 struct wined3d_texture *tex = NULL;
2521 HRESULT hr;
2522 BOOL tex_alpha = FALSE;
2523 DDPIXELFORMAT ddfmt;
2525 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2527 if(hr == WINED3D_OK && tex)
2529 struct wined3d_resource *sub_resource;
2531 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2533 struct wined3d_resource_desc desc;
2535 wined3d_resource_get_desc(sub_resource, &desc);
2536 ddfmt.dwSize = sizeof(ddfmt);
2537 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2538 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2541 wined3d_texture_decref(tex);
2544 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2545 alphaop == (tex_alpha ? WINED3DTOP_SELECTARG1 : WINED3DTOP_SELECTARG2) &&
2546 alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2548 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2551 *lpdwRenderState = D3DTBLEND_MODULATE;
2554 wined3d_mutex_unlock();
2556 return D3D_OK;
2559 default:
2560 return IDirect3DDevice7_GetRenderState(&This->IDirect3DDevice7_iface, dwRenderStateType, lpdwRenderState);
2564 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2565 D3DRENDERSTATETYPE dwRenderStateType, DWORD *lpdwRenderState)
2567 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2569 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2571 return IDirect3DDevice3_GetRenderState(&This->IDirect3DDevice3_iface,
2572 dwRenderStateType, lpdwRenderState);
2575 /*****************************************************************************
2576 * IDirect3DDevice7::SetRenderState
2578 * Sets a render state. The possible render states are defined in
2579 * include/d3dtypes.h
2581 * Version 2, 3 and 7
2583 * Params:
2584 * RenderStateType: State to set
2585 * Value: Value to assign to that state
2587 * Returns:
2588 * D3D_OK on success,
2589 * for details see IWineD3DDevice::SetRenderState
2591 *****************************************************************************/
2592 static HRESULT
2593 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2594 D3DRENDERSTATETYPE RenderStateType,
2595 DWORD Value)
2597 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
2598 HRESULT hr;
2600 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2602 wined3d_mutex_lock();
2603 /* Some render states need special care */
2604 switch(RenderStateType)
2607 * The ddraw texture filter mapping works like this:
2608 * D3DFILTER_NEAREST Point min/mag, no mip
2609 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2610 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2612 * D3DFILTER_LINEAR Linear min/mag, no mip
2613 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2614 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2616 * This is the opposite of the GL naming convention,
2617 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2619 case D3DRENDERSTATE_TEXTUREMAG:
2621 WINED3DTEXTUREFILTERTYPE tex_mag;
2623 switch (Value)
2625 case D3DFILTER_NEAREST:
2626 case D3DFILTER_MIPNEAREST:
2627 case D3DFILTER_LINEARMIPNEAREST:
2628 tex_mag = WINED3DTEXF_POINT;
2629 break;
2630 case D3DFILTER_LINEAR:
2631 case D3DFILTER_MIPLINEAR:
2632 case D3DFILTER_LINEARMIPLINEAR:
2633 tex_mag = WINED3DTEXF_LINEAR;
2634 break;
2635 default:
2636 tex_mag = WINED3DTEXF_POINT;
2637 ERR("Unhandled texture mag %d !\n",Value);
2638 break;
2641 hr = wined3d_device_set_sampler_state(This->wined3d_device, 0, WINED3DSAMP_MAGFILTER, tex_mag);
2642 break;
2645 case D3DRENDERSTATE_TEXTUREMIN:
2647 WINED3DTEXTUREFILTERTYPE tex_min;
2648 WINED3DTEXTUREFILTERTYPE tex_mip;
2650 switch ((D3DTEXTUREFILTER) Value)
2652 case D3DFILTER_NEAREST:
2653 tex_min = WINED3DTEXF_POINT;
2654 tex_mip = WINED3DTEXF_NONE;
2655 break;
2656 case D3DFILTER_LINEAR:
2657 tex_min = WINED3DTEXF_LINEAR;
2658 tex_mip = WINED3DTEXF_NONE;
2659 break;
2660 case D3DFILTER_MIPNEAREST:
2661 tex_min = WINED3DTEXF_POINT;
2662 tex_mip = WINED3DTEXF_POINT;
2663 break;
2664 case D3DFILTER_MIPLINEAR:
2665 tex_min = WINED3DTEXF_LINEAR;
2666 tex_mip = WINED3DTEXF_POINT;
2667 break;
2668 case D3DFILTER_LINEARMIPNEAREST:
2669 tex_min = WINED3DTEXF_POINT;
2670 tex_mip = WINED3DTEXF_LINEAR;
2671 break;
2672 case D3DFILTER_LINEARMIPLINEAR:
2673 tex_min = WINED3DTEXF_LINEAR;
2674 tex_mip = WINED3DTEXF_LINEAR;
2675 break;
2677 default:
2678 ERR("Unhandled texture min %d !\n",Value);
2679 tex_min = WINED3DTEXF_POINT;
2680 tex_mip = WINED3DTEXF_NONE;
2681 break;
2684 wined3d_device_set_sampler_state(This->wined3d_device,
2685 0, WINED3DSAMP_MIPFILTER, tex_mip);
2686 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2687 0, WINED3DSAMP_MINFILTER, tex_min);
2688 break;
2691 case D3DRENDERSTATE_TEXTUREADDRESS:
2692 wined3d_device_set_sampler_state(This->wined3d_device,
2693 0, WINED3DSAMP_ADDRESSV, Value);
2694 /* Drop through */
2695 case D3DRENDERSTATE_TEXTUREADDRESSU:
2696 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2697 0, WINED3DSAMP_ADDRESSU, Value);
2698 break;
2699 case D3DRENDERSTATE_TEXTUREADDRESSV:
2700 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2701 0, WINED3DSAMP_ADDRESSV, Value);
2702 break;
2704 case D3DRENDERSTATE_BORDERCOLOR:
2705 /* This should probably just forward to the corresponding sampler
2706 * state. Needs tests. */
2707 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2708 hr = E_NOTIMPL;
2709 break;
2711 case D3DRENDERSTATE_TEXTUREHANDLE:
2712 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2713 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2714 hr = DDERR_INVALIDPARAMS;
2715 break;
2717 case D3DRENDERSTATE_ZBIAS:
2718 hr = wined3d_device_set_render_state(This->wined3d_device, WINED3DRS_DEPTHBIAS, Value);
2719 break;
2721 default:
2722 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2723 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2725 FIXME("Unhandled stipple pattern render state (%#x).\n",
2726 RenderStateType);
2727 hr = E_NOTIMPL;
2728 break;
2731 hr = wined3d_device_set_render_state(This->wined3d_device, RenderStateType, Value);
2732 break;
2734 wined3d_mutex_unlock();
2736 return hr;
2739 static HRESULT WINAPI
2740 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2741 D3DRENDERSTATETYPE RenderStateType,
2742 DWORD Value)
2744 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2747 static HRESULT WINAPI
2748 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2749 D3DRENDERSTATETYPE RenderStateType,
2750 DWORD Value)
2752 HRESULT hr;
2753 WORD old_fpucw;
2755 old_fpucw = d3d_fpu_setup();
2756 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2757 set_fpu_control_word(old_fpucw);
2759 return hr;
2762 static HRESULT WINAPI
2763 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2764 D3DRENDERSTATETYPE RenderStateType,
2765 DWORD Value)
2767 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2768 for this state can be directly mapped to texture stage colorop and alphaop, but
2769 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2770 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2771 alphaarg when needed.
2773 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2775 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2776 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2777 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2778 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2779 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2780 in device - TRUE if the app is using TEXTUREMAPBLEND.
2782 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2783 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2784 unless some broken game will be found that cares. */
2786 HRESULT hr;
2787 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2789 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2791 wined3d_mutex_lock();
2793 switch(RenderStateType)
2795 case D3DRENDERSTATE_TEXTUREHANDLE:
2797 IDirectDrawSurfaceImpl *surf;
2799 if(Value == 0)
2801 hr = wined3d_device_set_texture(This->wined3d_device, 0, NULL);
2802 break;
2805 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2806 if (!surf)
2808 WARN("Invalid texture handle.\n");
2809 hr = DDERR_INVALIDPARAMS;
2810 break;
2813 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2814 break;
2817 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2819 This->legacyTextureBlending = TRUE;
2821 switch ( (D3DTEXTUREBLEND) Value)
2823 case D3DTBLEND_MODULATE:
2825 struct wined3d_texture *tex = NULL;
2826 BOOL tex_alpha = FALSE;
2827 DDPIXELFORMAT ddfmt;
2829 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2831 if(hr == WINED3D_OK && tex)
2833 struct wined3d_resource *sub_resource;
2835 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2837 struct wined3d_resource_desc desc;
2839 wined3d_resource_get_desc(sub_resource, &desc);
2840 ddfmt.dwSize = sizeof(ddfmt);
2841 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2842 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2845 wined3d_texture_decref(tex);
2848 if (tex_alpha)
2849 wined3d_device_set_texture_stage_state(This->wined3d_device,
2850 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2851 else
2852 wined3d_device_set_texture_stage_state(This->wined3d_device,
2853 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2854 wined3d_device_set_texture_stage_state(This->wined3d_device,
2855 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2856 wined3d_device_set_texture_stage_state(This->wined3d_device,
2857 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2858 wined3d_device_set_texture_stage_state(This->wined3d_device,
2859 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2860 wined3d_device_set_texture_stage_state(This->wined3d_device,
2861 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2862 wined3d_device_set_texture_stage_state(This->wined3d_device,
2863 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2864 break;
2867 case D3DTBLEND_ADD:
2868 wined3d_device_set_texture_stage_state(This->wined3d_device,
2869 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2870 wined3d_device_set_texture_stage_state(This->wined3d_device,
2871 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2872 wined3d_device_set_texture_stage_state(This->wined3d_device,
2873 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2874 wined3d_device_set_texture_stage_state(This->wined3d_device,
2875 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2876 wined3d_device_set_texture_stage_state(This->wined3d_device,
2877 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2878 break;
2880 case D3DTBLEND_MODULATEALPHA:
2881 wined3d_device_set_texture_stage_state(This->wined3d_device,
2882 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2883 wined3d_device_set_texture_stage_state(This->wined3d_device,
2884 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2885 wined3d_device_set_texture_stage_state(This->wined3d_device,
2886 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2887 wined3d_device_set_texture_stage_state(This->wined3d_device,
2888 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2889 wined3d_device_set_texture_stage_state(This->wined3d_device,
2890 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2891 wined3d_device_set_texture_stage_state(This->wined3d_device,
2892 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2893 break;
2895 case D3DTBLEND_COPY:
2896 case D3DTBLEND_DECAL:
2897 wined3d_device_set_texture_stage_state(This->wined3d_device,
2898 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2899 wined3d_device_set_texture_stage_state(This->wined3d_device,
2900 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2901 wined3d_device_set_texture_stage_state(This->wined3d_device,
2902 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2903 wined3d_device_set_texture_stage_state(This->wined3d_device,
2904 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2905 break;
2907 case D3DTBLEND_DECALALPHA:
2908 wined3d_device_set_texture_stage_state(This->wined3d_device,
2909 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2910 wined3d_device_set_texture_stage_state(This->wined3d_device,
2911 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2912 wined3d_device_set_texture_stage_state(This->wined3d_device,
2913 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2914 wined3d_device_set_texture_stage_state(This->wined3d_device,
2915 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2916 wined3d_device_set_texture_stage_state(This->wined3d_device,
2917 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2918 break;
2920 default:
2921 ERR("Unhandled texture environment %d !\n",Value);
2924 hr = D3D_OK;
2925 break;
2928 default:
2929 hr = IDirect3DDevice7_SetRenderState(&This->IDirect3DDevice7_iface, RenderStateType, Value);
2930 break;
2932 wined3d_mutex_unlock();
2934 return hr;
2937 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2938 D3DRENDERSTATETYPE RenderStateType, DWORD Value)
2940 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2942 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2944 return IDirect3DDevice3_SetRenderState(&This->IDirect3DDevice3_iface, RenderStateType, Value);
2947 /*****************************************************************************
2948 * Direct3DDevice3::SetLightState
2950 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2951 * light states are forwarded to Direct3DDevice7 render states
2953 * Version 2 and 3
2955 * Params:
2956 * LightStateType: The light state to change
2957 * Value: The value to assign to that light state
2959 * Returns:
2960 * D3D_OK on success
2961 * DDERR_INVALIDPARAMS if the parameters were incorrect
2962 * Also check IDirect3DDevice7::SetRenderState
2964 *****************************************************************************/
2965 static HRESULT WINAPI
2966 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
2967 D3DLIGHTSTATETYPE LightStateType,
2968 DWORD Value)
2970 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2971 HRESULT hr;
2973 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
2975 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2977 TRACE("Unexpected Light State Type\n");
2978 return DDERR_INVALIDPARAMS;
2981 wined3d_mutex_lock();
2982 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
2984 IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
2985 if (!m)
2987 WARN("Invalid material handle.\n");
2988 wined3d_mutex_unlock();
2989 return DDERR_INVALIDPARAMS;
2992 TRACE(" activating material %p.\n", m);
2993 material_activate(m);
2995 This->material = Value;
2997 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
2999 switch (Value)
3001 case D3DCOLOR_MONO:
3002 ERR("DDCOLOR_MONO should not happen!\n");
3003 break;
3004 case D3DCOLOR_RGB:
3005 /* We are already in this mode */
3006 TRACE("Setting color model to RGB (no-op).\n");
3007 break;
3008 default:
3009 ERR("Unknown color model!\n");
3010 wined3d_mutex_unlock();
3011 return DDERR_INVALIDPARAMS;
3014 else
3016 D3DRENDERSTATETYPE rs;
3017 switch (LightStateType)
3019 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3020 rs = D3DRENDERSTATE_AMBIENT;
3021 break;
3022 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3023 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3024 break;
3025 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3026 rs = D3DRENDERSTATE_FOGSTART;
3027 break;
3028 case D3DLIGHTSTATE_FOGEND: /* 6 */
3029 rs = D3DRENDERSTATE_FOGEND;
3030 break;
3031 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3032 rs = D3DRENDERSTATE_FOGDENSITY;
3033 break;
3034 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3035 rs = D3DRENDERSTATE_COLORVERTEX;
3036 break;
3037 default:
3038 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3039 wined3d_mutex_unlock();
3040 return DDERR_INVALIDPARAMS;
3043 hr = IDirect3DDevice7_SetRenderState(&This->IDirect3DDevice7_iface, rs, Value);
3044 wined3d_mutex_unlock();
3045 return hr;
3047 wined3d_mutex_unlock();
3049 return D3D_OK;
3052 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3053 D3DLIGHTSTATETYPE LightStateType, DWORD Value)
3055 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3057 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3059 return IDirect3DDevice3_SetLightState(&This->IDirect3DDevice3_iface, LightStateType, Value);
3062 /*****************************************************************************
3063 * IDirect3DDevice3::GetLightState
3065 * Returns the current setting of a light state. The state is read from
3066 * the Direct3DDevice7 render state.
3068 * Version 2 and 3
3070 * Params:
3071 * LightStateType: The light state to return
3072 * Value: The address to store the light state setting at
3074 * Returns:
3075 * D3D_OK on success
3076 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3077 * Also see IDirect3DDevice7::GetRenderState
3079 *****************************************************************************/
3080 static HRESULT WINAPI
3081 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3082 D3DLIGHTSTATETYPE LightStateType,
3083 DWORD *Value)
3085 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3086 HRESULT hr;
3088 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3090 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3092 TRACE("Unexpected Light State Type\n");
3093 return DDERR_INVALIDPARAMS;
3096 if(!Value)
3097 return DDERR_INVALIDPARAMS;
3099 wined3d_mutex_lock();
3100 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3102 *Value = This->material;
3104 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3106 *Value = D3DCOLOR_RGB;
3108 else
3110 D3DRENDERSTATETYPE rs;
3111 switch (LightStateType)
3113 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3114 rs = D3DRENDERSTATE_AMBIENT;
3115 break;
3116 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3117 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3118 break;
3119 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3120 rs = D3DRENDERSTATE_FOGSTART;
3121 break;
3122 case D3DLIGHTSTATE_FOGEND: /* 6 */
3123 rs = D3DRENDERSTATE_FOGEND;
3124 break;
3125 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3126 rs = D3DRENDERSTATE_FOGDENSITY;
3127 break;
3128 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3129 rs = D3DRENDERSTATE_COLORVERTEX;
3130 break;
3131 default:
3132 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3133 wined3d_mutex_unlock();
3134 return DDERR_INVALIDPARAMS;
3137 hr = IDirect3DDevice7_GetRenderState(&This->IDirect3DDevice7_iface, rs, Value);
3138 wined3d_mutex_unlock();
3139 return hr;
3141 wined3d_mutex_unlock();
3143 return D3D_OK;
3146 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3147 D3DLIGHTSTATETYPE LightStateType, DWORD *Value)
3149 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3151 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3153 return IDirect3DDevice3_GetLightState(&This->IDirect3DDevice3_iface, LightStateType, Value);
3156 /*****************************************************************************
3157 * IDirect3DDevice7::SetTransform
3159 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3160 * in include/d3dtypes.h.
3161 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3162 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3163 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3165 * Version 2, 3 and 7
3167 * Params:
3168 * TransformStateType: transform state to set
3169 * Matrix: Matrix to assign to the state
3171 * Returns:
3172 * D3D_OK on success
3173 * DDERR_INVALIDPARAMS if Matrix == NULL
3174 * For details see IWineD3DDevice::SetTransform
3176 *****************************************************************************/
3177 static HRESULT
3178 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3179 D3DTRANSFORMSTATETYPE TransformStateType,
3180 D3DMATRIX *Matrix)
3182 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3183 D3DTRANSFORMSTATETYPE type;
3184 HRESULT hr;
3186 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3188 switch(TransformStateType)
3190 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3191 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3192 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3193 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3194 default: type = TransformStateType;
3197 if (!Matrix)
3198 return DDERR_INVALIDPARAMS;
3200 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3201 wined3d_mutex_lock();
3202 hr = wined3d_device_set_transform(This->wined3d_device, type, (struct wined3d_matrix *)Matrix);
3203 wined3d_mutex_unlock();
3205 return hr;
3208 static HRESULT WINAPI
3209 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3210 D3DTRANSFORMSTATETYPE TransformStateType,
3211 D3DMATRIX *Matrix)
3213 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3216 static HRESULT WINAPI
3217 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3218 D3DTRANSFORMSTATETYPE TransformStateType,
3219 D3DMATRIX *Matrix)
3221 HRESULT hr;
3222 WORD old_fpucw;
3224 old_fpucw = d3d_fpu_setup();
3225 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3226 set_fpu_control_word(old_fpucw);
3228 return hr;
3231 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3232 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3234 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3236 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3238 return IDirect3DDevice7_SetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3241 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3242 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3244 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3246 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3248 return IDirect3DDevice7_SetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3251 /*****************************************************************************
3252 * IDirect3DDevice7::GetTransform
3254 * Returns the matrix assigned to a transform state
3255 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3256 * SetTransform
3258 * Params:
3259 * TransformStateType: State to read the matrix from
3260 * Matrix: Address to store the matrix at
3262 * Returns:
3263 * D3D_OK on success
3264 * DDERR_INVALIDPARAMS if Matrix == NULL
3265 * For details, see IWineD3DDevice::GetTransform
3267 *****************************************************************************/
3268 static HRESULT
3269 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3270 D3DTRANSFORMSTATETYPE TransformStateType,
3271 D3DMATRIX *Matrix)
3273 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3274 D3DTRANSFORMSTATETYPE type;
3275 HRESULT hr;
3277 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3279 switch(TransformStateType)
3281 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3282 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3283 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3284 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3285 default: type = TransformStateType;
3288 if(!Matrix)
3289 return DDERR_INVALIDPARAMS;
3291 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3292 wined3d_mutex_lock();
3293 hr = wined3d_device_get_transform(This->wined3d_device, type, (struct wined3d_matrix *)Matrix);
3294 wined3d_mutex_unlock();
3296 return hr;
3299 static HRESULT WINAPI
3300 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3301 D3DTRANSFORMSTATETYPE TransformStateType,
3302 D3DMATRIX *Matrix)
3304 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3307 static HRESULT WINAPI
3308 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3309 D3DTRANSFORMSTATETYPE TransformStateType,
3310 D3DMATRIX *Matrix)
3312 HRESULT hr;
3313 WORD old_fpucw;
3315 old_fpucw = d3d_fpu_setup();
3316 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3317 set_fpu_control_word(old_fpucw);
3319 return hr;
3322 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3323 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3325 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3327 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3329 return IDirect3DDevice7_GetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3332 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3333 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3335 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3337 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3339 return IDirect3DDevice7_GetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3342 /*****************************************************************************
3343 * IDirect3DDevice7::MultiplyTransform
3345 * Multiplies the already-set transform matrix of a transform state
3346 * with another matrix. For the world matrix, see SetTransform
3348 * Version 2, 3 and 7
3350 * Params:
3351 * TransformStateType: Transform state to multiply
3352 * D3DMatrix Matrix to multiply with.
3354 * Returns
3355 * D3D_OK on success
3356 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3357 * For details, see IWineD3DDevice::MultiplyTransform
3359 *****************************************************************************/
3360 static HRESULT
3361 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3362 D3DTRANSFORMSTATETYPE TransformStateType,
3363 D3DMATRIX *D3DMatrix)
3365 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3366 HRESULT hr;
3367 D3DTRANSFORMSTATETYPE type;
3369 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3371 switch(TransformStateType)
3373 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3374 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3375 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3376 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3377 default: type = TransformStateType;
3380 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3381 wined3d_mutex_lock();
3382 hr = wined3d_device_multiply_transform(This->wined3d_device,
3383 type, (struct wined3d_matrix *)D3DMatrix);
3384 wined3d_mutex_unlock();
3386 return hr;
3389 static HRESULT WINAPI
3390 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3391 D3DTRANSFORMSTATETYPE TransformStateType,
3392 D3DMATRIX *D3DMatrix)
3394 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3397 static HRESULT WINAPI
3398 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3399 D3DTRANSFORMSTATETYPE TransformStateType,
3400 D3DMATRIX *D3DMatrix)
3402 HRESULT hr;
3403 WORD old_fpucw;
3405 old_fpucw = d3d_fpu_setup();
3406 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3407 set_fpu_control_word(old_fpucw);
3409 return hr;
3412 static HRESULT WINAPI IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3413 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3415 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3417 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3419 return IDirect3DDevice7_MultiplyTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3422 static HRESULT WINAPI IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3423 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3425 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3427 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3429 return IDirect3DDevice7_MultiplyTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3432 /*****************************************************************************
3433 * IDirect3DDevice7::DrawPrimitive
3435 * Draws primitives based on vertices in an application-provided pointer
3437 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3438 * an FVF format for D3D7
3440 * Params:
3441 * PrimitiveType: The type of the primitives to draw
3442 * Vertex type: Flexible vertex format vertex description
3443 * Vertices: Pointer to the vertex array
3444 * VertexCount: The number of vertices to draw
3445 * Flags: As usual a few flags
3447 * Returns:
3448 * D3D_OK on success
3449 * DDERR_INVALIDPARAMS if Vertices is NULL
3450 * For details, see IWineD3DDevice::DrawPrimitiveUP
3452 *****************************************************************************/
3453 static HRESULT
3454 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3455 D3DPRIMITIVETYPE PrimitiveType,
3456 DWORD VertexType,
3457 void *Vertices,
3458 DWORD VertexCount,
3459 DWORD Flags)
3461 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3462 UINT stride;
3463 HRESULT hr;
3465 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3466 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3468 if(!Vertices)
3469 return DDERR_INVALIDPARAMS;
3471 /* Get the stride */
3472 stride = get_flexible_vertex_size(VertexType);
3474 /* Set the FVF */
3475 wined3d_mutex_lock();
3476 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3477 if(hr != D3D_OK)
3479 wined3d_mutex_unlock();
3480 return hr;
3483 /* This method translates to the user pointer draw of WineD3D */
3484 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3485 hr = wined3d_device_draw_primitive_up(This->wined3d_device, VertexCount, Vertices, stride);
3486 wined3d_mutex_unlock();
3488 return hr;
3491 static HRESULT WINAPI
3492 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3493 D3DPRIMITIVETYPE PrimitiveType,
3494 DWORD VertexType,
3495 void *Vertices,
3496 DWORD VertexCount,
3497 DWORD Flags)
3499 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3502 static HRESULT WINAPI
3503 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3504 D3DPRIMITIVETYPE PrimitiveType,
3505 DWORD VertexType,
3506 void *Vertices,
3507 DWORD VertexCount,
3508 DWORD Flags)
3510 HRESULT hr;
3511 WORD old_fpucw;
3513 old_fpucw = d3d_fpu_setup();
3514 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3515 set_fpu_control_word(old_fpucw);
3517 return hr;
3520 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3521 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3522 DWORD Flags)
3524 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3525 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3526 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3528 return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface,
3529 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3532 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3533 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3534 DWORD VertexCount, DWORD Flags)
3536 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3537 DWORD FVF;
3539 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3540 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3542 switch(VertexType)
3544 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3545 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3546 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3547 default:
3548 ERR("Unexpected vertex type %d\n", VertexType);
3549 return DDERR_INVALIDPARAMS; /* Should never happen */
3552 return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface,
3553 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3556 /*****************************************************************************
3557 * IDirect3DDevice7::DrawIndexedPrimitive
3559 * Draws vertices from an application-provided pointer, based on the index
3560 * numbers in a WORD array.
3562 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3563 * an FVF format for D3D7
3565 * Params:
3566 * PrimitiveType: The primitive type to draw
3567 * VertexType: The FVF vertex description
3568 * Vertices: Pointer to the vertex array
3569 * VertexCount: ?
3570 * Indices: Pointer to the index array
3571 * IndexCount: Number of indices = Number of vertices to draw
3572 * Flags: As usual, some flags
3574 * Returns:
3575 * D3D_OK on success
3576 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3577 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3579 *****************************************************************************/
3580 static HRESULT
3581 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3582 D3DPRIMITIVETYPE PrimitiveType,
3583 DWORD VertexType,
3584 void *Vertices,
3585 DWORD VertexCount,
3586 WORD *Indices,
3587 DWORD IndexCount,
3588 DWORD Flags)
3590 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3591 HRESULT hr;
3593 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3594 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3596 /* Set the D3DDevice's FVF */
3597 wined3d_mutex_lock();
3598 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3599 if(FAILED(hr))
3601 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3602 wined3d_mutex_unlock();
3603 return hr;
3606 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3607 hr = wined3d_device_draw_indexed_primitive_up(This->wined3d_device, IndexCount, Indices,
3608 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3609 wined3d_mutex_unlock();
3611 return hr;
3614 static HRESULT WINAPI
3615 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3616 D3DPRIMITIVETYPE PrimitiveType,
3617 DWORD VertexType,
3618 void *Vertices,
3619 DWORD VertexCount,
3620 WORD *Indices,
3621 DWORD IndexCount,
3622 DWORD Flags)
3624 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3627 static HRESULT WINAPI
3628 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3629 D3DPRIMITIVETYPE PrimitiveType,
3630 DWORD VertexType,
3631 void *Vertices,
3632 DWORD VertexCount,
3633 WORD *Indices,
3634 DWORD IndexCount,
3635 DWORD Flags)
3637 HRESULT hr;
3638 WORD old_fpucw;
3640 old_fpucw = d3d_fpu_setup();
3641 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3642 set_fpu_control_word(old_fpucw);
3644 return hr;
3647 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3648 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3649 WORD *Indices, DWORD IndexCount, DWORD Flags)
3651 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3652 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3653 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3655 return IDirect3DDevice7_DrawIndexedPrimitive(&This->IDirect3DDevice7_iface,
3656 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3659 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3660 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3661 DWORD VertexCount, WORD *Indices, DWORD IndexCount, DWORD Flags)
3663 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3664 DWORD FVF;
3666 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3667 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3669 switch(VertexType)
3671 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3672 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3673 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3674 default:
3675 ERR("Unexpected vertex type %d\n", VertexType);
3676 return DDERR_INVALIDPARAMS; /* Should never happen */
3679 return IDirect3DDevice7_DrawIndexedPrimitive(&This->IDirect3DDevice7_iface,
3680 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3683 /*****************************************************************************
3684 * IDirect3DDevice7::SetClipStatus
3686 * Sets the clip status. This defines things as clipping conditions and
3687 * the extents of the clipping region.
3689 * Version 2, 3 and 7
3691 * Params:
3692 * ClipStatus:
3694 * Returns:
3695 * D3D_OK because it's a stub
3696 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3698 *****************************************************************************/
3699 static HRESULT WINAPI
3700 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3701 D3DCLIPSTATUS *ClipStatus)
3703 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3705 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3706 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3708 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3709 return D3D_OK;
3712 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3713 D3DCLIPSTATUS *ClipStatus)
3715 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3716 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3718 return IDirect3DDevice7_SetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3721 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3722 D3DCLIPSTATUS *ClipStatus)
3724 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3725 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3727 return IDirect3DDevice7_SetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3730 /*****************************************************************************
3731 * IDirect3DDevice7::GetClipStatus
3733 * Returns the clip status
3735 * Params:
3736 * ClipStatus: Address to write the clip status to
3738 * Returns:
3739 * D3D_OK because it's a stub
3741 *****************************************************************************/
3742 static HRESULT WINAPI
3743 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3744 D3DCLIPSTATUS *ClipStatus)
3746 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3748 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3749 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3750 return D3D_OK;
3753 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3754 D3DCLIPSTATUS *ClipStatus)
3756 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3757 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3759 return IDirect3DDevice7_GetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3762 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3763 D3DCLIPSTATUS *ClipStatus)
3765 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3766 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3768 return IDirect3DDevice7_GetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3771 /*****************************************************************************
3772 * IDirect3DDevice::DrawPrimitiveStrided
3774 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3776 * Version 3 and 7
3778 * Params:
3779 * PrimitiveType: The primitive type to draw
3780 * VertexType: The FVF description of the vertices to draw (for the stride??)
3781 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3782 * the vertex data locations
3783 * VertexCount: The number of vertices to draw
3784 * Flags: Some flags
3786 * Returns:
3787 * D3D_OK, because it's a stub
3788 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3789 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3791 *****************************************************************************/
3792 static HRESULT
3793 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3794 D3DPRIMITIVETYPE PrimitiveType,
3795 DWORD VertexType,
3796 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3797 DWORD VertexCount,
3798 DWORD Flags)
3800 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3801 WineDirect3DVertexStridedData WineD3DStrided;
3802 DWORD i;
3803 HRESULT hr;
3805 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3806 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3808 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3809 /* Get the strided data right. the wined3d structure is a bit bigger
3810 * Watch out: The contents of the strided data are determined by the fvf,
3811 * not by the members set in D3DDrawPrimStrideData. So it's valid
3812 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3813 * not set in the fvf.
3815 if(VertexType & D3DFVF_POSITION_MASK)
3817 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3818 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3819 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3820 if (VertexType & D3DFVF_XYZRHW)
3822 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3823 WineD3DStrided.position_transformed = TRUE;
3824 } else
3825 WineD3DStrided.position_transformed = FALSE;
3828 if(VertexType & D3DFVF_NORMAL)
3830 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3831 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3832 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3835 if(VertexType & D3DFVF_DIFFUSE)
3837 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3838 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3839 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3842 if(VertexType & D3DFVF_SPECULAR)
3844 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3845 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3846 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3849 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3851 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3853 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3854 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3855 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3856 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3857 default: ERR("Unexpected texture coordinate size %d\n",
3858 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3860 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3861 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3864 /* WineD3D doesn't need the FVF here */
3865 wined3d_mutex_lock();
3866 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3867 hr = wined3d_device_draw_primitive_strided(This->wined3d_device, VertexCount, &WineD3DStrided);
3868 wined3d_mutex_unlock();
3870 return hr;
3873 static HRESULT WINAPI
3874 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3875 D3DPRIMITIVETYPE PrimitiveType,
3876 DWORD VertexType,
3877 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3878 DWORD VertexCount,
3879 DWORD Flags)
3881 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3884 static HRESULT WINAPI
3885 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3886 D3DPRIMITIVETYPE PrimitiveType,
3887 DWORD VertexType,
3888 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3889 DWORD VertexCount,
3890 DWORD Flags)
3892 HRESULT hr;
3893 WORD old_fpucw;
3895 old_fpucw = d3d_fpu_setup();
3896 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3897 set_fpu_control_word(old_fpucw);
3899 return hr;
3902 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3903 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3904 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3906 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3908 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3909 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3911 return IDirect3DDevice7_DrawPrimitiveStrided(&This->IDirect3DDevice7_iface,
3912 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3915 /*****************************************************************************
3916 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3918 * Draws primitives specified by strided data locations based on indices
3920 * Version 3 and 7
3922 * Params:
3923 * PrimitiveType:
3925 * Returns:
3926 * D3D_OK, because it's a stub
3927 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3928 * (DDERR_INVALIDPARAMS if Indices is NULL)
3929 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3931 *****************************************************************************/
3932 static HRESULT
3933 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3934 D3DPRIMITIVETYPE PrimitiveType,
3935 DWORD VertexType,
3936 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3937 DWORD VertexCount,
3938 WORD *Indices,
3939 DWORD IndexCount,
3940 DWORD Flags)
3942 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3943 WineDirect3DVertexStridedData WineD3DStrided;
3944 DWORD i;
3945 HRESULT hr;
3947 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3948 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3950 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3951 /* Get the strided data right. the wined3d structure is a bit bigger
3952 * Watch out: The contents of the strided data are determined by the fvf,
3953 * not by the members set in D3DDrawPrimStrideData. So it's valid
3954 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3955 * not set in the fvf.
3957 if(VertexType & D3DFVF_POSITION_MASK)
3959 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3960 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3961 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3962 if (VertexType & D3DFVF_XYZRHW)
3964 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3965 WineD3DStrided.position_transformed = TRUE;
3966 } else
3967 WineD3DStrided.position_transformed = FALSE;
3970 if(VertexType & D3DFVF_NORMAL)
3972 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3973 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3974 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3977 if(VertexType & D3DFVF_DIFFUSE)
3979 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3980 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3981 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3984 if(VertexType & D3DFVF_SPECULAR)
3986 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3987 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3988 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3991 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3993 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3995 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3996 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3997 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3998 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3999 default: ERR("Unexpected texture coordinate size %d\n",
4000 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4002 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4003 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4006 /* WineD3D doesn't need the FVF here */
4007 wined3d_mutex_lock();
4008 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4009 hr = wined3d_device_draw_indexed_primitive_strided(This->wined3d_device,
4010 IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
4011 wined3d_mutex_unlock();
4013 return hr;
4016 static HRESULT WINAPI
4017 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4018 D3DPRIMITIVETYPE PrimitiveType,
4019 DWORD VertexType,
4020 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4021 DWORD VertexCount,
4022 WORD *Indices,
4023 DWORD IndexCount,
4024 DWORD Flags)
4026 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4029 static HRESULT WINAPI
4030 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4031 D3DPRIMITIVETYPE PrimitiveType,
4032 DWORD VertexType,
4033 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4034 DWORD VertexCount,
4035 WORD *Indices,
4036 DWORD IndexCount,
4037 DWORD Flags)
4039 HRESULT hr;
4040 WORD old_fpucw;
4042 old_fpucw = d3d_fpu_setup();
4043 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4044 set_fpu_control_word(old_fpucw);
4046 return hr;
4049 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4050 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4051 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4052 DWORD IndexCount, DWORD Flags)
4054 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4056 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4057 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4059 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&This->IDirect3DDevice7_iface,
4060 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4063 /*****************************************************************************
4064 * IDirect3DDevice7::DrawPrimitiveVB
4066 * Draws primitives from a vertex buffer to the screen.
4068 * Version 3 and 7
4070 * Params:
4071 * PrimitiveType: Type of primitive to be rendered.
4072 * D3DVertexBuf: Source Vertex Buffer
4073 * StartVertex: Index of the first vertex from the buffer to be rendered
4074 * NumVertices: Number of vertices to be rendered
4075 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4077 * Return values
4078 * D3D_OK on success
4079 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4081 *****************************************************************************/
4082 static HRESULT
4083 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4084 D3DPRIMITIVETYPE PrimitiveType,
4085 IDirect3DVertexBuffer7 *D3DVertexBuf,
4086 DWORD StartVertex,
4087 DWORD NumVertices,
4088 DWORD Flags)
4090 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4091 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4092 HRESULT hr;
4093 DWORD stride;
4095 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4096 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4098 /* Sanity checks */
4099 if(!vb)
4101 ERR("(%p) No Vertex buffer specified\n", This);
4102 return DDERR_INVALIDPARAMS;
4104 stride = get_flexible_vertex_size(vb->fvf);
4106 wined3d_mutex_lock();
4107 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4108 if (FAILED(hr))
4110 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4111 wined3d_mutex_unlock();
4112 return hr;
4115 /* Set the vertex stream source */
4116 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4117 if(hr != D3D_OK)
4119 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4120 wined3d_mutex_unlock();
4121 return hr;
4124 /* Now draw the primitives */
4125 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4126 hr = wined3d_device_draw_primitive(This->wined3d_device, StartVertex, NumVertices);
4127 wined3d_mutex_unlock();
4129 return hr;
4132 static HRESULT WINAPI
4133 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4134 D3DPRIMITIVETYPE PrimitiveType,
4135 IDirect3DVertexBuffer7 *D3DVertexBuf,
4136 DWORD StartVertex,
4137 DWORD NumVertices,
4138 DWORD Flags)
4140 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4143 static HRESULT WINAPI
4144 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4145 D3DPRIMITIVETYPE PrimitiveType,
4146 IDirect3DVertexBuffer7 *D3DVertexBuf,
4147 DWORD StartVertex,
4148 DWORD NumVertices,
4149 DWORD Flags)
4151 HRESULT hr;
4152 WORD old_fpucw;
4154 old_fpucw = d3d_fpu_setup();
4155 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4156 set_fpu_control_word(old_fpucw);
4158 return hr;
4161 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4162 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex,
4163 DWORD NumVertices, DWORD Flags)
4165 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4166 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4168 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4169 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4171 return IDirect3DDevice7_DrawPrimitiveVB(&This->IDirect3DDevice7_iface,
4172 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4176 /*****************************************************************************
4177 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4179 * Draws primitives from a vertex buffer to the screen
4181 * Params:
4182 * PrimitiveType: Type of primitive to be rendered.
4183 * D3DVertexBuf: Source Vertex Buffer
4184 * StartVertex: Index of the first vertex from the buffer to be rendered
4185 * NumVertices: Number of vertices to be rendered
4186 * Indices: Array of DWORDs used to index into the Vertices
4187 * IndexCount: Number of indices in Indices
4188 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4190 * Return values
4192 *****************************************************************************/
4193 static HRESULT
4194 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4195 D3DPRIMITIVETYPE PrimitiveType,
4196 IDirect3DVertexBuffer7 *D3DVertexBuf,
4197 DWORD StartVertex,
4198 DWORD NumVertices,
4199 WORD *Indices,
4200 DWORD IndexCount,
4201 DWORD Flags)
4203 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4204 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4205 DWORD stride = get_flexible_vertex_size(vb->fvf);
4206 struct wined3d_resource *wined3d_resource;
4207 struct wined3d_resource_desc desc;
4208 WORD *LockedIndices;
4209 HRESULT hr;
4211 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4212 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4214 /* Steps:
4215 * 1) Upload the Indices to the index buffer
4216 * 2) Set the index source
4217 * 3) Set the Vertex Buffer as the Stream source
4218 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4221 wined3d_mutex_lock();
4223 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4224 if (FAILED(hr))
4226 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4227 wined3d_mutex_unlock();
4228 return hr;
4231 /* check that the buffer is large enough to hold the indices,
4232 * reallocate if necessary. */
4233 wined3d_resource = wined3d_buffer_get_resource(This->indexbuffer);
4234 wined3d_resource_get_desc(wined3d_resource, &desc);
4235 if (desc.size < IndexCount * sizeof(WORD))
4237 UINT size = max(desc.size * 2, IndexCount * sizeof(WORD));
4238 struct wined3d_buffer *buffer;
4240 TRACE("Growing index buffer to %u bytes\n", size);
4242 hr = wined3d_buffer_create_ib(This->wined3d_device, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4243 WINED3DPOOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
4244 if (FAILED(hr))
4246 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4247 wined3d_mutex_unlock();
4248 return hr;
4251 wined3d_buffer_decref(This->indexbuffer);
4252 This->indexbuffer = buffer;
4255 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4256 * method could be created which takes an user pointer containing the
4257 * indices or a SetData-Method for the index buffer, which overrides the
4258 * index buffer data with our pointer. */
4259 hr = wined3d_buffer_map(This->indexbuffer, 0, IndexCount * sizeof(WORD),
4260 (BYTE **)&LockedIndices, 0);
4261 if (FAILED(hr))
4263 ERR("Failed to map buffer, hr %#x.\n", hr);
4264 wined3d_mutex_unlock();
4265 return hr;
4267 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4268 wined3d_buffer_unmap(This->indexbuffer);
4270 /* Set the index stream */
4271 wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4272 hr = wined3d_device_set_index_buffer(This->wined3d_device, This->indexbuffer, WINED3DFMT_R16_UINT);
4274 /* Set the vertex stream source */
4275 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4276 if (FAILED(hr))
4278 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4279 wined3d_mutex_unlock();
4280 return hr;
4284 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4285 hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, 0, IndexCount);
4287 wined3d_mutex_unlock();
4289 return hr;
4292 static HRESULT WINAPI
4293 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4294 D3DPRIMITIVETYPE PrimitiveType,
4295 IDirect3DVertexBuffer7 *D3DVertexBuf,
4296 DWORD StartVertex,
4297 DWORD NumVertices,
4298 WORD *Indices,
4299 DWORD IndexCount,
4300 DWORD Flags)
4302 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4305 static HRESULT WINAPI
4306 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4307 D3DPRIMITIVETYPE PrimitiveType,
4308 IDirect3DVertexBuffer7 *D3DVertexBuf,
4309 DWORD StartVertex,
4310 DWORD NumVertices,
4311 WORD *Indices,
4312 DWORD IndexCount,
4313 DWORD Flags)
4315 HRESULT hr;
4316 WORD old_fpucw;
4318 old_fpucw = d3d_fpu_setup();
4319 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4320 set_fpu_control_word(old_fpucw);
4322 return hr;
4325 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4326 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4327 DWORD IndexCount, DWORD Flags)
4329 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4330 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4332 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4333 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4335 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&This->IDirect3DDevice7_iface,
4336 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount,
4337 Flags);
4340 /*****************************************************************************
4341 * IDirect3DDevice7::ComputeSphereVisibility
4343 * Calculates the visibility of spheres in the current viewport. The spheres
4344 * are passed in the Centers and Radii arrays, the results are passed back
4345 * in the ReturnValues array. Return values are either completely visible,
4346 * partially visible or completely invisible.
4347 * The return value consist of a combination of D3DCLIP_* flags, or it's
4348 * 0 if the sphere is completely visible(according to the SDK, not checked)
4350 * Version 3 and 7
4352 * Params:
4353 * Centers: Array containing the sphere centers
4354 * Radii: Array containing the sphere radii
4355 * NumSpheres: The number of centers and radii in the arrays
4356 * Flags: Some flags
4357 * ReturnValues: Array to write the results to
4359 * Returns:
4360 * D3D_OK
4361 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4362 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4363 * is singular)
4365 *****************************************************************************/
4367 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4369 float distance, norm;
4371 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4372 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4374 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4375 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4376 return 0;
4379 static HRESULT WINAPI
4380 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4381 D3DVECTOR *Centers,
4382 D3DVALUE *Radii,
4383 DWORD NumSpheres,
4384 DWORD Flags,
4385 DWORD *ReturnValues)
4387 D3DMATRIX m, temp;
4388 D3DVALUE origin_plane[6];
4389 D3DVECTOR vec[6];
4390 HRESULT hr;
4391 UINT i, j;
4393 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4394 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4396 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4397 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4398 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4399 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4400 multiply_matrix(&m, &temp, &m);
4402 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4403 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4404 multiply_matrix(&m, &temp, &m);
4406 /* Left plane */
4407 vec[0].u1.x = m._14 + m._11;
4408 vec[0].u2.y = m._24 + m._21;
4409 vec[0].u3.z = m._34 + m._31;
4410 origin_plane[0] = m._44 + m._41;
4412 /* Right plane */
4413 vec[1].u1.x = m._14 - m._11;
4414 vec[1].u2.y = m._24 - m._21;
4415 vec[1].u3.z = m._34 - m._31;
4416 origin_plane[1] = m._44 - m._41;
4418 /* Top plane */
4419 vec[2].u1.x = m._14 - m._12;
4420 vec[2].u2.y = m._24 - m._22;
4421 vec[2].u3.z = m._34 - m._32;
4422 origin_plane[2] = m._44 - m._42;
4424 /* Bottom plane */
4425 vec[3].u1.x = m._14 + m._12;
4426 vec[3].u2.y = m._24 + m._22;
4427 vec[3].u3.z = m._34 + m._32;
4428 origin_plane[3] = m._44 + m._42;
4430 /* Front plane */
4431 vec[4].u1.x = m._13;
4432 vec[4].u2.y = m._23;
4433 vec[4].u3.z = m._33;
4434 origin_plane[4] = m._43;
4436 /* Back plane*/
4437 vec[5].u1.x = m._14 - m._13;
4438 vec[5].u2.y = m._24 - m._23;
4439 vec[5].u3.z = m._34 - m._33;
4440 origin_plane[5] = m._44 - m._43;
4442 for(i=0; i<NumSpheres; i++)
4444 ReturnValues[i] = 0;
4445 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4448 return D3D_OK;
4451 static HRESULT WINAPI IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4452 D3DVECTOR *Centers, D3DVALUE *Radii, DWORD NumSpheres, DWORD Flags, DWORD *ReturnValues)
4454 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4456 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4457 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4459 return IDirect3DDevice7_ComputeSphereVisibility(&This->IDirect3DDevice7_iface,
4460 Centers, Radii, NumSpheres, Flags, ReturnValues);
4463 /*****************************************************************************
4464 * IDirect3DDevice7::GetTexture
4466 * Returns the texture interface handle assigned to a texture stage.
4467 * The returned texture is AddRefed. This is taken from old ddraw,
4468 * not checked in Windows.
4470 * Version 3 and 7
4472 * Params:
4473 * Stage: Texture stage to read the texture from
4474 * Texture: Address to store the interface pointer at
4476 * Returns:
4477 * D3D_OK on success
4478 * DDERR_INVALIDPARAMS if Texture is NULL
4479 * For details, see IWineD3DDevice::GetTexture
4481 *****************************************************************************/
4482 static HRESULT
4483 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4484 DWORD Stage,
4485 IDirectDrawSurface7 **Texture)
4487 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4488 struct wined3d_texture *wined3d_texture;
4489 HRESULT hr;
4491 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4493 if(!Texture)
4495 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4496 return DDERR_INVALIDPARAMS;
4499 wined3d_mutex_lock();
4500 hr = wined3d_device_get_texture(This->wined3d_device, Stage, &wined3d_texture);
4501 if (FAILED(hr) || !wined3d_texture)
4503 *Texture = NULL;
4504 wined3d_mutex_unlock();
4505 return hr;
4508 *Texture = wined3d_texture_get_parent(wined3d_texture);
4509 IDirectDrawSurface7_AddRef(*Texture);
4510 wined3d_texture_decref(wined3d_texture);
4511 wined3d_mutex_unlock();
4513 return hr;
4516 static HRESULT WINAPI
4517 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4518 DWORD Stage,
4519 IDirectDrawSurface7 **Texture)
4521 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4524 static HRESULT WINAPI
4525 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4526 DWORD Stage,
4527 IDirectDrawSurface7 **Texture)
4529 HRESULT hr;
4530 WORD old_fpucw;
4532 old_fpucw = d3d_fpu_setup();
4533 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4534 set_fpu_control_word(old_fpucw);
4536 return hr;
4539 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface, DWORD Stage,
4540 IDirect3DTexture2 **Texture2)
4542 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4543 HRESULT ret;
4544 IDirectDrawSurface7 *ret_val;
4545 IDirectDrawSurfaceImpl *ret_val_impl;
4547 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4549 ret = IDirect3DDevice7_GetTexture(&This->IDirect3DDevice7_iface, Stage, &ret_val);
4551 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4552 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4554 TRACE("Returning texture %p.\n", *Texture2);
4556 return ret;
4559 /*****************************************************************************
4560 * IDirect3DDevice7::SetTexture
4562 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4564 * Version 3 and 7
4566 * Params:
4567 * Stage: The stage to assign the texture to
4568 * Texture: Interface pointer to the texture surface
4570 * Returns
4571 * D3D_OK on success
4572 * For details, see IWineD3DDevice::SetTexture
4574 *****************************************************************************/
4575 static HRESULT
4576 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4577 DWORD Stage,
4578 IDirectDrawSurface7 *Texture)
4580 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4581 IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
4582 HRESULT hr;
4584 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4586 /* Texture may be NULL here */
4587 wined3d_mutex_lock();
4588 hr = wined3d_device_set_texture(This->wined3d_device,
4589 Stage, surf ? surf->wined3d_texture : NULL);
4590 wined3d_mutex_unlock();
4592 return hr;
4595 static HRESULT WINAPI
4596 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4597 DWORD Stage,
4598 IDirectDrawSurface7 *Texture)
4600 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4603 static HRESULT WINAPI
4604 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4605 DWORD Stage,
4606 IDirectDrawSurface7 *Texture)
4608 HRESULT hr;
4609 WORD old_fpucw;
4611 old_fpucw = d3d_fpu_setup();
4612 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4613 set_fpu_control_word(old_fpucw);
4615 return hr;
4618 static HRESULT WINAPI
4619 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4620 DWORD Stage,
4621 IDirect3DTexture2 *Texture2)
4623 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4624 IDirectDrawSurfaceImpl *tex = unsafe_impl_from_IDirect3DTexture2(Texture2);
4625 DWORD texmapblend;
4626 HRESULT hr;
4628 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4630 wined3d_mutex_lock();
4632 if (This->legacyTextureBlending)
4633 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4635 hr = IDirect3DDevice7_SetTexture(&This->IDirect3DDevice7_iface, Stage, &tex->IDirectDrawSurface7_iface);
4637 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4639 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4640 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4641 struct wined3d_texture *tex = NULL;
4642 BOOL tex_alpha = FALSE;
4643 DDPIXELFORMAT ddfmt;
4644 HRESULT result;
4646 result = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
4647 if (result == WINED3D_OK && tex)
4649 struct wined3d_resource *sub_resource;
4651 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4653 struct wined3d_resource_desc desc;
4655 wined3d_resource_get_desc(sub_resource, &desc);
4656 ddfmt.dwSize = sizeof(ddfmt);
4657 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4658 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4661 wined3d_texture_decref(tex);
4664 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4665 if (tex_alpha)
4666 wined3d_device_set_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4667 else
4668 wined3d_device_set_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4671 wined3d_mutex_unlock();
4673 return hr;
4676 static const struct tss_lookup
4678 BOOL sampler_state;
4679 DWORD state;
4681 tss_lookup[] =
4683 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
4684 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
4685 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
4686 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
4687 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
4688 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
4689 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
4690 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4691 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4692 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4693 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4694 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4695 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
4696 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
4697 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
4698 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
4699 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
4700 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
4701 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
4702 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4703 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4704 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4705 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4706 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4707 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4710 /*****************************************************************************
4711 * IDirect3DDevice7::GetTextureStageState
4713 * Retrieves a state from a texture stage.
4715 * Version 3 and 7
4717 * Params:
4718 * Stage: The stage to retrieve the state from
4719 * TexStageStateType: The state type to retrieve
4720 * State: Address to store the state's value at
4722 * Returns:
4723 * D3D_OK on success
4724 * DDERR_INVALIDPARAMS if State is NULL
4725 * For details, see IWineD3DDevice::GetTextureStageState
4727 *****************************************************************************/
4728 static HRESULT
4729 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4730 DWORD Stage,
4731 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4732 DWORD *State)
4734 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4735 HRESULT hr;
4736 const struct tss_lookup *l;
4738 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4739 iface, Stage, TexStageStateType, State);
4741 if(!State)
4742 return DDERR_INVALIDPARAMS;
4744 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4746 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4747 return DD_OK;
4750 l = &tss_lookup[TexStageStateType];
4752 wined3d_mutex_lock();
4754 if (l->sampler_state)
4756 hr = wined3d_device_get_sampler_state(This->wined3d_device, Stage, l->state, State);
4758 switch(TexStageStateType)
4760 /* Mipfilter is a sampler state with different values */
4761 case D3DTSS_MIPFILTER:
4763 switch(*State)
4765 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4766 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4767 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4768 default:
4769 ERR("Unexpected mipfilter value %#x\n", *State);
4770 *State = D3DTFP_NONE;
4771 break;
4773 break;
4776 /* Magfilter has slightly different values */
4777 case D3DTSS_MAGFILTER:
4779 switch(*State)
4781 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4782 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4783 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4784 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4785 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4786 default:
4787 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4788 *State = D3DTFG_POINT;
4789 break;
4791 break;
4794 default:
4795 break;
4798 else
4800 hr = wined3d_device_get_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4803 wined3d_mutex_unlock();
4805 return hr;
4808 static HRESULT WINAPI
4809 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4810 DWORD Stage,
4811 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4812 DWORD *State)
4814 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4817 static HRESULT WINAPI
4818 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4819 DWORD Stage,
4820 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4821 DWORD *State)
4823 HRESULT hr;
4824 WORD old_fpucw;
4826 old_fpucw = d3d_fpu_setup();
4827 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4828 set_fpu_control_word(old_fpucw);
4830 return hr;
4833 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4834 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD *State)
4836 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4838 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4839 iface, Stage, TexStageStateType, State);
4841 return IDirect3DDevice7_GetTextureStageState(&This->IDirect3DDevice7_iface,
4842 Stage, TexStageStateType, State);
4845 /*****************************************************************************
4846 * IDirect3DDevice7::SetTextureStageState
4848 * Sets a texture stage state. Some stage types need to be handled specially,
4849 * because they do not exist in WineD3D and were moved to another place
4851 * Version 3 and 7
4853 * Params:
4854 * Stage: The stage to modify
4855 * TexStageStateType: The state to change
4856 * State: The new value for the state
4858 * Returns:
4859 * D3D_OK on success
4860 * For details, see IWineD3DDevice::SetTextureStageState
4862 *****************************************************************************/
4863 static HRESULT
4864 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4865 DWORD Stage,
4866 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4867 DWORD State)
4869 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4870 const struct tss_lookup *l;
4871 HRESULT hr;
4873 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4874 iface, Stage, TexStageStateType, State);
4876 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4878 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4879 return DD_OK;
4882 l = &tss_lookup[TexStageStateType];
4884 wined3d_mutex_lock();
4886 if (l->sampler_state)
4888 switch(TexStageStateType)
4890 /* Mipfilter is a sampler state with different values */
4891 case D3DTSS_MIPFILTER:
4893 switch(State)
4895 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
4896 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
4897 case 0: /* Unchecked */
4898 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
4899 default:
4900 ERR("Unexpected mipfilter value %d\n", State);
4901 State = WINED3DTEXF_NONE;
4902 break;
4904 break;
4907 /* Magfilter has slightly different values */
4908 case D3DTSS_MAGFILTER:
4910 switch(State)
4912 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
4913 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
4914 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
4915 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
4916 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
4917 default:
4918 ERR("Unexpected d3d7 mag filter type %d\n", State);
4919 State = WINED3DTEXF_POINT;
4920 break;
4922 break;
4925 case D3DTSS_ADDRESS:
4926 wined3d_device_set_sampler_state(This->wined3d_device, Stage, WINED3DSAMP_ADDRESSV, State);
4927 break;
4929 default:
4930 break;
4933 hr = wined3d_device_set_sampler_state(This->wined3d_device, Stage, l->state, State);
4935 else
4937 hr = wined3d_device_set_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4940 wined3d_mutex_unlock();
4942 return hr;
4945 static HRESULT WINAPI
4946 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4947 DWORD Stage,
4948 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4949 DWORD State)
4951 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4954 static HRESULT WINAPI
4955 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4956 DWORD Stage,
4957 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4958 DWORD State)
4960 HRESULT hr;
4961 WORD old_fpucw;
4963 old_fpucw = d3d_fpu_setup();
4964 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4965 set_fpu_control_word(old_fpucw);
4967 return hr;
4970 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
4971 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD State)
4973 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4975 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4976 iface, Stage, TexStageStateType, State);
4978 return IDirect3DDevice7_SetTextureStageState(&This->IDirect3DDevice7_iface,
4979 Stage, TexStageStateType, State);
4982 /*****************************************************************************
4983 * IDirect3DDevice7::ValidateDevice
4985 * SDK: "Reports the device's ability to render the currently set
4986 * texture-blending operations in a single pass". Whatever that means
4987 * exactly...
4989 * Version 3 and 7
4991 * Params:
4992 * NumPasses: Address to write the number of necessary passes for the
4993 * desired effect to.
4995 * Returns:
4996 * D3D_OK on success
4997 * See IWineD3DDevice::ValidateDevice for more details
4999 *****************************************************************************/
5000 static HRESULT
5001 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
5002 DWORD *NumPasses)
5004 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5005 HRESULT hr;
5007 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
5009 wined3d_mutex_lock();
5010 hr = wined3d_device_validate_device(This->wined3d_device, NumPasses);
5011 wined3d_mutex_unlock();
5013 return hr;
5016 static HRESULT WINAPI
5017 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
5018 DWORD *NumPasses)
5020 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5023 static HRESULT WINAPI
5024 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
5025 DWORD *NumPasses)
5027 HRESULT hr;
5028 WORD old_fpucw;
5030 old_fpucw = d3d_fpu_setup();
5031 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5032 set_fpu_control_word(old_fpucw);
5034 return hr;
5037 static HRESULT WINAPI IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *Passes)
5039 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
5041 TRACE("iface %p, pass_count %p.\n", iface, Passes);
5043 return IDirect3DDevice7_ValidateDevice(&This->IDirect3DDevice7_iface, Passes);
5046 /*****************************************************************************
5047 * IDirect3DDevice7::Clear
5049 * Fills the render target, the z buffer and the stencil buffer with a
5050 * clear color / value
5052 * Version 7 only
5054 * Params:
5055 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5056 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5057 * Flags: Some flags, as usual
5058 * Color: Clear color for the render target
5059 * Z: Clear value for the Z buffer
5060 * Stencil: Clear value to store in each stencil buffer entry
5062 * Returns:
5063 * D3D_OK on success
5064 * For details, see IWineD3DDevice::Clear
5066 *****************************************************************************/
5067 static HRESULT IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface, DWORD count,
5068 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5070 const struct wined3d_color c =
5072 ((color >> 16) & 0xff) / 255.0f,
5073 ((color >> 8) & 0xff) / 255.0f,
5074 (color & 0xff) / 255.0f,
5075 ((color >> 24) & 0xff) / 255.0f,
5077 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5078 HRESULT hr;
5080 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5081 iface, count, rects, flags, color, z, stencil);
5083 wined3d_mutex_lock();
5084 hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
5085 wined3d_mutex_unlock();
5087 return hr;
5090 static HRESULT WINAPI
5091 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5092 DWORD Count,
5093 D3DRECT *Rects,
5094 DWORD Flags,
5095 D3DCOLOR Color,
5096 D3DVALUE Z,
5097 DWORD Stencil)
5099 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5102 static HRESULT WINAPI
5103 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5104 DWORD Count,
5105 D3DRECT *Rects,
5106 DWORD Flags,
5107 D3DCOLOR Color,
5108 D3DVALUE Z,
5109 DWORD Stencil)
5111 HRESULT hr;
5112 WORD old_fpucw;
5114 old_fpucw = d3d_fpu_setup();
5115 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5116 set_fpu_control_word(old_fpucw);
5118 return hr;
5121 /*****************************************************************************
5122 * IDirect3DDevice7::SetViewport
5124 * Sets the current viewport.
5126 * Version 7 only, but IDirect3DViewport uses this call for older
5127 * versions
5129 * Params:
5130 * Data: The new viewport to set
5132 * Returns:
5133 * D3D_OK on success
5134 * DDERR_INVALIDPARAMS if Data is NULL
5135 * For more details, see IWineDDDevice::SetViewport
5137 *****************************************************************************/
5138 static HRESULT
5139 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5140 D3DVIEWPORT7 *Data)
5142 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5143 HRESULT hr;
5145 TRACE("iface %p, viewport %p.\n", iface, Data);
5147 if(!Data)
5148 return DDERR_INVALIDPARAMS;
5150 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5151 wined3d_mutex_lock();
5152 hr = wined3d_device_set_viewport(This->wined3d_device, (struct wined3d_viewport *)Data);
5153 wined3d_mutex_unlock();
5155 return hr;
5158 static HRESULT WINAPI
5159 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5160 D3DVIEWPORT7 *Data)
5162 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5165 static HRESULT WINAPI
5166 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5167 D3DVIEWPORT7 *Data)
5169 HRESULT hr;
5170 WORD old_fpucw;
5172 old_fpucw = d3d_fpu_setup();
5173 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5174 set_fpu_control_word(old_fpucw);
5176 return hr;
5179 /*****************************************************************************
5180 * IDirect3DDevice::GetViewport
5182 * Returns the current viewport
5184 * Version 7
5186 * Params:
5187 * Data: D3D7Viewport structure to write the viewport information to
5189 * Returns:
5190 * D3D_OK on success
5191 * DDERR_INVALIDPARAMS if Data is NULL
5192 * For more details, see IWineD3DDevice::GetViewport
5194 *****************************************************************************/
5195 static HRESULT
5196 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5197 D3DVIEWPORT7 *Data)
5199 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5200 HRESULT hr;
5202 TRACE("iface %p, viewport %p.\n", iface, Data);
5204 if(!Data)
5205 return DDERR_INVALIDPARAMS;
5207 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5208 wined3d_mutex_lock();
5209 hr = wined3d_device_get_viewport(This->wined3d_device, (struct wined3d_viewport *)Data);
5210 wined3d_mutex_unlock();
5212 return hr_ddraw_from_wined3d(hr);
5215 static HRESULT WINAPI
5216 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5217 D3DVIEWPORT7 *Data)
5219 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5222 static HRESULT WINAPI
5223 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5224 D3DVIEWPORT7 *Data)
5226 HRESULT hr;
5227 WORD old_fpucw;
5229 old_fpucw = d3d_fpu_setup();
5230 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5231 set_fpu_control_word(old_fpucw);
5233 return hr;
5236 /*****************************************************************************
5237 * IDirect3DDevice7::SetMaterial
5239 * Sets the Material
5241 * Version 7
5243 * Params:
5244 * Mat: The material to set
5246 * Returns:
5247 * D3D_OK on success
5248 * DDERR_INVALIDPARAMS if Mat is NULL.
5249 * For more details, see IWineD3DDevice::SetMaterial
5251 *****************************************************************************/
5252 static HRESULT
5253 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5254 D3DMATERIAL7 *Mat)
5256 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5257 HRESULT hr;
5259 TRACE("iface %p, material %p.\n", iface, Mat);
5261 if (!Mat) return DDERR_INVALIDPARAMS;
5263 wined3d_mutex_lock();
5264 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5265 hr = wined3d_device_set_material(This->wined3d_device, (struct wined3d_material *)Mat);
5266 wined3d_mutex_unlock();
5268 return hr_ddraw_from_wined3d(hr);
5271 static HRESULT WINAPI
5272 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5273 D3DMATERIAL7 *Mat)
5275 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5278 static HRESULT WINAPI
5279 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5280 D3DMATERIAL7 *Mat)
5282 HRESULT hr;
5283 WORD old_fpucw;
5285 old_fpucw = d3d_fpu_setup();
5286 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5287 set_fpu_control_word(old_fpucw);
5289 return hr;
5292 /*****************************************************************************
5293 * IDirect3DDevice7::GetMaterial
5295 * Returns the current material
5297 * Version 7
5299 * Params:
5300 * Mat: D3DMATERIAL7 structure to write the material parameters to
5302 * Returns:
5303 * D3D_OK on success
5304 * DDERR_INVALIDPARAMS if Mat is NULL
5305 * For more details, see IWineD3DDevice::GetMaterial
5307 *****************************************************************************/
5308 static HRESULT
5309 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5310 D3DMATERIAL7 *Mat)
5312 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5313 HRESULT hr;
5315 TRACE("iface %p, material %p.\n", iface, Mat);
5317 wined3d_mutex_lock();
5318 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5319 hr = wined3d_device_get_material(This->wined3d_device, (struct wined3d_material *)Mat);
5320 wined3d_mutex_unlock();
5322 return hr_ddraw_from_wined3d(hr);
5325 static HRESULT WINAPI
5326 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5327 D3DMATERIAL7 *Mat)
5329 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5332 static HRESULT WINAPI
5333 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5334 D3DMATERIAL7 *Mat)
5336 HRESULT hr;
5337 WORD old_fpucw;
5339 old_fpucw = d3d_fpu_setup();
5340 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5341 set_fpu_control_word(old_fpucw);
5343 return hr;
5346 /*****************************************************************************
5347 * IDirect3DDevice7::SetLight
5349 * Assigns a light to a light index, but doesn't activate it yet.
5351 * Version 7, IDirect3DLight uses this method for older versions
5353 * Params:
5354 * LightIndex: The index of the new light
5355 * Light: A D3DLIGHT7 structure describing the light
5357 * Returns:
5358 * D3D_OK on success
5359 * For more details, see IWineD3DDevice::SetLight
5361 *****************************************************************************/
5362 static HRESULT
5363 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5364 DWORD LightIndex,
5365 D3DLIGHT7 *Light)
5367 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5368 HRESULT hr;
5370 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5372 wined3d_mutex_lock();
5373 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5374 hr = wined3d_device_set_light(This->wined3d_device, LightIndex, (struct wined3d_light *)Light);
5375 wined3d_mutex_unlock();
5377 return hr_ddraw_from_wined3d(hr);
5380 static HRESULT WINAPI
5381 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5382 DWORD LightIndex,
5383 D3DLIGHT7 *Light)
5385 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5388 static HRESULT WINAPI
5389 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5390 DWORD LightIndex,
5391 D3DLIGHT7 *Light)
5393 HRESULT hr;
5394 WORD old_fpucw;
5396 old_fpucw = d3d_fpu_setup();
5397 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5398 set_fpu_control_word(old_fpucw);
5400 return hr;
5403 /*****************************************************************************
5404 * IDirect3DDevice7::GetLight
5406 * Returns the light assigned to a light index
5408 * Params:
5409 * Light: Structure to write the light information to
5411 * Returns:
5412 * D3D_OK on success
5413 * DDERR_INVALIDPARAMS if Light is NULL
5414 * For details, see IWineD3DDevice::GetLight
5416 *****************************************************************************/
5417 static HRESULT
5418 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5419 DWORD LightIndex,
5420 D3DLIGHT7 *Light)
5422 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5423 HRESULT rc;
5425 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5427 wined3d_mutex_lock();
5428 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5429 rc = wined3d_device_get_light(This->wined3d_device, LightIndex, (struct wined3d_light *)Light);
5430 wined3d_mutex_unlock();
5432 /* Translate the result. WineD3D returns other values than D3D7 */
5433 return hr_ddraw_from_wined3d(rc);
5436 static HRESULT WINAPI
5437 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5438 DWORD LightIndex,
5439 D3DLIGHT7 *Light)
5441 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5444 static HRESULT WINAPI
5445 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5446 DWORD LightIndex,
5447 D3DLIGHT7 *Light)
5449 HRESULT hr;
5450 WORD old_fpucw;
5452 old_fpucw = d3d_fpu_setup();
5453 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5454 set_fpu_control_word(old_fpucw);
5456 return hr;
5459 /*****************************************************************************
5460 * IDirect3DDevice7::BeginStateBlock
5462 * Begins recording to a stateblock
5464 * Version 7
5466 * Returns:
5467 * D3D_OK on success
5468 * For details see IWineD3DDevice::BeginStateBlock
5470 *****************************************************************************/
5471 static HRESULT
5472 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5474 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5475 HRESULT hr;
5477 TRACE("iface %p.\n", iface);
5479 wined3d_mutex_lock();
5480 hr = wined3d_device_begin_stateblock(This->wined3d_device);
5481 wined3d_mutex_unlock();
5483 return hr_ddraw_from_wined3d(hr);
5486 static HRESULT WINAPI
5487 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5489 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5492 static HRESULT WINAPI
5493 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5495 HRESULT hr;
5496 WORD old_fpucw;
5498 old_fpucw = d3d_fpu_setup();
5499 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5500 set_fpu_control_word(old_fpucw);
5502 return hr;
5505 /*****************************************************************************
5506 * IDirect3DDevice7::EndStateBlock
5508 * Stops recording to a state block and returns the created stateblock
5509 * handle.
5511 * Version 7
5513 * Params:
5514 * BlockHandle: Address to store the stateblock's handle to
5516 * Returns:
5517 * D3D_OK on success
5518 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5519 * See IWineD3DDevice::EndStateBlock for more details
5521 *****************************************************************************/
5522 static HRESULT
5523 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5524 DWORD *BlockHandle)
5526 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5527 struct wined3d_stateblock *wined3d_sb;
5528 HRESULT hr;
5529 DWORD h;
5531 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5533 if(!BlockHandle)
5535 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5536 return DDERR_INVALIDPARAMS;
5539 wined3d_mutex_lock();
5541 hr = wined3d_device_end_stateblock(This->wined3d_device, &wined3d_sb);
5542 if (FAILED(hr))
5544 WARN("Failed to end stateblock, hr %#x.\n", hr);
5545 wined3d_mutex_unlock();
5546 *BlockHandle = 0;
5547 return hr_ddraw_from_wined3d(hr);
5550 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5551 if (h == DDRAW_INVALID_HANDLE)
5553 ERR("Failed to allocate a stateblock handle.\n");
5554 wined3d_stateblock_decref(wined3d_sb);
5555 wined3d_mutex_unlock();
5556 *BlockHandle = 0;
5557 return DDERR_OUTOFMEMORY;
5560 wined3d_mutex_unlock();
5561 *BlockHandle = h + 1;
5563 return hr_ddraw_from_wined3d(hr);
5566 static HRESULT WINAPI
5567 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5568 DWORD *BlockHandle)
5570 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5573 static HRESULT WINAPI
5574 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5575 DWORD *BlockHandle)
5577 HRESULT hr;
5578 WORD old_fpucw;
5580 old_fpucw = d3d_fpu_setup();
5581 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5582 set_fpu_control_word(old_fpucw);
5584 return hr;
5587 /*****************************************************************************
5588 * IDirect3DDevice7::PreLoad
5590 * Allows the app to signal that a texture will be used soon, to allow
5591 * the Direct3DDevice to load it to the video card in the meantime.
5593 * Version 7
5595 * Params:
5596 * Texture: The texture to preload
5598 * Returns:
5599 * D3D_OK on success
5600 * DDERR_INVALIDPARAMS if Texture is NULL
5601 * See IWineD3DSurface::PreLoad for details
5603 *****************************************************************************/
5604 static HRESULT
5605 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5606 IDirectDrawSurface7 *Texture)
5608 IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
5610 TRACE("iface %p, texture %p.\n", iface, Texture);
5612 if(!Texture)
5613 return DDERR_INVALIDPARAMS;
5615 wined3d_mutex_lock();
5616 wined3d_surface_preload(surf->wined3d_surface);
5617 wined3d_mutex_unlock();
5619 return D3D_OK;
5622 static HRESULT WINAPI
5623 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5624 IDirectDrawSurface7 *Texture)
5626 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5629 static HRESULT WINAPI
5630 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5631 IDirectDrawSurface7 *Texture)
5633 HRESULT hr;
5634 WORD old_fpucw;
5636 old_fpucw = d3d_fpu_setup();
5637 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5638 set_fpu_control_word(old_fpucw);
5640 return hr;
5643 /*****************************************************************************
5644 * IDirect3DDevice7::ApplyStateBlock
5646 * Activates the state stored in a state block handle.
5648 * Params:
5649 * BlockHandle: The stateblock handle to activate
5651 * Returns:
5652 * D3D_OK on success
5653 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5655 *****************************************************************************/
5656 static HRESULT
5657 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5658 DWORD BlockHandle)
5660 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5661 struct wined3d_stateblock *wined3d_sb;
5662 HRESULT hr;
5664 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5666 wined3d_mutex_lock();
5667 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5668 if (!wined3d_sb)
5670 WARN("Invalid stateblock handle.\n");
5671 wined3d_mutex_unlock();
5672 return D3DERR_INVALIDSTATEBLOCK;
5675 hr = wined3d_stateblock_apply(wined3d_sb);
5676 wined3d_mutex_unlock();
5678 return hr_ddraw_from_wined3d(hr);
5681 static HRESULT WINAPI
5682 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5683 DWORD BlockHandle)
5685 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5688 static HRESULT WINAPI
5689 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5690 DWORD BlockHandle)
5692 HRESULT hr;
5693 WORD old_fpucw;
5695 old_fpucw = d3d_fpu_setup();
5696 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5697 set_fpu_control_word(old_fpucw);
5699 return hr;
5702 /*****************************************************************************
5703 * IDirect3DDevice7::CaptureStateBlock
5705 * Updates a stateblock's values to the values currently set for the device
5707 * Version 7
5709 * Params:
5710 * BlockHandle: Stateblock to update
5712 * Returns:
5713 * D3D_OK on success
5714 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5715 * See IWineD3DDevice::CaptureStateBlock for more details
5717 *****************************************************************************/
5718 static HRESULT
5719 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5720 DWORD BlockHandle)
5722 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5723 struct wined3d_stateblock *wined3d_sb;
5724 HRESULT hr;
5726 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5728 wined3d_mutex_lock();
5729 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5730 if (!wined3d_sb)
5732 WARN("Invalid stateblock handle.\n");
5733 wined3d_mutex_unlock();
5734 return D3DERR_INVALIDSTATEBLOCK;
5737 hr = wined3d_stateblock_capture(wined3d_sb);
5738 wined3d_mutex_unlock();
5740 return hr_ddraw_from_wined3d(hr);
5743 static HRESULT WINAPI
5744 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5745 DWORD BlockHandle)
5747 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5750 static HRESULT WINAPI
5751 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5752 DWORD BlockHandle)
5754 HRESULT hr;
5755 WORD old_fpucw;
5757 old_fpucw = d3d_fpu_setup();
5758 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5759 set_fpu_control_word(old_fpucw);
5761 return hr;
5764 /*****************************************************************************
5765 * IDirect3DDevice7::DeleteStateBlock
5767 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5769 * Version 7
5771 * Params:
5772 * BlockHandle: Stateblock handle to delete
5774 * Returns:
5775 * D3D_OK on success
5776 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5778 *****************************************************************************/
5779 static HRESULT
5780 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5781 DWORD BlockHandle)
5783 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5784 struct wined3d_stateblock *wined3d_sb;
5785 ULONG ref;
5787 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5789 wined3d_mutex_lock();
5791 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5792 if (!wined3d_sb)
5794 WARN("Invalid stateblock handle.\n");
5795 wined3d_mutex_unlock();
5796 return D3DERR_INVALIDSTATEBLOCK;
5799 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5801 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5804 wined3d_mutex_unlock();
5806 return D3D_OK;
5809 static HRESULT WINAPI
5810 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5811 DWORD BlockHandle)
5813 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5816 static HRESULT WINAPI
5817 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5818 DWORD BlockHandle)
5820 HRESULT hr;
5821 WORD old_fpucw;
5823 old_fpucw = d3d_fpu_setup();
5824 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5825 set_fpu_control_word(old_fpucw);
5827 return hr;
5830 /*****************************************************************************
5831 * IDirect3DDevice7::CreateStateBlock
5833 * Creates a new state block handle.
5835 * Version 7
5837 * Params:
5838 * Type: The state block type
5839 * BlockHandle: Address to write the created handle to
5841 * Returns:
5842 * D3D_OK on success
5843 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5845 *****************************************************************************/
5846 static HRESULT
5847 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5848 D3DSTATEBLOCKTYPE Type,
5849 DWORD *BlockHandle)
5851 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5852 struct wined3d_stateblock *wined3d_sb;
5853 HRESULT hr;
5854 DWORD h;
5856 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5858 if(!BlockHandle)
5860 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5861 return DDERR_INVALIDPARAMS;
5863 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5864 Type != D3DSBT_VERTEXSTATE ) {
5865 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5866 return DDERR_INVALIDPARAMS;
5869 wined3d_mutex_lock();
5871 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5872 hr = wined3d_stateblock_create(This->wined3d_device, Type, &wined3d_sb);
5873 if (FAILED(hr))
5875 WARN("Failed to create stateblock, hr %#x.\n", hr);
5876 wined3d_mutex_unlock();
5877 return hr_ddraw_from_wined3d(hr);
5880 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5881 if (h == DDRAW_INVALID_HANDLE)
5883 ERR("Failed to allocate stateblock handle.\n");
5884 wined3d_stateblock_decref(wined3d_sb);
5885 wined3d_mutex_unlock();
5886 return DDERR_OUTOFMEMORY;
5889 *BlockHandle = h + 1;
5890 wined3d_mutex_unlock();
5892 return hr_ddraw_from_wined3d(hr);
5895 static HRESULT WINAPI
5896 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5897 D3DSTATEBLOCKTYPE Type,
5898 DWORD *BlockHandle)
5900 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5903 static HRESULT WINAPI
5904 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5905 D3DSTATEBLOCKTYPE Type,
5906 DWORD *BlockHandle)
5908 HRESULT hr;
5909 WORD old_fpucw;
5911 old_fpucw = d3d_fpu_setup();
5912 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5913 set_fpu_control_word(old_fpucw);
5915 return hr;
5918 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5919 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
5920 IDirectDrawSurfaceImpl *src)
5922 IDirectDrawSurfaceImpl *src_level, *dest_level;
5923 IDirectDrawSurface7 *temp;
5924 DDSURFACEDESC2 ddsd;
5925 BOOL levelFound; /* at least one suitable sublevel in dest found */
5927 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5928 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5929 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5931 levelFound = FALSE;
5933 src_level = src;
5934 dest_level = dest;
5936 for (;src_level && dest_level;)
5938 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5939 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5941 levelFound = TRUE;
5943 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5944 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5945 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5947 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5949 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5952 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5953 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5954 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5956 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5958 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5961 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5962 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5964 return !dest_level && levelFound;
5967 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5968 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
5969 IDirectDrawSurfaceImpl *dest,
5970 IDirectDrawSurfaceImpl *src,
5971 const POINT *DestPoint,
5972 const RECT *SrcRect)
5974 IDirectDrawSurfaceImpl *src_level, *dest_level;
5975 IDirectDrawSurface7 *temp;
5976 DDSURFACEDESC2 ddsd;
5977 POINT point;
5978 RECT src_rect;
5979 HRESULT hr;
5980 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5981 DWORD ckeyflag;
5982 DDCOLORKEY ddckey;
5984 /* Copy palette, if possible. */
5985 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
5986 IDirectDrawSurface7_GetPalette(&dest->IDirectDrawSurface7_iface, &pal);
5988 if (pal_src != NULL && pal != NULL)
5990 PALETTEENTRY palent[256];
5992 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5993 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5996 if (pal) IDirectDrawPalette_Release(pal);
5997 if (pal_src) IDirectDrawPalette_Release(pal_src);
5999 /* Copy colorkeys, if present. */
6000 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6002 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6004 if (SUCCEEDED(hr))
6006 IDirectDrawSurface7_SetColorKey(&dest->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6010 src_level = src;
6011 dest_level = dest;
6013 point = *DestPoint;
6014 src_rect = *SrcRect;
6016 for (;src_level && dest_level;)
6018 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6019 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6021 UINT src_w = src_rect.right - src_rect.left;
6022 UINT src_h = src_rect.bottom - src_rect.top;
6023 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
6025 if (FAILED(hr = wined3d_surface_blt(dest_level->wined3d_surface, &dst_rect,
6026 src_level->wined3d_surface, &src_rect, 0, NULL, WINED3DTEXF_POINT)))
6027 ERR("Blit failed, hr %#x.\n", hr);
6029 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6030 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6031 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6033 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6035 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6038 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6039 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6040 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6042 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6044 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6046 point.x /= 2;
6047 point.y /= 2;
6049 src_rect.top /= 2;
6050 src_rect.left /= 2;
6051 src_rect.right = (src_rect.right + 1) / 2;
6052 src_rect.bottom = (src_rect.bottom + 1) / 2;
6055 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6056 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6059 /*****************************************************************************
6060 * IDirect3DDevice7::Load
6062 * Loads a rectangular area from the source into the destination texture.
6063 * It can also copy the source to the faces of a cubic environment map
6065 * Version 7
6067 * Params:
6068 * DestTex: Destination texture
6069 * DestPoint: Point in the destination where the source image should be
6070 * written to
6071 * SrcTex: Source texture
6072 * SrcRect: Source rectangle
6073 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6074 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6075 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6077 * Returns:
6078 * D3D_OK on success
6079 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6082 *****************************************************************************/
6084 static HRESULT
6085 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6086 IDirectDrawSurface7 *DestTex,
6087 POINT *DestPoint,
6088 IDirectDrawSurface7 *SrcTex,
6089 RECT *SrcRect,
6090 DWORD Flags)
6092 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6093 IDirectDrawSurfaceImpl *dest = unsafe_impl_from_IDirectDrawSurface7(DestTex);
6094 IDirectDrawSurfaceImpl *src = unsafe_impl_from_IDirectDrawSurface7(SrcTex);
6095 POINT destpoint;
6096 RECT srcrect;
6098 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6099 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6101 if( (!src) || (!dest) )
6102 return DDERR_INVALIDPARAMS;
6104 wined3d_mutex_lock();
6106 if (SrcRect) srcrect = *SrcRect;
6107 else
6109 srcrect.left = srcrect.top = 0;
6110 srcrect.right = src->surface_desc.dwWidth;
6111 srcrect.bottom = src->surface_desc.dwHeight;
6114 if (DestPoint) destpoint = *DestPoint;
6115 else
6117 destpoint.x = destpoint.y = 0;
6119 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6120 * destination can be a subset of mip levels, in which case actual coordinates used
6121 * for it may be divided. If any dimension of dest is larger than source, it can't be
6122 * mip level subset, so an error can be returned early.
6124 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6125 srcrect.right > src->surface_desc.dwWidth ||
6126 srcrect.bottom > src->surface_desc.dwHeight ||
6127 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6128 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6129 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6130 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6132 wined3d_mutex_unlock();
6133 return DDERR_INVALIDPARAMS;
6136 /* Must be top level surfaces. */
6137 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6138 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6140 wined3d_mutex_unlock();
6141 return DDERR_INVALIDPARAMS;
6144 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6146 DWORD src_face_flag, dest_face_flag;
6147 IDirectDrawSurfaceImpl *src_face, *dest_face;
6148 IDirectDrawSurface7 *temp;
6149 DDSURFACEDESC2 ddsd;
6150 int i;
6152 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6154 wined3d_mutex_unlock();
6155 return DDERR_INVALIDPARAMS;
6158 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6159 * time it's actual surface loading. */
6160 for (i = 0; i < 2; i++)
6162 dest_face = dest;
6163 src_face = src;
6165 for (;dest_face && src_face;)
6167 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6168 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6170 if (src_face_flag == dest_face_flag)
6172 if (i == 0)
6174 /* Destination mip levels must be subset of source mip levels. */
6175 if (!is_mip_level_subset(dest_face, src_face))
6177 wined3d_mutex_unlock();
6178 return DDERR_INVALIDPARAMS;
6181 else if (Flags & dest_face_flag)
6183 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6186 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6188 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6189 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6190 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6192 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6194 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6196 else
6198 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6200 src_face = NULL;
6204 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6206 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6207 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6208 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6210 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6212 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6214 else
6216 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6218 dest_face = NULL;
6222 if (i == 0)
6224 /* Native returns error if src faces are not subset of dest faces. */
6225 if (src_face)
6227 wined3d_mutex_unlock();
6228 return DDERR_INVALIDPARAMS;
6233 wined3d_mutex_unlock();
6234 return D3D_OK;
6236 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6238 wined3d_mutex_unlock();
6239 return DDERR_INVALIDPARAMS;
6242 /* Handle non cube map textures. */
6244 /* Destination mip levels must be subset of source mip levels. */
6245 if (!is_mip_level_subset(dest, src))
6247 wined3d_mutex_unlock();
6248 return DDERR_INVALIDPARAMS;
6251 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6253 wined3d_mutex_unlock();
6255 return D3D_OK;
6258 static HRESULT WINAPI
6259 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6260 IDirectDrawSurface7 *DestTex,
6261 POINT *DestPoint,
6262 IDirectDrawSurface7 *SrcTex,
6263 RECT *SrcRect,
6264 DWORD Flags)
6266 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6269 static HRESULT WINAPI
6270 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6271 IDirectDrawSurface7 *DestTex,
6272 POINT *DestPoint,
6273 IDirectDrawSurface7 *SrcTex,
6274 RECT *SrcRect,
6275 DWORD Flags)
6277 HRESULT hr;
6278 WORD old_fpucw;
6280 old_fpucw = d3d_fpu_setup();
6281 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6282 set_fpu_control_word(old_fpucw);
6284 return hr;
6287 /*****************************************************************************
6288 * IDirect3DDevice7::LightEnable
6290 * Enables or disables a light
6292 * Version 7, IDirect3DLight uses this method too.
6294 * Params:
6295 * LightIndex: The index of the light to enable / disable
6296 * Enable: Enable or disable the light
6298 * Returns:
6299 * D3D_OK on success
6300 * For more details, see IWineD3DDevice::SetLightEnable
6302 *****************************************************************************/
6303 static HRESULT
6304 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6305 DWORD LightIndex,
6306 BOOL Enable)
6308 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6309 HRESULT hr;
6311 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6313 wined3d_mutex_lock();
6314 hr = wined3d_device_set_light_enable(This->wined3d_device, LightIndex, Enable);
6315 wined3d_mutex_unlock();
6317 return hr_ddraw_from_wined3d(hr);
6320 static HRESULT WINAPI
6321 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6322 DWORD LightIndex,
6323 BOOL Enable)
6325 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6328 static HRESULT WINAPI
6329 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6330 DWORD LightIndex,
6331 BOOL Enable)
6333 HRESULT hr;
6334 WORD old_fpucw;
6336 old_fpucw = d3d_fpu_setup();
6337 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6338 set_fpu_control_word(old_fpucw);
6340 return hr;
6343 /*****************************************************************************
6344 * IDirect3DDevice7::GetLightEnable
6346 * Retrieves if the light with the given index is enabled or not
6348 * Version 7
6350 * Params:
6351 * LightIndex: Index of desired light
6352 * Enable: Pointer to a BOOL which contains the result
6354 * Returns:
6355 * D3D_OK on success
6356 * DDERR_INVALIDPARAMS if Enable is NULL
6357 * See IWineD3DDevice::GetLightEnable for more details
6359 *****************************************************************************/
6360 static HRESULT
6361 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6362 DWORD LightIndex,
6363 BOOL* Enable)
6365 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6366 HRESULT hr;
6368 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6370 if(!Enable)
6371 return DDERR_INVALIDPARAMS;
6373 wined3d_mutex_lock();
6374 hr = wined3d_device_get_light_enable(This->wined3d_device, LightIndex, Enable);
6375 wined3d_mutex_unlock();
6377 return hr_ddraw_from_wined3d(hr);
6380 static HRESULT WINAPI
6381 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6382 DWORD LightIndex,
6383 BOOL* Enable)
6385 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6388 static HRESULT WINAPI
6389 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6390 DWORD LightIndex,
6391 BOOL* Enable)
6393 HRESULT hr;
6394 WORD old_fpucw;
6396 old_fpucw = d3d_fpu_setup();
6397 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6398 set_fpu_control_word(old_fpucw);
6400 return hr;
6403 /*****************************************************************************
6404 * IDirect3DDevice7::SetClipPlane
6406 * Sets custom clipping plane
6408 * Version 7
6410 * Params:
6411 * Index: The index of the clipping plane
6412 * PlaneEquation: An equation defining the clipping plane
6414 * Returns:
6415 * D3D_OK on success
6416 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6417 * See IWineD3DDevice::SetClipPlane for more details
6419 *****************************************************************************/
6420 static HRESULT
6421 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6422 DWORD Index,
6423 D3DVALUE* PlaneEquation)
6425 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6426 HRESULT hr;
6428 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6430 if(!PlaneEquation)
6431 return DDERR_INVALIDPARAMS;
6433 wined3d_mutex_lock();
6434 hr = wined3d_device_set_clip_plane(This->wined3d_device, Index, PlaneEquation);
6435 wined3d_mutex_unlock();
6437 return hr;
6440 static HRESULT WINAPI
6441 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6442 DWORD Index,
6443 D3DVALUE* PlaneEquation)
6445 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6448 static HRESULT WINAPI
6449 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6450 DWORD Index,
6451 D3DVALUE* PlaneEquation)
6453 HRESULT hr;
6454 WORD old_fpucw;
6456 old_fpucw = d3d_fpu_setup();
6457 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6458 set_fpu_control_word(old_fpucw);
6460 return hr;
6463 /*****************************************************************************
6464 * IDirect3DDevice7::GetClipPlane
6466 * Returns the clipping plane with a specific index
6468 * Params:
6469 * Index: The index of the desired plane
6470 * PlaneEquation: Address to store the plane equation to
6472 * Returns:
6473 * D3D_OK on success
6474 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6475 * See IWineD3DDevice::GetClipPlane for more details
6477 *****************************************************************************/
6478 static HRESULT
6479 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6480 DWORD Index,
6481 D3DVALUE* PlaneEquation)
6483 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6484 HRESULT hr;
6486 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6488 if(!PlaneEquation)
6489 return DDERR_INVALIDPARAMS;
6491 wined3d_mutex_lock();
6492 hr = wined3d_device_get_clip_plane(This->wined3d_device, Index, PlaneEquation);
6493 wined3d_mutex_unlock();
6495 return hr;
6498 static HRESULT WINAPI
6499 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6500 DWORD Index,
6501 D3DVALUE* PlaneEquation)
6503 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6506 static HRESULT WINAPI
6507 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6508 DWORD Index,
6509 D3DVALUE* PlaneEquation)
6511 HRESULT hr;
6512 WORD old_fpucw;
6514 old_fpucw = d3d_fpu_setup();
6515 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6516 set_fpu_control_word(old_fpucw);
6518 return hr;
6521 /*****************************************************************************
6522 * IDirect3DDevice7::GetInfo
6524 * Retrieves some information about the device. The DirectX sdk says that
6525 * this version returns S_FALSE for all retail builds of DirectX, that's what
6526 * this implementation does.
6528 * Params:
6529 * DevInfoID: Information type requested
6530 * DevInfoStruct: Pointer to a structure to store the info to
6531 * Size: Size of the structure
6533 * Returns:
6534 * S_FALSE, because it's a non-debug driver
6536 *****************************************************************************/
6537 static HRESULT WINAPI
6538 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6539 DWORD DevInfoID,
6540 void *DevInfoStruct,
6541 DWORD Size)
6543 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6544 iface, DevInfoID, DevInfoStruct, Size);
6546 if (TRACE_ON(ddraw))
6548 TRACE(" info requested : ");
6549 switch (DevInfoID)
6551 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6552 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6553 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6554 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6558 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6561 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6562 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6563 * are not duplicated.
6565 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6566 * has already been setup for optimal d3d operation.
6568 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6569 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6570 * by Sacrifice (game). */
6571 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6573 /*** IUnknown Methods ***/
6574 IDirect3DDeviceImpl_7_QueryInterface,
6575 IDirect3DDeviceImpl_7_AddRef,
6576 IDirect3DDeviceImpl_7_Release,
6577 /*** IDirect3DDevice7 ***/
6578 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6579 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6580 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6581 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6582 IDirect3DDeviceImpl_7_GetDirect3D,
6583 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6584 IDirect3DDeviceImpl_7_GetRenderTarget,
6585 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6586 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6587 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6588 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6589 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6590 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6591 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6592 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6593 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6594 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6595 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6596 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6597 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6598 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6599 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6600 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6601 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6602 IDirect3DDeviceImpl_7_SetClipStatus,
6603 IDirect3DDeviceImpl_7_GetClipStatus,
6604 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6605 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6606 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6607 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6608 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6609 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6610 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6611 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6612 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6613 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6614 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6615 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6616 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6617 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6618 IDirect3DDeviceImpl_7_Load_FPUSetup,
6619 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6620 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6621 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6622 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6623 IDirect3DDeviceImpl_7_GetInfo
6626 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6628 /*** IUnknown Methods ***/
6629 IDirect3DDeviceImpl_7_QueryInterface,
6630 IDirect3DDeviceImpl_7_AddRef,
6631 IDirect3DDeviceImpl_7_Release,
6632 /*** IDirect3DDevice7 ***/
6633 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6634 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6635 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6636 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6637 IDirect3DDeviceImpl_7_GetDirect3D,
6638 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6639 IDirect3DDeviceImpl_7_GetRenderTarget,
6640 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6641 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6642 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6643 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6644 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6645 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6646 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6647 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6648 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6649 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6650 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6651 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6652 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6653 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6654 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6655 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6656 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6657 IDirect3DDeviceImpl_7_SetClipStatus,
6658 IDirect3DDeviceImpl_7_GetClipStatus,
6659 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6660 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6661 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6662 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6663 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6664 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6665 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6666 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6667 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6668 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6669 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6670 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6671 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6672 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6673 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6674 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6675 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6676 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6677 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6678 IDirect3DDeviceImpl_7_GetInfo
6681 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6683 /*** IUnknown Methods ***/
6684 IDirect3DDeviceImpl_3_QueryInterface,
6685 IDirect3DDeviceImpl_3_AddRef,
6686 IDirect3DDeviceImpl_3_Release,
6687 /*** IDirect3DDevice3 ***/
6688 IDirect3DDeviceImpl_3_GetCaps,
6689 IDirect3DDeviceImpl_3_GetStats,
6690 IDirect3DDeviceImpl_3_AddViewport,
6691 IDirect3DDeviceImpl_3_DeleteViewport,
6692 IDirect3DDeviceImpl_3_NextViewport,
6693 IDirect3DDeviceImpl_3_EnumTextureFormats,
6694 IDirect3DDeviceImpl_3_BeginScene,
6695 IDirect3DDeviceImpl_3_EndScene,
6696 IDirect3DDeviceImpl_3_GetDirect3D,
6697 IDirect3DDeviceImpl_3_SetCurrentViewport,
6698 IDirect3DDeviceImpl_3_GetCurrentViewport,
6699 IDirect3DDeviceImpl_3_SetRenderTarget,
6700 IDirect3DDeviceImpl_3_GetRenderTarget,
6701 IDirect3DDeviceImpl_3_Begin,
6702 IDirect3DDeviceImpl_3_BeginIndexed,
6703 IDirect3DDeviceImpl_3_Vertex,
6704 IDirect3DDeviceImpl_3_Index,
6705 IDirect3DDeviceImpl_3_End,
6706 IDirect3DDeviceImpl_3_GetRenderState,
6707 IDirect3DDeviceImpl_3_SetRenderState,
6708 IDirect3DDeviceImpl_3_GetLightState,
6709 IDirect3DDeviceImpl_3_SetLightState,
6710 IDirect3DDeviceImpl_3_SetTransform,
6711 IDirect3DDeviceImpl_3_GetTransform,
6712 IDirect3DDeviceImpl_3_MultiplyTransform,
6713 IDirect3DDeviceImpl_3_DrawPrimitive,
6714 IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6715 IDirect3DDeviceImpl_3_SetClipStatus,
6716 IDirect3DDeviceImpl_3_GetClipStatus,
6717 IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6718 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6719 IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6720 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6721 IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6722 IDirect3DDeviceImpl_3_GetTexture,
6723 IDirect3DDeviceImpl_3_SetTexture,
6724 IDirect3DDeviceImpl_3_GetTextureStageState,
6725 IDirect3DDeviceImpl_3_SetTextureStageState,
6726 IDirect3DDeviceImpl_3_ValidateDevice
6729 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6731 /*** IUnknown Methods ***/
6732 IDirect3DDeviceImpl_2_QueryInterface,
6733 IDirect3DDeviceImpl_2_AddRef,
6734 IDirect3DDeviceImpl_2_Release,
6735 /*** IDirect3DDevice2 ***/
6736 IDirect3DDeviceImpl_2_GetCaps,
6737 IDirect3DDeviceImpl_2_SwapTextureHandles,
6738 IDirect3DDeviceImpl_2_GetStats,
6739 IDirect3DDeviceImpl_2_AddViewport,
6740 IDirect3DDeviceImpl_2_DeleteViewport,
6741 IDirect3DDeviceImpl_2_NextViewport,
6742 IDirect3DDeviceImpl_2_EnumTextureFormats,
6743 IDirect3DDeviceImpl_2_BeginScene,
6744 IDirect3DDeviceImpl_2_EndScene,
6745 IDirect3DDeviceImpl_2_GetDirect3D,
6746 IDirect3DDeviceImpl_2_SetCurrentViewport,
6747 IDirect3DDeviceImpl_2_GetCurrentViewport,
6748 IDirect3DDeviceImpl_2_SetRenderTarget,
6749 IDirect3DDeviceImpl_2_GetRenderTarget,
6750 IDirect3DDeviceImpl_2_Begin,
6751 IDirect3DDeviceImpl_2_BeginIndexed,
6752 IDirect3DDeviceImpl_2_Vertex,
6753 IDirect3DDeviceImpl_2_Index,
6754 IDirect3DDeviceImpl_2_End,
6755 IDirect3DDeviceImpl_2_GetRenderState,
6756 IDirect3DDeviceImpl_2_SetRenderState,
6757 IDirect3DDeviceImpl_2_GetLightState,
6758 IDirect3DDeviceImpl_2_SetLightState,
6759 IDirect3DDeviceImpl_2_SetTransform,
6760 IDirect3DDeviceImpl_2_GetTransform,
6761 IDirect3DDeviceImpl_2_MultiplyTransform,
6762 IDirect3DDeviceImpl_2_DrawPrimitive,
6763 IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6764 IDirect3DDeviceImpl_2_SetClipStatus,
6765 IDirect3DDeviceImpl_2_GetClipStatus
6768 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6770 /*** IUnknown Methods ***/
6771 IDirect3DDeviceImpl_1_QueryInterface,
6772 IDirect3DDeviceImpl_1_AddRef,
6773 IDirect3DDeviceImpl_1_Release,
6774 /*** IDirect3DDevice1 ***/
6775 IDirect3DDeviceImpl_1_Initialize,
6776 IDirect3DDeviceImpl_1_GetCaps,
6777 IDirect3DDeviceImpl_1_SwapTextureHandles,
6778 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6779 IDirect3DDeviceImpl_1_GetStats,
6780 IDirect3DDeviceImpl_1_Execute,
6781 IDirect3DDeviceImpl_1_AddViewport,
6782 IDirect3DDeviceImpl_1_DeleteViewport,
6783 IDirect3DDeviceImpl_1_NextViewport,
6784 IDirect3DDeviceImpl_1_Pick,
6785 IDirect3DDeviceImpl_1_GetPickRecords,
6786 IDirect3DDeviceImpl_1_EnumTextureFormats,
6787 IDirect3DDeviceImpl_1_CreateMatrix,
6788 IDirect3DDeviceImpl_1_SetMatrix,
6789 IDirect3DDeviceImpl_1_GetMatrix,
6790 IDirect3DDeviceImpl_1_DeleteMatrix,
6791 IDirect3DDeviceImpl_1_BeginScene,
6792 IDirect3DDeviceImpl_1_EndScene,
6793 IDirect3DDeviceImpl_1_GetDirect3D
6796 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6798 if (!iface) return NULL;
6799 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6800 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice7_iface);
6803 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6805 if (!iface) return NULL;
6806 assert(iface->lpVtbl == &d3d_device3_vtbl);
6807 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice3_iface);
6810 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6812 if (!iface) return NULL;
6813 assert(iface->lpVtbl == &d3d_device2_vtbl);
6814 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice2_iface);
6817 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6819 if (!iface) return NULL;
6820 assert(iface->lpVtbl == &d3d_device1_vtbl);
6821 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice_iface);
6824 /*****************************************************************************
6825 * IDirect3DDeviceImpl_UpdateDepthStencil
6827 * Checks the current render target for attached depth stencils and sets the
6828 * WineD3D depth stencil accordingly.
6830 * Returns:
6831 * The depth stencil state to set if creating the device
6833 *****************************************************************************/
6834 WINED3DZBUFFERTYPE
6835 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6837 IDirectDrawSurface7 *depthStencil = NULL;
6838 IDirectDrawSurfaceImpl *dsi;
6839 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6841 IDirectDrawSurface7_GetAttachedSurface(&This->target->IDirectDrawSurface7_iface, &depthcaps, &depthStencil);
6842 if(!depthStencil)
6844 TRACE("Setting wined3d depth stencil to NULL\n");
6845 wined3d_device_set_depth_stencil(This->wined3d_device, NULL);
6846 return WINED3DZB_FALSE;
6849 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6850 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
6851 wined3d_device_set_depth_stencil(This->wined3d_device, dsi->wined3d_surface);
6853 IDirectDrawSurface7_Release(depthStencil);
6854 return WINED3DZB_TRUE;
6857 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
6859 HRESULT hr;
6861 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6862 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6863 else
6864 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
6866 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6867 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6868 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6869 device->ref = 1;
6870 device->ddraw = ddraw;
6871 device->target = target;
6872 list_init(&device->viewport_list);
6874 if (!ddraw_handle_table_init(&device->handle_table, 64))
6876 ERR("Failed to initialize handle table.\n");
6877 return DDERR_OUTOFMEMORY;
6880 device->legacyTextureBlending = FALSE;
6882 /* Create an index buffer, it's needed for indexed drawing */
6883 hr = wined3d_buffer_create_ib(ddraw->wined3d_device, 0x40000 /* Length. Don't know how long it should be */,
6884 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, NULL,
6885 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
6886 if (FAILED(hr))
6888 ERR("Failed to create an index buffer, hr %#x.\n", hr);
6889 ddraw_handle_table_destroy(&device->handle_table);
6890 return hr;
6893 /* This is for convenience. */
6894 device->wined3d_device = ddraw->wined3d_device;
6895 wined3d_device_incref(ddraw->wined3d_device);
6897 /* Render to the back buffer */
6898 hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
6899 if (FAILED(hr))
6901 ERR("Failed to set render target, hr %#x.\n", hr);
6902 wined3d_buffer_decref(device->indexbuffer);
6903 ddraw_handle_table_destroy(&device->handle_table);
6904 return hr;
6907 /* FIXME: This is broken. The target AddRef() makes some sense, because
6908 * we store a pointer during initialization, but then that's also where
6909 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6910 /* AddRef the render target. Also AddRef the render target from ddraw,
6911 * because if it is released before the app releases the D3D device, the
6912 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6914 * In most cases, those surfaces are the same anyway, but this will simply
6915 * add another ref which is released when the device is destroyed. */
6916 IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
6917 IDirectDrawSurface7_AddRef(&ddraw->d3d_target->IDirectDrawSurface7_iface);
6919 ddraw->d3ddevice = device;
6921 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3DRS_ZENABLE,
6922 IDirect3DDeviceImpl_UpdateDepthStencil(device));
6924 return D3D_OK;