ddraw: Use unsafe_impl_from_IDirect3DDevice7 for application provided interfaces.
[wine/multimedia.git] / dlls / ddraw / device.c
blobe29ee151c9edb3d0b258a867f7fc08c0454d6c74
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 = (IDirect3DDeviceImpl *)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((IDirect3DDevice7 *)This, 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((IDirect3DDevice7 *)This, 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((IDirect3DDevice7 *)This, 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 = (IDirect3DDeviceImpl *)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((IDirect3DDevice7 *)This);
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((IDirect3DDevice7 *)This);
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((IDirect3DDevice7 *)This);
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 = (IDirect3DDeviceImpl *)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 EnterCriticalSection(&ddraw_cs);
298 /* There is no need to unset any resources here, wined3d will take
299 * care of that on Uninit3D(). */
301 /* Free the index buffer. */
302 wined3d_buffer_decref(This->indexbuffer);
304 /* Set the device up to render to the front buffer since the back
305 * buffer will vanish soon. */
306 wined3d_device_set_render_target(This->wined3d_device, 0,
307 This->ddraw->d3d_target->wined3d_surface, TRUE);
309 /* Release the WineD3DDevice. This won't destroy it. */
310 if (!wined3d_device_decref(This->wined3d_device))
311 ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This->wined3d_device);
313 /* The texture handles should be unset by now, but there might be some bits
314 * missing in our reference counting(needs test). Do a sanity check. */
315 for (i = 0; i < This->handle_table.entry_count; ++i)
317 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
319 switch (entry->type)
321 case DDRAW_HANDLE_FREE:
322 break;
324 case DDRAW_HANDLE_MATERIAL:
326 IDirect3DMaterialImpl *m = entry->object;
327 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
328 m->Handle = 0;
329 break;
332 case DDRAW_HANDLE_MATRIX:
334 /* No FIXME here because this might happen because of sloppy applications. */
335 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
336 IDirect3DDevice_DeleteMatrix(&This->IDirect3DDevice_iface, i + 1);
337 break;
340 case DDRAW_HANDLE_STATEBLOCK:
342 /* No FIXME here because this might happen because of sloppy applications. */
343 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
344 IDirect3DDevice7_DeleteStateBlock(iface, i + 1);
345 break;
348 case DDRAW_HANDLE_SURFACE:
350 IDirectDrawSurfaceImpl *surf = entry->object;
351 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
352 surf->Handle = 0;
353 break;
356 default:
357 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
358 break;
362 ddraw_handle_table_destroy(&This->handle_table);
364 TRACE("Releasing target %p %p\n", This->target, This->ddraw->d3d_target);
365 /* Release the render target and the WineD3D render target
366 * (See IDirect3D7::CreateDevice for more comments on this)
368 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
369 IDirectDrawSurface7_Release(&This->ddraw->d3d_target->IDirectDrawSurface7_iface);
370 TRACE("Target release done\n");
372 This->ddraw->d3ddevice = NULL;
374 /* Now free the structure */
375 HeapFree(GetProcessHeap(), 0, This);
376 LeaveCriticalSection(&ddraw_cs);
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((IDirect3DDevice7 *)This);
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((IDirect3DDevice7 *)This);
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((IDirect3DDevice7 *)This);
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 = (IDirect3DDeviceImpl *)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 EnterCriticalSection(&ddraw_cs);
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 LeaveCriticalSection(&ddraw_cs);
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 EnterCriticalSection(&ddraw_cs);
734 hr = d3d_execute_buffer_execute(buffer, This, Direct3DViewportImpl);
735 LeaveCriticalSection(&ddraw_cs);
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 EnterCriticalSection(&ddraw_cs);
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 LeaveCriticalSection(&ddraw_cs);
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 EnterCriticalSection(&ddraw_cs);
826 if (vp->active_device != This)
828 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
829 LeaveCriticalSection(&ddraw_cs);
830 return DDERR_INVALIDPARAMS;
833 vp->active_device = NULL;
834 list_remove(&vp->entry);
836 LeaveCriticalSection(&ddraw_cs);
837 return D3D_OK;
840 static HRESULT WINAPI IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
841 IDirect3DViewport2 *Direct3DViewport2)
843 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
844 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
846 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
848 return IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
851 static HRESULT WINAPI IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
852 IDirect3DViewport *Direct3DViewport)
854 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
855 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport(Direct3DViewport);
857 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
859 return IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
862 /*****************************************************************************
863 * IDirect3DDevice3::NextViewport
865 * Returns a viewport from the viewport list, depending on the
866 * passed viewport and the flags.
868 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
869 * are equal.
871 * Params:
872 * Viewport: Viewport to use for beginning the search
873 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
875 * Returns:
876 * D3D_OK on success
877 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
879 *****************************************************************************/
880 static HRESULT WINAPI
881 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
882 IDirect3DViewport3 *Viewport3,
883 IDirect3DViewport3 **lplpDirect3DViewport3,
884 DWORD Flags)
886 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
887 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(Viewport3);
888 IDirect3DViewportImpl *next;
889 struct list *entry;
891 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
892 iface, Viewport3, lplpDirect3DViewport3, Flags);
894 if(!vp)
896 *lplpDirect3DViewport3 = NULL;
897 return DDERR_INVALIDPARAMS;
901 EnterCriticalSection(&ddraw_cs);
902 switch (Flags)
904 case D3DNEXT_NEXT:
905 entry = list_next(&This->viewport_list, &vp->entry);
906 break;
908 case D3DNEXT_HEAD:
909 entry = list_head(&This->viewport_list);
910 break;
912 case D3DNEXT_TAIL:
913 entry = list_tail(&This->viewport_list);
914 break;
916 default:
917 WARN("Invalid flags %#x.\n", Flags);
918 *lplpDirect3DViewport3 = NULL;
919 LeaveCriticalSection(&ddraw_cs);
920 return DDERR_INVALIDPARAMS;
923 if (entry)
925 next = LIST_ENTRY(entry, IDirect3DViewportImpl, entry);
926 *lplpDirect3DViewport3 = &next->IDirect3DViewport3_iface;
928 else
929 *lplpDirect3DViewport3 = NULL;
931 LeaveCriticalSection(&ddraw_cs);
932 return D3D_OK;
935 static HRESULT WINAPI IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
936 IDirect3DViewport2 *Viewport2, IDirect3DViewport2 **lplpDirect3DViewport2, DWORD Flags)
938 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
939 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Viewport2);
940 IDirect3DViewport3 *res;
941 HRESULT hr;
943 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
944 iface, Viewport2, lplpDirect3DViewport2, Flags);
946 hr = IDirect3DDevice3_NextViewport(&This->IDirect3DDevice3_iface,
947 &vp->IDirect3DViewport3_iface, &res, Flags);
948 *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
949 return hr;
952 static HRESULT WINAPI IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
953 IDirect3DViewport *Viewport, IDirect3DViewport **lplpDirect3DViewport, DWORD Flags)
955 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
956 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport(Viewport);
957 IDirect3DViewport3 *res;
958 HRESULT hr;
960 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
961 iface, Viewport, lplpDirect3DViewport, Flags);
963 hr = IDirect3DDevice3_NextViewport(&This->IDirect3DDevice3_iface,
964 &vp->IDirect3DViewport3_iface, &res, Flags);
965 *lplpDirect3DViewport = (IDirect3DViewport *)res;
966 return hr;
969 /*****************************************************************************
970 * IDirect3DDevice::Pick
972 * Executes an execute buffer without performing rendering. Instead, a
973 * list of primitives that intersect with (x1,y1) of the passed rectangle
974 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
975 * this list.
977 * Version 1 only
979 * Params:
980 * ExecuteBuffer: Buffer to execute
981 * Viewport: Viewport to use for execution
982 * Flags: None are defined, according to the SDK
983 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
984 * x2 and y2 are ignored.
986 * Returns:
987 * D3D_OK because it's a stub
989 *****************************************************************************/
990 static HRESULT WINAPI
991 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
992 IDirect3DExecuteBuffer *ExecuteBuffer,
993 IDirect3DViewport *Viewport,
994 DWORD Flags,
995 D3DRECT *Rect)
997 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
998 iface, ExecuteBuffer, Viewport, Flags, wine_dbgstr_rect((RECT *)Rect));
1000 return D3D_OK;
1003 /*****************************************************************************
1004 * IDirect3DDevice::GetPickRecords
1006 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1008 * Version 1 only
1010 * Params:
1011 * Count: Pointer to a DWORD containing the numbers of pick records to
1012 * retrieve
1013 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1015 * Returns:
1016 * D3D_OK, because it's a stub
1018 *****************************************************************************/
1019 static HRESULT WINAPI
1020 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1021 DWORD *Count,
1022 D3DPICKRECORD *D3DPickRec)
1024 FIXME("iface %p, count %p, records %p stub!\n", iface, Count, D3DPickRec);
1026 return D3D_OK;
1029 /*****************************************************************************
1030 * IDirect3DDevice7::EnumTextureformats
1032 * Enumerates the supported texture formats. It has a list of all possible
1033 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1034 * WineD3D supports it. If so, then it is passed to the app.
1036 * This is for Version 7 and 3, older versions have a different
1037 * callback function and their own implementation
1039 * Params:
1040 * Callback: Callback to call for each enumerated format
1041 * Arg: Argument to pass to the callback
1043 * Returns:
1044 * D3D_OK on success
1045 * DDERR_INVALIDPARAMS if Callback == NULL
1047 *****************************************************************************/
1048 static HRESULT
1049 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1050 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1051 void *Arg)
1053 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1054 HRESULT hr;
1055 WINED3DDISPLAYMODE mode;
1056 unsigned int i;
1058 static const enum wined3d_format_id FormatList[] =
1060 /* 32 bit */
1061 WINED3DFMT_B8G8R8A8_UNORM,
1062 WINED3DFMT_B8G8R8X8_UNORM,
1063 /* 24 bit */
1064 WINED3DFMT_B8G8R8_UNORM,
1065 /* 16 Bit */
1066 WINED3DFMT_B5G5R5A1_UNORM,
1067 WINED3DFMT_B4G4R4A4_UNORM,
1068 WINED3DFMT_B5G6R5_UNORM,
1069 WINED3DFMT_B5G5R5X1_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 EnterCriticalSection(&ddraw_cs);
1096 memset(&mode, 0, sizeof(mode));
1097 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1098 if (FAILED(hr))
1100 LeaveCriticalSection(&ddraw_cs);
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, 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 LeaveCriticalSection(&ddraw_cs);
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, 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 LeaveCriticalSection(&ddraw_cs);
1147 return D3D_OK;
1151 TRACE("End of enumeration\n");
1152 LeaveCriticalSection(&ddraw_cs);
1153 return D3D_OK;
1156 static HRESULT WINAPI
1157 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1158 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1159 void *Arg)
1161 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1164 static HRESULT WINAPI
1165 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1166 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1167 void *Arg)
1169 HRESULT hr;
1170 WORD old_fpucw;
1172 old_fpucw = d3d_fpu_setup();
1173 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1174 set_fpu_control_word(old_fpucw);
1176 return hr;
1179 static HRESULT WINAPI IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1180 LPD3DENUMPIXELFORMATSCALLBACK Callback, void *Arg)
1182 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1184 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1186 return IDirect3DDevice7_EnumTextureFormats((IDirect3DDevice7 *)This, Callback, Arg);
1189 /*****************************************************************************
1190 * IDirect3DDevice2::EnumTextureformats
1192 * EnumTextureFormats for Version 1 and 2, see
1193 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1195 * This version has a different callback and does not enumerate FourCC
1196 * formats
1198 *****************************************************************************/
1199 static HRESULT WINAPI
1200 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1201 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1202 void *Arg)
1204 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1205 HRESULT hr;
1206 unsigned int i;
1207 WINED3DDISPLAYMODE mode;
1209 static const enum wined3d_format_id FormatList[] =
1211 /* 32 bit */
1212 WINED3DFMT_B8G8R8A8_UNORM,
1213 WINED3DFMT_B8G8R8X8_UNORM,
1214 /* 24 bit */
1215 WINED3DFMT_B8G8R8_UNORM,
1216 /* 16 Bit */
1217 WINED3DFMT_B5G5R5A1_UNORM,
1218 WINED3DFMT_B4G4R4A4_UNORM,
1219 WINED3DFMT_B5G6R5_UNORM,
1220 WINED3DFMT_B5G5R5X1_UNORM,
1221 /* 8 Bit */
1222 WINED3DFMT_B2G3R3_UNORM,
1223 WINED3DFMT_P8_UINT,
1224 /* FOURCC codes - Not in this version*/
1227 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1229 if(!Callback)
1230 return DDERR_INVALIDPARAMS;
1232 EnterCriticalSection(&ddraw_cs);
1234 memset(&mode, 0, sizeof(mode));
1235 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1236 if (FAILED(hr))
1238 LeaveCriticalSection(&ddraw_cs);
1239 WARN("Cannot get the current adapter format\n");
1240 return hr;
1243 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1245 hr = wined3d_check_device_format(This->ddraw->wineD3D, 0, WINED3DDEVTYPE_HAL,
1246 mode.Format, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1247 if (hr == D3D_OK)
1249 DDSURFACEDESC sdesc;
1251 memset(&sdesc, 0, sizeof(sdesc));
1252 sdesc.dwSize = sizeof(sdesc);
1253 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1254 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1255 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1256 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1258 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1259 hr = Callback(&sdesc, Arg);
1260 if(hr != DDENUMRET_OK)
1262 TRACE("Format enumeration cancelled by application\n");
1263 LeaveCriticalSection(&ddraw_cs);
1264 return D3D_OK;
1268 TRACE("End of enumeration\n");
1269 LeaveCriticalSection(&ddraw_cs);
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 EnterCriticalSection(&ddraw_cs);
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 LeaveCriticalSection(&ddraw_cs);
1326 return DDERR_OUTOFMEMORY;
1329 *D3DMatHandle = h + 1;
1331 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1333 LeaveCriticalSection(&ddraw_cs);
1334 return D3D_OK;
1337 /*****************************************************************************
1338 * IDirect3DDevice::SetMatrix
1340 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1341 * allocated for the handle
1343 * Version 1 only
1345 * Params:
1346 * D3DMatHandle: Handle to set the matrix to
1347 * D3DMatrix: Matrix to set
1349 * Returns:
1350 * D3D_OK on success
1351 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1352 * to set is NULL
1354 *****************************************************************************/
1355 static HRESULT WINAPI
1356 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1357 D3DMATRIXHANDLE D3DMatHandle,
1358 D3DMATRIX *D3DMatrix)
1360 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1361 D3DMATRIX *m;
1363 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1365 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1367 EnterCriticalSection(&ddraw_cs);
1369 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1370 if (!m)
1372 WARN("Invalid matrix handle.\n");
1373 LeaveCriticalSection(&ddraw_cs);
1374 return DDERR_INVALIDPARAMS;
1377 if (TRACE_ON(ddraw))
1378 dump_D3DMATRIX(D3DMatrix);
1380 *m = *D3DMatrix;
1382 if (D3DMatHandle == This->world)
1383 wined3d_device_set_transform(This->wined3d_device, WINED3DTS_WORLDMATRIX(0), (WINED3DMATRIX *)D3DMatrix);
1385 if (D3DMatHandle == This->view)
1386 wined3d_device_set_transform(This->wined3d_device, WINED3DTS_VIEW, (WINED3DMATRIX *)D3DMatrix);
1388 if (D3DMatHandle == This->proj)
1389 wined3d_device_set_transform(This->wined3d_device, WINED3DTS_PROJECTION, (WINED3DMATRIX *)D3DMatrix);
1391 LeaveCriticalSection(&ddraw_cs);
1392 return D3D_OK;
1395 /*****************************************************************************
1396 * IDirect3DDevice::GetMatrix
1398 * Returns the content of a D3DMATRIX handle
1400 * Version 1 only
1402 * Params:
1403 * D3DMatHandle: Matrix handle to read the content from
1404 * D3DMatrix: Address to store the content at
1406 * Returns:
1407 * D3D_OK on success
1408 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1410 *****************************************************************************/
1411 static HRESULT WINAPI
1412 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1413 D3DMATRIXHANDLE D3DMatHandle,
1414 D3DMATRIX *D3DMatrix)
1416 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1417 D3DMATRIX *m;
1419 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1421 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1423 EnterCriticalSection(&ddraw_cs);
1425 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1426 if (!m)
1428 WARN("Invalid matrix handle.\n");
1429 LeaveCriticalSection(&ddraw_cs);
1430 return DDERR_INVALIDPARAMS;
1433 *D3DMatrix = *m;
1435 LeaveCriticalSection(&ddraw_cs);
1436 return D3D_OK;
1439 /*****************************************************************************
1440 * IDirect3DDevice::DeleteMatrix
1442 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1444 * Version 1 only
1446 * Params:
1447 * D3DMatHandle: Handle to destroy
1449 * Returns:
1450 * D3D_OK on success
1451 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1453 *****************************************************************************/
1454 static HRESULT WINAPI
1455 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1456 D3DMATRIXHANDLE D3DMatHandle)
1458 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1459 D3DMATRIX *m;
1461 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1463 EnterCriticalSection(&ddraw_cs);
1465 m = ddraw_free_handle(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1466 if (!m)
1468 WARN("Invalid matrix handle.\n");
1469 LeaveCriticalSection(&ddraw_cs);
1470 return DDERR_INVALIDPARAMS;
1473 LeaveCriticalSection(&ddraw_cs);
1475 HeapFree(GetProcessHeap(), 0, m);
1477 return D3D_OK;
1480 /*****************************************************************************
1481 * IDirect3DDevice7::BeginScene
1483 * This method must be called before any rendering is performed.
1484 * IDirect3DDevice::EndScene has to be called after the scene is complete
1486 * Version 1, 2, 3 and 7
1488 * Returns:
1489 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1490 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1491 * started scene).
1493 *****************************************************************************/
1494 static HRESULT
1495 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1497 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1498 HRESULT hr;
1500 TRACE("iface %p.\n", iface);
1502 EnterCriticalSection(&ddraw_cs);
1503 hr = wined3d_device_begin_scene(This->wined3d_device);
1504 LeaveCriticalSection(&ddraw_cs);
1505 if(hr == WINED3D_OK) return D3D_OK;
1506 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1509 static HRESULT WINAPI
1510 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1512 return IDirect3DDeviceImpl_7_BeginScene(iface);
1515 static HRESULT WINAPI
1516 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1518 HRESULT hr;
1519 WORD old_fpucw;
1521 old_fpucw = d3d_fpu_setup();
1522 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1523 set_fpu_control_word(old_fpucw);
1525 return hr;
1528 static HRESULT WINAPI IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1530 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1531 TRACE("iface %p.\n", iface);
1533 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)This);
1536 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1538 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1539 TRACE("iface %p.\n", iface);
1541 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)This);
1544 static HRESULT WINAPI IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1546 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1547 TRACE("iface %p.\n", iface);
1549 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)This);
1552 /*****************************************************************************
1553 * IDirect3DDevice7::EndScene
1555 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1556 * This method must be called after rendering is finished.
1558 * Version 1, 2, 3 and 7
1560 * Returns:
1561 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1562 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1563 * that only if the scene was already ended.
1565 *****************************************************************************/
1566 static HRESULT
1567 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1569 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1570 HRESULT hr;
1572 TRACE("iface %p.\n", iface);
1574 EnterCriticalSection(&ddraw_cs);
1575 hr = wined3d_device_end_scene(This->wined3d_device);
1576 LeaveCriticalSection(&ddraw_cs);
1577 if(hr == WINED3D_OK) return D3D_OK;
1578 else return D3DERR_SCENE_NOT_IN_SCENE;
1581 static HRESULT WINAPI DECLSPEC_HOTPATCH
1582 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1584 return IDirect3DDeviceImpl_7_EndScene(iface);
1587 static HRESULT WINAPI DECLSPEC_HOTPATCH
1588 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1590 HRESULT hr;
1591 WORD old_fpucw;
1593 old_fpucw = d3d_fpu_setup();
1594 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1595 set_fpu_control_word(old_fpucw);
1597 return hr;
1600 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1602 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1603 TRACE("iface %p.\n", iface);
1605 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)This);
1608 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1610 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1611 TRACE("iface %p.\n", iface);
1613 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)This);
1616 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1618 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1619 TRACE("iface %p.\n", iface);
1621 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)This);
1624 /*****************************************************************************
1625 * IDirect3DDevice7::GetDirect3D
1627 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1628 * this device.
1630 * Params:
1631 * Direct3D7: Address to store the interface pointer at
1633 * Returns:
1634 * D3D_OK on success
1635 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1637 *****************************************************************************/
1638 static HRESULT WINAPI
1639 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1640 IDirect3D7 **Direct3D7)
1642 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1644 TRACE("iface %p, d3d %p.\n", iface, Direct3D7);
1646 if(!Direct3D7)
1647 return DDERR_INVALIDPARAMS;
1649 *Direct3D7 = &This->ddraw->IDirect3D7_iface;
1650 IDirect3D7_AddRef(*Direct3D7);
1652 TRACE(" returning interface %p\n", *Direct3D7);
1653 return D3D_OK;
1656 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1657 IDirect3D3 **Direct3D3)
1659 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1661 TRACE("iface %p, d3d %p.\n", iface, Direct3D3);
1663 if(!Direct3D3)
1664 return DDERR_INVALIDPARAMS;
1666 IDirect3D3_AddRef(&This->ddraw->IDirect3D3_iface);
1667 *Direct3D3 = &This->ddraw->IDirect3D3_iface;
1668 TRACE(" returning interface %p\n", *Direct3D3);
1669 return D3D_OK;
1672 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1673 IDirect3D2 **Direct3D2)
1675 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1677 TRACE("iface %p, d3d %p.\n", iface, Direct3D2);
1679 if(!Direct3D2)
1680 return DDERR_INVALIDPARAMS;
1682 IDirect3D2_AddRef(&This->ddraw->IDirect3D2_iface);
1683 *Direct3D2 = &This->ddraw->IDirect3D2_iface;
1684 TRACE(" returning interface %p\n", *Direct3D2);
1685 return D3D_OK;
1688 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1689 IDirect3D **Direct3D)
1691 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1693 TRACE("iface %p, d3d %p.\n", iface, Direct3D);
1695 if(!Direct3D)
1696 return DDERR_INVALIDPARAMS;
1698 IDirect3D_AddRef(&This->ddraw->IDirect3D_iface);
1699 *Direct3D = &This->ddraw->IDirect3D_iface;
1700 TRACE(" returning interface %p\n", *Direct3D);
1701 return D3D_OK;
1704 /*****************************************************************************
1705 * IDirect3DDevice3::SetCurrentViewport
1707 * Sets a Direct3DViewport as the current viewport.
1708 * For the thunks note that all viewport interface versions are equal
1710 * Params:
1711 * Direct3DViewport3: The viewport to set
1713 * Version 2 and 3
1715 * Returns:
1716 * D3D_OK on success
1717 * (Is a NULL viewport valid?)
1719 *****************************************************************************/
1720 static HRESULT WINAPI
1721 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1722 IDirect3DViewport3 *Direct3DViewport3)
1724 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1725 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(Direct3DViewport3);
1727 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1729 EnterCriticalSection(&ddraw_cs);
1730 /* Do nothing if the specified viewport is the same as the current one */
1731 if (This->current_viewport == vp )
1733 LeaveCriticalSection(&ddraw_cs);
1734 return D3D_OK;
1737 if (vp->active_device != This)
1739 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1740 LeaveCriticalSection(&ddraw_cs);
1741 return DDERR_INVALIDPARAMS;
1744 /* Release previous viewport and AddRef the new one */
1745 if (This->current_viewport)
1747 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1748 &This->current_viewport->IDirect3DViewport3_iface);
1749 IDirect3DViewport3_Release(&This->current_viewport->IDirect3DViewport3_iface);
1751 IDirect3DViewport3_AddRef(Direct3DViewport3);
1753 /* Set this viewport as the current viewport */
1754 This->current_viewport = vp;
1756 /* Activate this viewport */
1757 viewport_activate(This->current_viewport, FALSE);
1759 LeaveCriticalSection(&ddraw_cs);
1760 return D3D_OK;
1763 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1764 IDirect3DViewport2 *Direct3DViewport2)
1766 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1767 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
1769 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1771 return IDirect3DDevice3_SetCurrentViewport(&This->IDirect3DDevice3_iface,
1772 &vp->IDirect3DViewport3_iface);
1775 /*****************************************************************************
1776 * IDirect3DDevice3::GetCurrentViewport
1778 * Returns the currently active viewport.
1780 * Version 2 and 3
1782 * Params:
1783 * Direct3DViewport3: Address to return the interface pointer at
1785 * Returns:
1786 * D3D_OK on success
1787 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1789 *****************************************************************************/
1790 static HRESULT WINAPI
1791 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1792 IDirect3DViewport3 **Direct3DViewport3)
1794 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1796 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1798 if(!Direct3DViewport3)
1799 return DDERR_INVALIDPARAMS;
1801 EnterCriticalSection(&ddraw_cs);
1802 *Direct3DViewport3 = &This->current_viewport->IDirect3DViewport3_iface;
1804 /* AddRef the returned viewport */
1805 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1807 TRACE(" returning interface %p\n", *Direct3DViewport3);
1809 LeaveCriticalSection(&ddraw_cs);
1810 return D3D_OK;
1813 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1814 IDirect3DViewport2 **Direct3DViewport2)
1816 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1817 HRESULT hr;
1819 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1821 hr = IDirect3DDevice3_GetCurrentViewport(&This->IDirect3DDevice3_iface,
1822 (IDirect3DViewport3 **)Direct3DViewport2);
1823 if(hr != D3D_OK) return hr;
1824 return D3D_OK;
1827 /*****************************************************************************
1828 * IDirect3DDevice7::SetRenderTarget
1830 * Sets the render target for the Direct3DDevice.
1831 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1832 * IDirectDrawSurface3 == IDirectDrawSurface
1834 * Version 2, 3 and 7
1836 * Params:
1837 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1838 * render target
1839 * Flags: Some flags
1841 * Returns:
1842 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1844 *****************************************************************************/
1845 static HRESULT d3d_device_set_render_target(IDirect3DDeviceImpl *This, IDirectDrawSurfaceImpl *Target)
1847 HRESULT hr;
1849 EnterCriticalSection(&ddraw_cs);
1850 /* Flags: Not used */
1852 if(This->target == Target)
1854 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1855 LeaveCriticalSection(&ddraw_cs);
1856 return D3D_OK;
1858 This->target = Target;
1859 hr = wined3d_device_set_render_target(This->wined3d_device, 0,
1860 Target ? Target->wined3d_surface : NULL, FALSE);
1861 if(hr != D3D_OK)
1863 LeaveCriticalSection(&ddraw_cs);
1864 return hr;
1866 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1867 LeaveCriticalSection(&ddraw_cs);
1868 return D3D_OK;
1871 static HRESULT
1872 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1873 IDirectDrawSurface7 *NewTarget,
1874 DWORD Flags)
1876 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1877 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface7(NewTarget);
1879 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, Flags);
1880 /* Flags: Not used */
1882 IDirectDrawSurface7_AddRef(NewTarget);
1883 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
1884 return d3d_device_set_render_target(This, Target);
1887 static HRESULT WINAPI
1888 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1889 IDirectDrawSurface7 *NewTarget,
1890 DWORD Flags)
1892 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1895 static HRESULT WINAPI
1896 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1897 IDirectDrawSurface7 *NewTarget,
1898 DWORD Flags)
1900 HRESULT hr;
1901 WORD old_fpucw;
1903 old_fpucw = d3d_fpu_setup();
1904 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1905 set_fpu_control_word(old_fpucw);
1907 return hr;
1910 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
1911 IDirectDrawSurface4 *NewRenderTarget, DWORD Flags)
1913 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1914 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface4(NewRenderTarget);
1916 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1918 IDirectDrawSurface4_AddRef(NewRenderTarget);
1919 IDirectDrawSurface4_Release(&This->target->IDirectDrawSurface4_iface);
1920 return d3d_device_set_render_target(This, Target);
1923 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
1924 IDirectDrawSurface *NewRenderTarget, DWORD Flags)
1926 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1927 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface(NewRenderTarget);
1929 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1931 IDirectDrawSurface_AddRef(NewRenderTarget);
1932 IDirectDrawSurface_Release(&This->target->IDirectDrawSurface_iface);
1933 return d3d_device_set_render_target(This, Target);
1936 /*****************************************************************************
1937 * IDirect3DDevice7::GetRenderTarget
1939 * Returns the current render target.
1940 * This is handled locally, because the WineD3D render target's parent
1941 * is an IParent
1943 * Version 2, 3 and 7
1945 * Params:
1946 * RenderTarget: Address to store the surface interface pointer
1948 * Returns:
1949 * D3D_OK on success
1950 * DDERR_INVALIDPARAMS if RenderTarget == NULL
1952 *****************************************************************************/
1953 static HRESULT WINAPI
1954 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
1955 IDirectDrawSurface7 **RenderTarget)
1957 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1959 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1961 if(!RenderTarget)
1962 return DDERR_INVALIDPARAMS;
1964 EnterCriticalSection(&ddraw_cs);
1965 *RenderTarget = &This->target->IDirectDrawSurface7_iface;
1966 IDirectDrawSurface7_AddRef(*RenderTarget);
1968 LeaveCriticalSection(&ddraw_cs);
1969 return D3D_OK;
1972 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
1973 IDirectDrawSurface4 **RenderTarget)
1975 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1976 IDirectDrawSurface7 *RenderTarget7;
1977 IDirectDrawSurfaceImpl *RenderTargetImpl;
1978 HRESULT hr;
1980 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1982 if(!RenderTarget)
1983 return DDERR_INVALIDPARAMS;
1985 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, &RenderTarget7);
1986 if(hr != D3D_OK) return hr;
1987 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
1988 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface;
1989 IDirectDrawSurface4_AddRef(*RenderTarget);
1990 IDirectDrawSurface7_Release(RenderTarget7);
1991 return D3D_OK;
1994 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
1995 IDirectDrawSurface **RenderTarget)
1997 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1998 IDirectDrawSurface7 *RenderTarget7;
1999 IDirectDrawSurfaceImpl *RenderTargetImpl;
2000 HRESULT hr;
2002 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2004 if(!RenderTarget)
2005 return DDERR_INVALIDPARAMS;
2007 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, &RenderTarget7);
2008 if(hr != D3D_OK) return hr;
2009 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2010 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
2011 IDirectDrawSurface_AddRef(*RenderTarget);
2012 IDirectDrawSurface7_Release(RenderTarget7);
2013 return D3D_OK;
2016 /*****************************************************************************
2017 * IDirect3DDevice3::Begin
2019 * Begins a description block of vertices. This is similar to glBegin()
2020 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2021 * described with IDirect3DDevice::Vertex are drawn.
2023 * Version 2 and 3
2025 * Params:
2026 * PrimitiveType: The type of primitives to draw
2027 * VertexTypeDesc: A flexible vertex format description of the vertices
2028 * Flags: Some flags..
2030 * Returns:
2031 * D3D_OK on success
2033 *****************************************************************************/
2034 static HRESULT WINAPI
2035 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2036 D3DPRIMITIVETYPE PrimitiveType,
2037 DWORD VertexTypeDesc,
2038 DWORD Flags)
2040 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2042 TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
2043 iface, PrimitiveType, VertexTypeDesc, Flags);
2045 EnterCriticalSection(&ddraw_cs);
2046 This->primitive_type = PrimitiveType;
2047 This->vertex_type = VertexTypeDesc;
2048 This->render_flags = Flags;
2049 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2050 This->nb_vertices = 0;
2051 LeaveCriticalSection(&ddraw_cs);
2053 return D3D_OK;
2056 static HRESULT WINAPI IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface, D3DPRIMITIVETYPE d3dpt,
2057 D3DVERTEXTYPE dwVertexTypeDesc, DWORD dwFlags)
2059 DWORD FVF;
2060 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2062 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2063 iface, d3dpt, dwVertexTypeDesc, dwFlags);
2065 switch(dwVertexTypeDesc)
2067 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2068 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2069 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2070 default:
2071 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2072 return DDERR_INVALIDPARAMS; /* Should never happen */
2075 return IDirect3DDevice3_Begin(&This->IDirect3DDevice3_iface, d3dpt, FVF, dwFlags);
2078 /*****************************************************************************
2079 * IDirect3DDevice3::BeginIndexed
2081 * Draws primitives based on vertices in a vertex array which are specified
2082 * by indices.
2084 * Version 2 and 3
2086 * Params:
2087 * PrimitiveType: Primitive type to draw
2088 * VertexType: A FVF description of the vertex format
2089 * Vertices: pointer to an array containing the vertices
2090 * NumVertices: The number of vertices in the vertex array
2091 * Flags: Some flags ...
2093 * Returns:
2094 * D3D_OK, because it's a stub
2096 *****************************************************************************/
2097 static HRESULT WINAPI
2098 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2099 D3DPRIMITIVETYPE PrimitiveType,
2100 DWORD VertexType,
2101 void *Vertices,
2102 DWORD NumVertices,
2103 DWORD Flags)
2105 FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2106 iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2108 return D3D_OK;
2112 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2113 D3DPRIMITIVETYPE d3dptPrimitiveType, D3DVERTEXTYPE d3dvtVertexType,
2114 void *lpvVertices, DWORD dwNumVertices, DWORD dwFlags)
2116 DWORD FVF;
2117 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2119 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2120 iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2122 switch(d3dvtVertexType)
2124 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2125 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2126 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2127 default:
2128 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2129 return DDERR_INVALIDPARAMS; /* Should never happen */
2132 return IDirect3DDevice3_BeginIndexed(&This->IDirect3DDevice3_iface,
2133 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2136 /*****************************************************************************
2137 * IDirect3DDevice3::Vertex
2139 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2140 * drawn vertices in a vertex buffer. If the buffer is too small, its
2141 * size is increased.
2143 * Version 2 and 3
2145 * Params:
2146 * Vertex: Pointer to the vertex
2148 * Returns:
2149 * D3D_OK, on success
2150 * DDERR_INVALIDPARAMS if Vertex is NULL
2152 *****************************************************************************/
2153 static HRESULT WINAPI
2154 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2155 void *Vertex)
2157 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2159 TRACE("iface %p, vertex %p.\n", iface, Vertex);
2161 if(!Vertex)
2162 return DDERR_INVALIDPARAMS;
2164 EnterCriticalSection(&ddraw_cs);
2165 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2167 BYTE *old_buffer;
2168 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2169 old_buffer = This->vertex_buffer;
2170 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2171 if (old_buffer)
2173 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2174 HeapFree(GetProcessHeap(), 0, old_buffer);
2178 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2180 LeaveCriticalSection(&ddraw_cs);
2181 return D3D_OK;
2184 static HRESULT WINAPI IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface, void *lpVertexType)
2186 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2188 TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
2190 return IDirect3DDevice3_Vertex(&This->IDirect3DDevice3_iface, lpVertexType);
2193 /*****************************************************************************
2194 * IDirect3DDevice3::Index
2196 * Specifies an index to a vertex to be drawn. The vertex array has to
2197 * be specified with BeginIndexed first.
2199 * Parameters:
2200 * VertexIndex: The index of the vertex to draw
2202 * Returns:
2203 * D3D_OK because it's a stub
2205 *****************************************************************************/
2206 static HRESULT WINAPI
2207 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2208 WORD VertexIndex)
2210 FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
2212 return D3D_OK;
2215 static HRESULT WINAPI IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface, WORD wVertexIndex)
2217 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2219 TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
2221 return IDirect3DDevice3_Index(&This->IDirect3DDevice3_iface, wVertexIndex);
2224 /*****************************************************************************
2225 * IDirect3DDevice3::End
2227 * Ends a draw begun with IDirect3DDevice3::Begin or
2228 * IDirect3DDevice::BeginIndexed. The vertices specified with
2229 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2230 * the IDirect3DDevice7::DrawPrimitive method. So far only
2231 * non-indexed mode is supported
2233 * Version 2 and 3
2235 * Params:
2236 * Flags: Some flags, as usual. Don't know which are defined
2238 * Returns:
2239 * The return value of IDirect3DDevice7::DrawPrimitive
2241 *****************************************************************************/
2242 static HRESULT WINAPI
2243 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2244 DWORD Flags)
2246 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2248 TRACE("iface %p, flags %#x.\n", iface, Flags);
2250 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This, This->primitive_type,
2251 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2254 static HRESULT WINAPI IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface, DWORD dwFlags)
2256 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2258 TRACE("iface %p, flags %#x.\n", iface, dwFlags);
2260 return IDirect3DDevice3_End(&This->IDirect3DDevice3_iface, dwFlags);
2263 /*****************************************************************************
2264 * IDirect3DDevice7::GetRenderState
2266 * Returns the value of a render state. The possible render states are
2267 * defined in include/d3dtypes.h
2269 * Version 2, 3 and 7
2271 * Params:
2272 * RenderStateType: Render state to return the current setting of
2273 * Value: Address to store the value at
2275 * Returns:
2276 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2277 * DDERR_INVALIDPARAMS if Value == NULL
2279 *****************************************************************************/
2280 static HRESULT IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2281 D3DRENDERSTATETYPE RenderStateType, DWORD *Value)
2283 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2284 HRESULT hr;
2286 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2288 if(!Value)
2289 return DDERR_INVALIDPARAMS;
2291 EnterCriticalSection(&ddraw_cs);
2292 switch(RenderStateType)
2294 case D3DRENDERSTATE_TEXTUREMAG:
2296 WINED3DTEXTUREFILTERTYPE tex_mag;
2298 hr = wined3d_device_get_sampler_state(This->wined3d_device, 0, WINED3DSAMP_MAGFILTER, &tex_mag);
2300 switch (tex_mag)
2302 case WINED3DTEXF_POINT:
2303 *Value = D3DFILTER_NEAREST;
2304 break;
2305 case WINED3DTEXF_LINEAR:
2306 *Value = D3DFILTER_LINEAR;
2307 break;
2308 default:
2309 ERR("Unhandled texture mag %d !\n",tex_mag);
2310 *Value = 0;
2312 break;
2315 case D3DRENDERSTATE_TEXTUREMIN:
2317 WINED3DTEXTUREFILTERTYPE tex_min;
2318 WINED3DTEXTUREFILTERTYPE tex_mip;
2320 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2321 0, WINED3DSAMP_MINFILTER, &tex_min);
2322 if (FAILED(hr))
2324 LeaveCriticalSection(&ddraw_cs);
2325 return hr;
2327 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2328 0, WINED3DSAMP_MIPFILTER, &tex_mip);
2330 switch (tex_min)
2332 case WINED3DTEXF_POINT:
2333 switch (tex_mip)
2335 case WINED3DTEXF_NONE:
2336 *Value = D3DFILTER_NEAREST;
2337 break;
2338 case WINED3DTEXF_POINT:
2339 *Value = D3DFILTER_MIPNEAREST;
2340 break;
2341 case WINED3DTEXF_LINEAR:
2342 *Value = D3DFILTER_LINEARMIPNEAREST;
2343 break;
2344 default:
2345 ERR("Unhandled mip filter %#x.\n", tex_mip);
2346 *Value = D3DFILTER_NEAREST;
2347 break;
2349 break;
2350 case WINED3DTEXF_LINEAR:
2351 switch (tex_mip)
2353 case WINED3DTEXF_NONE:
2354 *Value = D3DFILTER_LINEAR;
2355 break;
2356 case WINED3DTEXF_POINT:
2357 *Value = D3DFILTER_MIPLINEAR;
2358 break;
2359 case WINED3DTEXF_LINEAR:
2360 *Value = D3DFILTER_LINEARMIPLINEAR;
2361 break;
2362 default:
2363 ERR("Unhandled mip filter %#x.\n", tex_mip);
2364 *Value = D3DFILTER_LINEAR;
2365 break;
2367 break;
2368 default:
2369 ERR("Unhandled texture min filter %#x.\n",tex_min);
2370 *Value = D3DFILTER_NEAREST;
2371 break;
2373 break;
2376 case D3DRENDERSTATE_TEXTUREADDRESS:
2377 case D3DRENDERSTATE_TEXTUREADDRESSU:
2378 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2379 0, WINED3DSAMP_ADDRESSU, Value);
2380 break;
2381 case D3DRENDERSTATE_TEXTUREADDRESSV:
2382 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2383 0, WINED3DSAMP_ADDRESSV, Value);
2384 break;
2386 case D3DRENDERSTATE_BORDERCOLOR:
2387 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2388 hr = E_NOTIMPL;
2389 break;
2391 case D3DRENDERSTATE_TEXTUREHANDLE:
2392 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2393 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2394 hr = DDERR_INVALIDPARAMS;
2395 break;
2397 case D3DRENDERSTATE_ZBIAS:
2398 hr = wined3d_device_get_render_state(This->wined3d_device, WINED3DRS_DEPTHBIAS, Value);
2399 break;
2401 default:
2402 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2403 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2405 FIXME("Unhandled stipple pattern render state (%#x).\n",
2406 RenderStateType);
2407 hr = E_NOTIMPL;
2408 break;
2410 hr = wined3d_device_get_render_state(This->wined3d_device, RenderStateType, Value);
2412 LeaveCriticalSection(&ddraw_cs);
2413 return hr;
2416 static HRESULT WINAPI
2417 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2418 D3DRENDERSTATETYPE RenderStateType,
2419 DWORD *Value)
2421 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2424 static HRESULT WINAPI
2425 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2426 D3DRENDERSTATETYPE RenderStateType,
2427 DWORD *Value)
2429 HRESULT hr;
2430 WORD old_fpucw;
2432 old_fpucw = d3d_fpu_setup();
2433 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2434 set_fpu_control_word(old_fpucw);
2436 return hr;
2439 static HRESULT WINAPI
2440 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2441 D3DRENDERSTATETYPE dwRenderStateType,
2442 DWORD *lpdwRenderState)
2444 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2445 HRESULT hr;
2447 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2449 switch(dwRenderStateType)
2451 case D3DRENDERSTATE_TEXTUREHANDLE:
2453 /* This state is wrapped to SetTexture in SetRenderState, so
2454 * it has to be wrapped to GetTexture here. */
2455 struct wined3d_texture *tex = NULL;
2456 *lpdwRenderState = 0;
2458 EnterCriticalSection(&ddraw_cs);
2460 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2461 if (SUCCEEDED(hr) && tex)
2463 /* The parent of the texture is the IDirectDrawSurface7
2464 * interface of the ddraw surface. */
2465 IDirectDrawSurfaceImpl *parent = wined3d_texture_get_parent(tex);
2466 if (parent) *lpdwRenderState = parent->Handle;
2467 wined3d_texture_decref(tex);
2470 LeaveCriticalSection(&ddraw_cs);
2472 return hr;
2475 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2477 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2478 the mapping to get the value. */
2479 DWORD colorop, colorarg1, colorarg2;
2480 DWORD alphaop, alphaarg1, alphaarg2;
2482 EnterCriticalSection(&ddraw_cs);
2484 This->legacyTextureBlending = TRUE;
2486 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLOROP, &colorop);
2487 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLORARG1, &colorarg1);
2488 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLORARG2, &colorarg2);
2489 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, &alphaop);
2490 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2491 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2493 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2494 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2496 *lpdwRenderState = D3DTBLEND_DECAL;
2498 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2499 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2501 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2503 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2504 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2506 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2508 else
2510 struct wined3d_texture *tex = NULL;
2511 HRESULT hr;
2512 BOOL tex_alpha = FALSE;
2513 DDPIXELFORMAT ddfmt;
2515 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2517 if(hr == WINED3D_OK && tex)
2519 struct wined3d_resource *sub_resource;
2521 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2523 struct wined3d_resource_desc desc;
2525 wined3d_resource_get_desc(sub_resource, &desc);
2526 ddfmt.dwSize = sizeof(ddfmt);
2527 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2528 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2531 wined3d_texture_decref(tex);
2534 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2535 alphaop == (tex_alpha ? WINED3DTOP_SELECTARG1 : WINED3DTOP_SELECTARG2) &&
2536 alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2538 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2541 *lpdwRenderState = D3DTBLEND_MODULATE;
2544 LeaveCriticalSection(&ddraw_cs);
2546 return D3D_OK;
2549 default:
2550 return IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, dwRenderStateType, lpdwRenderState);
2554 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2555 D3DRENDERSTATETYPE dwRenderStateType, DWORD *lpdwRenderState)
2557 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2559 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2561 return IDirect3DDevice3_GetRenderState(&This->IDirect3DDevice3_iface,
2562 dwRenderStateType, lpdwRenderState);
2565 /*****************************************************************************
2566 * IDirect3DDevice7::SetRenderState
2568 * Sets a render state. The possible render states are defined in
2569 * include/d3dtypes.h
2571 * Version 2, 3 and 7
2573 * Params:
2574 * RenderStateType: State to set
2575 * Value: Value to assign to that state
2577 * Returns:
2578 * D3D_OK on success,
2579 * for details see IWineD3DDevice::SetRenderState
2581 *****************************************************************************/
2582 static HRESULT
2583 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2584 D3DRENDERSTATETYPE RenderStateType,
2585 DWORD Value)
2587 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2588 HRESULT hr;
2590 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2592 EnterCriticalSection(&ddraw_cs);
2593 /* Some render states need special care */
2594 switch(RenderStateType)
2597 * The ddraw texture filter mapping works like this:
2598 * D3DFILTER_NEAREST Point min/mag, no mip
2599 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2600 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2602 * D3DFILTER_LINEAR Linear min/mag, no mip
2603 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2604 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2606 * This is the opposite of the GL naming convention,
2607 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2609 case D3DRENDERSTATE_TEXTUREMAG:
2611 WINED3DTEXTUREFILTERTYPE tex_mag;
2613 switch (Value)
2615 case D3DFILTER_NEAREST:
2616 case D3DFILTER_MIPNEAREST:
2617 case D3DFILTER_LINEARMIPNEAREST:
2618 tex_mag = WINED3DTEXF_POINT;
2619 break;
2620 case D3DFILTER_LINEAR:
2621 case D3DFILTER_MIPLINEAR:
2622 case D3DFILTER_LINEARMIPLINEAR:
2623 tex_mag = WINED3DTEXF_LINEAR;
2624 break;
2625 default:
2626 tex_mag = WINED3DTEXF_POINT;
2627 ERR("Unhandled texture mag %d !\n",Value);
2628 break;
2631 hr = wined3d_device_set_sampler_state(This->wined3d_device, 0, WINED3DSAMP_MAGFILTER, tex_mag);
2632 break;
2635 case D3DRENDERSTATE_TEXTUREMIN:
2637 WINED3DTEXTUREFILTERTYPE tex_min;
2638 WINED3DTEXTUREFILTERTYPE tex_mip;
2640 switch ((D3DTEXTUREFILTER) Value)
2642 case D3DFILTER_NEAREST:
2643 tex_min = WINED3DTEXF_POINT;
2644 tex_mip = WINED3DTEXF_NONE;
2645 break;
2646 case D3DFILTER_LINEAR:
2647 tex_min = WINED3DTEXF_LINEAR;
2648 tex_mip = WINED3DTEXF_NONE;
2649 break;
2650 case D3DFILTER_MIPNEAREST:
2651 tex_min = WINED3DTEXF_POINT;
2652 tex_mip = WINED3DTEXF_POINT;
2653 break;
2654 case D3DFILTER_MIPLINEAR:
2655 tex_min = WINED3DTEXF_LINEAR;
2656 tex_mip = WINED3DTEXF_POINT;
2657 break;
2658 case D3DFILTER_LINEARMIPNEAREST:
2659 tex_min = WINED3DTEXF_POINT;
2660 tex_mip = WINED3DTEXF_LINEAR;
2661 break;
2662 case D3DFILTER_LINEARMIPLINEAR:
2663 tex_min = WINED3DTEXF_LINEAR;
2664 tex_mip = WINED3DTEXF_LINEAR;
2665 break;
2667 default:
2668 ERR("Unhandled texture min %d !\n",Value);
2669 tex_min = WINED3DTEXF_POINT;
2670 tex_mip = WINED3DTEXF_NONE;
2671 break;
2674 wined3d_device_set_sampler_state(This->wined3d_device,
2675 0, WINED3DSAMP_MIPFILTER, tex_mip);
2676 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2677 0, WINED3DSAMP_MINFILTER, tex_min);
2678 break;
2681 case D3DRENDERSTATE_TEXTUREADDRESS:
2682 wined3d_device_set_sampler_state(This->wined3d_device,
2683 0, WINED3DSAMP_ADDRESSV, Value);
2684 /* Drop through */
2685 case D3DRENDERSTATE_TEXTUREADDRESSU:
2686 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2687 0, WINED3DSAMP_ADDRESSU, Value);
2688 break;
2689 case D3DRENDERSTATE_TEXTUREADDRESSV:
2690 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2691 0, WINED3DSAMP_ADDRESSV, Value);
2692 break;
2694 case D3DRENDERSTATE_BORDERCOLOR:
2695 /* This should probably just forward to the corresponding sampler
2696 * state. Needs tests. */
2697 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2698 hr = E_NOTIMPL;
2699 break;
2701 case D3DRENDERSTATE_TEXTUREHANDLE:
2702 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2703 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2704 hr = DDERR_INVALIDPARAMS;
2705 break;
2707 case D3DRENDERSTATE_ZBIAS:
2708 hr = wined3d_device_set_render_state(This->wined3d_device, WINED3DRS_DEPTHBIAS, Value);
2709 break;
2711 default:
2712 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2713 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2715 FIXME("Unhandled stipple pattern render state (%#x).\n",
2716 RenderStateType);
2717 hr = E_NOTIMPL;
2718 break;
2721 hr = wined3d_device_set_render_state(This->wined3d_device, RenderStateType, Value);
2722 break;
2724 LeaveCriticalSection(&ddraw_cs);
2725 return hr;
2728 static HRESULT WINAPI
2729 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2730 D3DRENDERSTATETYPE RenderStateType,
2731 DWORD Value)
2733 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2736 static HRESULT WINAPI
2737 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2738 D3DRENDERSTATETYPE RenderStateType,
2739 DWORD Value)
2741 HRESULT hr;
2742 WORD old_fpucw;
2744 old_fpucw = d3d_fpu_setup();
2745 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2746 set_fpu_control_word(old_fpucw);
2748 return hr;
2751 static HRESULT WINAPI
2752 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2753 D3DRENDERSTATETYPE RenderStateType,
2754 DWORD Value)
2756 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2757 for this state can be directly mapped to texture stage colorop and alphaop, but
2758 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2759 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2760 alphaarg when needed.
2762 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2764 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2765 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2766 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2767 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2768 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2769 in device - TRUE if the app is using TEXTUREMAPBLEND.
2771 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2772 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2773 unless some broken game will be found that cares. */
2775 HRESULT hr;
2776 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2778 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2780 EnterCriticalSection(&ddraw_cs);
2782 switch(RenderStateType)
2784 case D3DRENDERSTATE_TEXTUREHANDLE:
2786 IDirectDrawSurfaceImpl *surf;
2788 if(Value == 0)
2790 hr = wined3d_device_set_texture(This->wined3d_device, 0, NULL);
2791 break;
2794 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2795 if (!surf)
2797 WARN("Invalid texture handle.\n");
2798 hr = DDERR_INVALIDPARAMS;
2799 break;
2802 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2803 break;
2806 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2808 This->legacyTextureBlending = TRUE;
2810 switch ( (D3DTEXTUREBLEND) Value)
2812 case D3DTBLEND_MODULATE:
2814 struct wined3d_texture *tex = NULL;
2815 BOOL tex_alpha = FALSE;
2816 DDPIXELFORMAT ddfmt;
2818 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2820 if(hr == WINED3D_OK && tex)
2822 struct wined3d_resource *sub_resource;
2824 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2826 struct wined3d_resource_desc desc;
2828 wined3d_resource_get_desc(sub_resource, &desc);
2829 ddfmt.dwSize = sizeof(ddfmt);
2830 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2831 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2834 wined3d_texture_decref(tex);
2837 if (tex_alpha)
2838 wined3d_device_set_texture_stage_state(This->wined3d_device,
2839 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2840 else
2841 wined3d_device_set_texture_stage_state(This->wined3d_device,
2842 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2843 wined3d_device_set_texture_stage_state(This->wined3d_device,
2844 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2845 wined3d_device_set_texture_stage_state(This->wined3d_device,
2846 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2847 wined3d_device_set_texture_stage_state(This->wined3d_device,
2848 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2849 wined3d_device_set_texture_stage_state(This->wined3d_device,
2850 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2851 wined3d_device_set_texture_stage_state(This->wined3d_device,
2852 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2853 break;
2856 case D3DTBLEND_ADD:
2857 wined3d_device_set_texture_stage_state(This->wined3d_device,
2858 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2859 wined3d_device_set_texture_stage_state(This->wined3d_device,
2860 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2861 wined3d_device_set_texture_stage_state(This->wined3d_device,
2862 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2863 wined3d_device_set_texture_stage_state(This->wined3d_device,
2864 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2865 wined3d_device_set_texture_stage_state(This->wined3d_device,
2866 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2867 break;
2869 case D3DTBLEND_MODULATEALPHA:
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_ALPHAARG1, WINED3DTA_TEXTURE);
2874 wined3d_device_set_texture_stage_state(This->wined3d_device,
2875 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2876 wined3d_device_set_texture_stage_state(This->wined3d_device,
2877 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2878 wined3d_device_set_texture_stage_state(This->wined3d_device,
2879 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2880 wined3d_device_set_texture_stage_state(This->wined3d_device,
2881 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2882 break;
2884 case D3DTBLEND_COPY:
2885 case D3DTBLEND_DECAL:
2886 wined3d_device_set_texture_stage_state(This->wined3d_device,
2887 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2888 wined3d_device_set_texture_stage_state(This->wined3d_device,
2889 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2890 wined3d_device_set_texture_stage_state(This->wined3d_device,
2891 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2892 wined3d_device_set_texture_stage_state(This->wined3d_device,
2893 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2894 break;
2896 case D3DTBLEND_DECALALPHA:
2897 wined3d_device_set_texture_stage_state(This->wined3d_device,
2898 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2899 wined3d_device_set_texture_stage_state(This->wined3d_device,
2900 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2901 wined3d_device_set_texture_stage_state(This->wined3d_device,
2902 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2903 wined3d_device_set_texture_stage_state(This->wined3d_device,
2904 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2905 wined3d_device_set_texture_stage_state(This->wined3d_device,
2906 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2907 break;
2909 default:
2910 ERR("Unhandled texture environment %d !\n",Value);
2913 hr = D3D_OK;
2914 break;
2917 default:
2918 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, RenderStateType, Value);
2919 break;
2922 LeaveCriticalSection(&ddraw_cs);
2924 return hr;
2927 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2928 D3DRENDERSTATETYPE RenderStateType, DWORD Value)
2930 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2932 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2934 return IDirect3DDevice3_SetRenderState(&This->IDirect3DDevice3_iface, RenderStateType, Value);
2937 /*****************************************************************************
2938 * Direct3DDevice3::SetLightState
2940 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2941 * light states are forwarded to Direct3DDevice7 render states
2943 * Version 2 and 3
2945 * Params:
2946 * LightStateType: The light state to change
2947 * Value: The value to assign to that light state
2949 * Returns:
2950 * D3D_OK on success
2951 * DDERR_INVALIDPARAMS if the parameters were incorrect
2952 * Also check IDirect3DDevice7::SetRenderState
2954 *****************************************************************************/
2955 static HRESULT WINAPI
2956 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
2957 D3DLIGHTSTATETYPE LightStateType,
2958 DWORD Value)
2960 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2961 HRESULT hr;
2963 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
2965 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2967 TRACE("Unexpected Light State Type\n");
2968 return DDERR_INVALIDPARAMS;
2971 EnterCriticalSection(&ddraw_cs);
2972 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
2974 IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
2975 if (!m)
2977 WARN("Invalid material handle.\n");
2978 LeaveCriticalSection(&ddraw_cs);
2979 return DDERR_INVALIDPARAMS;
2982 TRACE(" activating material %p.\n", m);
2983 material_activate(m);
2985 This->material = Value;
2987 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
2989 switch (Value)
2991 case D3DCOLOR_MONO:
2992 ERR("DDCOLOR_MONO should not happen!\n");
2993 break;
2994 case D3DCOLOR_RGB:
2995 /* We are already in this mode */
2996 TRACE("Setting color model to RGB (no-op).\n");
2997 break;
2998 default:
2999 ERR("Unknown color model!\n");
3000 LeaveCriticalSection(&ddraw_cs);
3001 return DDERR_INVALIDPARAMS;
3004 else
3006 D3DRENDERSTATETYPE rs;
3007 switch (LightStateType)
3009 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3010 rs = D3DRENDERSTATE_AMBIENT;
3011 break;
3012 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3013 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3014 break;
3015 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3016 rs = D3DRENDERSTATE_FOGSTART;
3017 break;
3018 case D3DLIGHTSTATE_FOGEND: /* 6 */
3019 rs = D3DRENDERSTATE_FOGEND;
3020 break;
3021 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3022 rs = D3DRENDERSTATE_FOGDENSITY;
3023 break;
3024 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3025 rs = D3DRENDERSTATE_COLORVERTEX;
3026 break;
3027 default:
3028 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3029 LeaveCriticalSection(&ddraw_cs);
3030 return DDERR_INVALIDPARAMS;
3033 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, rs, Value);
3034 LeaveCriticalSection(&ddraw_cs);
3035 return hr;
3038 LeaveCriticalSection(&ddraw_cs);
3039 return D3D_OK;
3042 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3043 D3DLIGHTSTATETYPE LightStateType, DWORD Value)
3045 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3047 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3049 return IDirect3DDevice3_SetLightState(&This->IDirect3DDevice3_iface, LightStateType, Value);
3052 /*****************************************************************************
3053 * IDirect3DDevice3::GetLightState
3055 * Returns the current setting of a light state. The state is read from
3056 * the Direct3DDevice7 render state.
3058 * Version 2 and 3
3060 * Params:
3061 * LightStateType: The light state to return
3062 * Value: The address to store the light state setting at
3064 * Returns:
3065 * D3D_OK on success
3066 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3067 * Also see IDirect3DDevice7::GetRenderState
3069 *****************************************************************************/
3070 static HRESULT WINAPI
3071 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3072 D3DLIGHTSTATETYPE LightStateType,
3073 DWORD *Value)
3075 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3076 HRESULT hr;
3078 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3080 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3082 TRACE("Unexpected Light State Type\n");
3083 return DDERR_INVALIDPARAMS;
3086 if(!Value)
3087 return DDERR_INVALIDPARAMS;
3089 EnterCriticalSection(&ddraw_cs);
3090 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3092 *Value = This->material;
3094 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3096 *Value = D3DCOLOR_RGB;
3098 else
3100 D3DRENDERSTATETYPE rs;
3101 switch (LightStateType)
3103 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3104 rs = D3DRENDERSTATE_AMBIENT;
3105 break;
3106 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3107 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3108 break;
3109 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3110 rs = D3DRENDERSTATE_FOGSTART;
3111 break;
3112 case D3DLIGHTSTATE_FOGEND: /* 6 */
3113 rs = D3DRENDERSTATE_FOGEND;
3114 break;
3115 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3116 rs = D3DRENDERSTATE_FOGDENSITY;
3117 break;
3118 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3119 rs = D3DRENDERSTATE_COLORVERTEX;
3120 break;
3121 default:
3122 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3123 LeaveCriticalSection(&ddraw_cs);
3124 return DDERR_INVALIDPARAMS;
3127 hr = IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, rs, Value);
3128 LeaveCriticalSection(&ddraw_cs);
3129 return hr;
3132 LeaveCriticalSection(&ddraw_cs);
3133 return D3D_OK;
3136 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3137 D3DLIGHTSTATETYPE LightStateType, DWORD *Value)
3139 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3141 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3143 return IDirect3DDevice3_GetLightState(&This->IDirect3DDevice3_iface, LightStateType, Value);
3146 /*****************************************************************************
3147 * IDirect3DDevice7::SetTransform
3149 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3150 * in include/d3dtypes.h.
3151 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3152 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3153 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3155 * Version 2, 3 and 7
3157 * Params:
3158 * TransformStateType: transform state to set
3159 * Matrix: Matrix to assign to the state
3161 * Returns:
3162 * D3D_OK on success
3163 * DDERR_INVALIDPARAMS if Matrix == NULL
3164 * For details see IWineD3DDevice::SetTransform
3166 *****************************************************************************/
3167 static HRESULT
3168 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3169 D3DTRANSFORMSTATETYPE TransformStateType,
3170 D3DMATRIX *Matrix)
3172 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3173 D3DTRANSFORMSTATETYPE type;
3174 HRESULT hr;
3176 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3178 switch(TransformStateType)
3180 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3181 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3182 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3183 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3184 default: type = TransformStateType;
3187 if (!Matrix)
3188 return DDERR_INVALIDPARAMS;
3190 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3191 EnterCriticalSection(&ddraw_cs);
3192 hr = wined3d_device_set_transform(This->wined3d_device, type, (WINED3DMATRIX *)Matrix);
3193 LeaveCriticalSection(&ddraw_cs);
3194 return hr;
3197 static HRESULT WINAPI
3198 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3199 D3DTRANSFORMSTATETYPE TransformStateType,
3200 D3DMATRIX *Matrix)
3202 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3205 static HRESULT WINAPI
3206 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3207 D3DTRANSFORMSTATETYPE TransformStateType,
3208 D3DMATRIX *Matrix)
3210 HRESULT hr;
3211 WORD old_fpucw;
3213 old_fpucw = d3d_fpu_setup();
3214 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3215 set_fpu_control_word(old_fpucw);
3217 return hr;
3220 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3221 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3223 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3225 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3227 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3230 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3231 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3233 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3235 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3237 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3240 /*****************************************************************************
3241 * IDirect3DDevice7::GetTransform
3243 * Returns the matrix assigned to a transform state
3244 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3245 * SetTransform
3247 * Params:
3248 * TransformStateType: State to read the matrix from
3249 * Matrix: Address to store the matrix at
3251 * Returns:
3252 * D3D_OK on success
3253 * DDERR_INVALIDPARAMS if Matrix == NULL
3254 * For details, see IWineD3DDevice::GetTransform
3256 *****************************************************************************/
3257 static HRESULT
3258 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3259 D3DTRANSFORMSTATETYPE TransformStateType,
3260 D3DMATRIX *Matrix)
3262 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3263 D3DTRANSFORMSTATETYPE type;
3264 HRESULT hr;
3266 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3268 switch(TransformStateType)
3270 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3271 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3272 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3273 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3274 default: type = TransformStateType;
3277 if(!Matrix)
3278 return DDERR_INVALIDPARAMS;
3280 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3281 EnterCriticalSection(&ddraw_cs);
3282 hr = wined3d_device_get_transform(This->wined3d_device, type, (WINED3DMATRIX *)Matrix);
3283 LeaveCriticalSection(&ddraw_cs);
3284 return hr;
3287 static HRESULT WINAPI
3288 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3289 D3DTRANSFORMSTATETYPE TransformStateType,
3290 D3DMATRIX *Matrix)
3292 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3295 static HRESULT WINAPI
3296 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3297 D3DTRANSFORMSTATETYPE TransformStateType,
3298 D3DMATRIX *Matrix)
3300 HRESULT hr;
3301 WORD old_fpucw;
3303 old_fpucw = d3d_fpu_setup();
3304 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3305 set_fpu_control_word(old_fpucw);
3307 return hr;
3310 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3311 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3313 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3315 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3317 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3320 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3321 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3323 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3325 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3327 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3330 /*****************************************************************************
3331 * IDirect3DDevice7::MultiplyTransform
3333 * Multiplies the already-set transform matrix of a transform state
3334 * with another matrix. For the world matrix, see SetTransform
3336 * Version 2, 3 and 7
3338 * Params:
3339 * TransformStateType: Transform state to multiply
3340 * D3DMatrix Matrix to multiply with.
3342 * Returns
3343 * D3D_OK on success
3344 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3345 * For details, see IWineD3DDevice::MultiplyTransform
3347 *****************************************************************************/
3348 static HRESULT
3349 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3350 D3DTRANSFORMSTATETYPE TransformStateType,
3351 D3DMATRIX *D3DMatrix)
3353 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3354 HRESULT hr;
3355 D3DTRANSFORMSTATETYPE type;
3357 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3359 switch(TransformStateType)
3361 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3362 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3363 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3364 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3365 default: type = TransformStateType;
3368 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3369 EnterCriticalSection(&ddraw_cs);
3370 hr = wined3d_device_multiply_transform(This->wined3d_device,
3371 type, (WINED3DMATRIX *)D3DMatrix);
3372 LeaveCriticalSection(&ddraw_cs);
3373 return hr;
3376 static HRESULT WINAPI
3377 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3378 D3DTRANSFORMSTATETYPE TransformStateType,
3379 D3DMATRIX *D3DMatrix)
3381 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3384 static HRESULT WINAPI
3385 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3386 D3DTRANSFORMSTATETYPE TransformStateType,
3387 D3DMATRIX *D3DMatrix)
3389 HRESULT hr;
3390 WORD old_fpucw;
3392 old_fpucw = d3d_fpu_setup();
3393 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3394 set_fpu_control_word(old_fpucw);
3396 return hr;
3399 static HRESULT WINAPI IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3400 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3402 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3404 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3406 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3409 static HRESULT WINAPI IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3410 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3412 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3414 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3416 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3419 /*****************************************************************************
3420 * IDirect3DDevice7::DrawPrimitive
3422 * Draws primitives based on vertices in an application-provided pointer
3424 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3425 * an FVF format for D3D7
3427 * Params:
3428 * PrimitiveType: The type of the primitives to draw
3429 * Vertex type: Flexible vertex format vertex description
3430 * Vertices: Pointer to the vertex array
3431 * VertexCount: The number of vertices to draw
3432 * Flags: As usual a few flags
3434 * Returns:
3435 * D3D_OK on success
3436 * DDERR_INVALIDPARAMS if Vertices is NULL
3437 * For details, see IWineD3DDevice::DrawPrimitiveUP
3439 *****************************************************************************/
3440 static HRESULT
3441 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3442 D3DPRIMITIVETYPE PrimitiveType,
3443 DWORD VertexType,
3444 void *Vertices,
3445 DWORD VertexCount,
3446 DWORD Flags)
3448 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3449 UINT stride;
3450 HRESULT hr;
3452 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3453 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3455 if(!Vertices)
3456 return DDERR_INVALIDPARAMS;
3458 /* Get the stride */
3459 stride = get_flexible_vertex_size(VertexType);
3461 /* Set the FVF */
3462 EnterCriticalSection(&ddraw_cs);
3463 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3464 if(hr != D3D_OK)
3466 LeaveCriticalSection(&ddraw_cs);
3467 return hr;
3470 /* This method translates to the user pointer draw of WineD3D */
3471 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3472 hr = wined3d_device_draw_primitive_up(This->wined3d_device, VertexCount, Vertices, stride);
3473 LeaveCriticalSection(&ddraw_cs);
3474 return hr;
3477 static HRESULT WINAPI
3478 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3479 D3DPRIMITIVETYPE PrimitiveType,
3480 DWORD VertexType,
3481 void *Vertices,
3482 DWORD VertexCount,
3483 DWORD Flags)
3485 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3488 static HRESULT WINAPI
3489 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3490 D3DPRIMITIVETYPE PrimitiveType,
3491 DWORD VertexType,
3492 void *Vertices,
3493 DWORD VertexCount,
3494 DWORD Flags)
3496 HRESULT hr;
3497 WORD old_fpucw;
3499 old_fpucw = d3d_fpu_setup();
3500 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3501 set_fpu_control_word(old_fpucw);
3503 return hr;
3506 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3507 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3508 DWORD Flags)
3510 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3511 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3512 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3514 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This,
3515 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3518 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3519 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3520 DWORD VertexCount, DWORD Flags)
3522 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3523 DWORD FVF;
3525 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3526 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3528 switch(VertexType)
3530 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3531 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3532 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3533 default:
3534 ERR("Unexpected vertex type %d\n", VertexType);
3535 return DDERR_INVALIDPARAMS; /* Should never happen */
3538 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This,
3539 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3542 /*****************************************************************************
3543 * IDirect3DDevice7::DrawIndexedPrimitive
3545 * Draws vertices from an application-provided pointer, based on the index
3546 * numbers in a WORD array.
3548 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3549 * an FVF format for D3D7
3551 * Params:
3552 * PrimitiveType: The primitive type to draw
3553 * VertexType: The FVF vertex description
3554 * Vertices: Pointer to the vertex array
3555 * VertexCount: ?
3556 * Indices: Pointer to the index array
3557 * IndexCount: Number of indices = Number of vertices to draw
3558 * Flags: As usual, some flags
3560 * Returns:
3561 * D3D_OK on success
3562 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3563 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3565 *****************************************************************************/
3566 static HRESULT
3567 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3568 D3DPRIMITIVETYPE PrimitiveType,
3569 DWORD VertexType,
3570 void *Vertices,
3571 DWORD VertexCount,
3572 WORD *Indices,
3573 DWORD IndexCount,
3574 DWORD Flags)
3576 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3577 HRESULT hr;
3579 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3580 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3582 /* Set the D3DDevice's FVF */
3583 EnterCriticalSection(&ddraw_cs);
3584 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3585 if(FAILED(hr))
3587 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3588 LeaveCriticalSection(&ddraw_cs);
3589 return hr;
3592 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3593 hr = wined3d_device_draw_indexed_primitive_up(This->wined3d_device, IndexCount, Indices,
3594 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3595 LeaveCriticalSection(&ddraw_cs);
3596 return hr;
3599 static HRESULT WINAPI
3600 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3601 D3DPRIMITIVETYPE PrimitiveType,
3602 DWORD VertexType,
3603 void *Vertices,
3604 DWORD VertexCount,
3605 WORD *Indices,
3606 DWORD IndexCount,
3607 DWORD Flags)
3609 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3612 static HRESULT WINAPI
3613 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3614 D3DPRIMITIVETYPE PrimitiveType,
3615 DWORD VertexType,
3616 void *Vertices,
3617 DWORD VertexCount,
3618 WORD *Indices,
3619 DWORD IndexCount,
3620 DWORD Flags)
3622 HRESULT hr;
3623 WORD old_fpucw;
3625 old_fpucw = d3d_fpu_setup();
3626 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3627 set_fpu_control_word(old_fpucw);
3629 return hr;
3632 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3633 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3634 WORD *Indices, DWORD IndexCount, DWORD Flags)
3636 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3637 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3638 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3640 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)This,
3641 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3644 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3645 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3646 DWORD VertexCount, WORD *Indices, DWORD IndexCount, DWORD Flags)
3648 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3649 DWORD FVF;
3651 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3652 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3654 switch(VertexType)
3656 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3657 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3658 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3659 default:
3660 ERR("Unexpected vertex type %d\n", VertexType);
3661 return DDERR_INVALIDPARAMS; /* Should never happen */
3664 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)This,
3665 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3668 /*****************************************************************************
3669 * IDirect3DDevice7::SetClipStatus
3671 * Sets the clip status. This defines things as clipping conditions and
3672 * the extents of the clipping region.
3674 * Version 2, 3 and 7
3676 * Params:
3677 * ClipStatus:
3679 * Returns:
3680 * D3D_OK because it's a stub
3681 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3683 *****************************************************************************/
3684 static HRESULT WINAPI
3685 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3686 D3DCLIPSTATUS *ClipStatus)
3688 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3690 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3691 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3693 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3694 return D3D_OK;
3697 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3698 D3DCLIPSTATUS *ClipStatus)
3700 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3701 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3703 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)This, ClipStatus);
3706 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3707 D3DCLIPSTATUS *ClipStatus)
3709 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3710 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3712 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)This, ClipStatus);
3715 /*****************************************************************************
3716 * IDirect3DDevice7::GetClipStatus
3718 * Returns the clip status
3720 * Params:
3721 * ClipStatus: Address to write the clip status to
3723 * Returns:
3724 * D3D_OK because it's a stub
3726 *****************************************************************************/
3727 static HRESULT WINAPI
3728 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3729 D3DCLIPSTATUS *ClipStatus)
3731 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3733 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3734 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3735 return D3D_OK;
3738 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3739 D3DCLIPSTATUS *ClipStatus)
3741 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3742 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3744 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)This, ClipStatus);
3747 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3748 D3DCLIPSTATUS *ClipStatus)
3750 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3751 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3753 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)This, ClipStatus);
3756 /*****************************************************************************
3757 * IDirect3DDevice::DrawPrimitiveStrided
3759 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3761 * Version 3 and 7
3763 * Params:
3764 * PrimitiveType: The primitive type to draw
3765 * VertexType: The FVF description of the vertices to draw (for the stride??)
3766 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3767 * the vertex data locations
3768 * VertexCount: The number of vertices to draw
3769 * Flags: Some flags
3771 * Returns:
3772 * D3D_OK, because it's a stub
3773 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3774 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3776 *****************************************************************************/
3777 static HRESULT
3778 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3779 D3DPRIMITIVETYPE PrimitiveType,
3780 DWORD VertexType,
3781 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3782 DWORD VertexCount,
3783 DWORD Flags)
3785 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3786 WineDirect3DVertexStridedData WineD3DStrided;
3787 DWORD i;
3788 HRESULT hr;
3790 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3791 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3793 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3794 /* Get the strided data right. the wined3d structure is a bit bigger
3795 * Watch out: The contents of the strided data are determined by the fvf,
3796 * not by the members set in D3DDrawPrimStrideData. So it's valid
3797 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3798 * not set in the fvf.
3800 if(VertexType & D3DFVF_POSITION_MASK)
3802 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3803 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3804 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3805 if (VertexType & D3DFVF_XYZRHW)
3807 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3808 WineD3DStrided.position_transformed = TRUE;
3809 } else
3810 WineD3DStrided.position_transformed = FALSE;
3813 if(VertexType & D3DFVF_NORMAL)
3815 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3816 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3817 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3820 if(VertexType & D3DFVF_DIFFUSE)
3822 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3823 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3824 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3827 if(VertexType & D3DFVF_SPECULAR)
3829 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3830 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3831 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3834 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3836 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3838 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3839 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3840 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3841 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3842 default: ERR("Unexpected texture coordinate size %d\n",
3843 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3845 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3846 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3849 /* WineD3D doesn't need the FVF here */
3850 EnterCriticalSection(&ddraw_cs);
3851 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3852 hr = wined3d_device_draw_primitive_strided(This->wined3d_device, VertexCount, &WineD3DStrided);
3853 LeaveCriticalSection(&ddraw_cs);
3854 return hr;
3857 static HRESULT WINAPI
3858 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3859 D3DPRIMITIVETYPE PrimitiveType,
3860 DWORD VertexType,
3861 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3862 DWORD VertexCount,
3863 DWORD Flags)
3865 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3868 static HRESULT WINAPI
3869 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3870 D3DPRIMITIVETYPE PrimitiveType,
3871 DWORD VertexType,
3872 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3873 DWORD VertexCount,
3874 DWORD Flags)
3876 HRESULT hr;
3877 WORD old_fpucw;
3879 old_fpucw = d3d_fpu_setup();
3880 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3881 set_fpu_control_word(old_fpucw);
3883 return hr;
3886 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3887 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3888 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3890 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3892 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3893 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3895 return IDirect3DDevice7_DrawPrimitiveStrided((IDirect3DDevice7 *)This,
3896 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3899 /*****************************************************************************
3900 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3902 * Draws primitives specified by strided data locations based on indices
3904 * Version 3 and 7
3906 * Params:
3907 * PrimitiveType:
3909 * Returns:
3910 * D3D_OK, because it's a stub
3911 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3912 * (DDERR_INVALIDPARAMS if Indices is NULL)
3913 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3915 *****************************************************************************/
3916 static HRESULT
3917 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3918 D3DPRIMITIVETYPE PrimitiveType,
3919 DWORD VertexType,
3920 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3921 DWORD VertexCount,
3922 WORD *Indices,
3923 DWORD IndexCount,
3924 DWORD Flags)
3926 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3927 WineDirect3DVertexStridedData WineD3DStrided;
3928 DWORD i;
3929 HRESULT hr;
3931 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3932 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3934 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3935 /* Get the strided data right. the wined3d structure is a bit bigger
3936 * Watch out: The contents of the strided data are determined by the fvf,
3937 * not by the members set in D3DDrawPrimStrideData. So it's valid
3938 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3939 * not set in the fvf.
3941 if(VertexType & D3DFVF_POSITION_MASK)
3943 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3944 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3945 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3946 if (VertexType & D3DFVF_XYZRHW)
3948 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3949 WineD3DStrided.position_transformed = TRUE;
3950 } else
3951 WineD3DStrided.position_transformed = FALSE;
3954 if(VertexType & D3DFVF_NORMAL)
3956 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3957 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3958 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3961 if(VertexType & D3DFVF_DIFFUSE)
3963 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3964 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3965 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3968 if(VertexType & D3DFVF_SPECULAR)
3970 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3971 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3972 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3975 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3977 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3979 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3980 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3981 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3982 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3983 default: ERR("Unexpected texture coordinate size %d\n",
3984 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3986 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3987 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3990 /* WineD3D doesn't need the FVF here */
3991 EnterCriticalSection(&ddraw_cs);
3992 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3993 hr = wined3d_device_draw_indexed_primitive_strided(This->wined3d_device,
3994 IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
3995 LeaveCriticalSection(&ddraw_cs);
3996 return hr;
3999 static HRESULT WINAPI
4000 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4001 D3DPRIMITIVETYPE PrimitiveType,
4002 DWORD VertexType,
4003 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4004 DWORD VertexCount,
4005 WORD *Indices,
4006 DWORD IndexCount,
4007 DWORD Flags)
4009 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4012 static HRESULT WINAPI
4013 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4014 D3DPRIMITIVETYPE PrimitiveType,
4015 DWORD VertexType,
4016 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4017 DWORD VertexCount,
4018 WORD *Indices,
4019 DWORD IndexCount,
4020 DWORD Flags)
4022 HRESULT hr;
4023 WORD old_fpucw;
4025 old_fpucw = d3d_fpu_setup();
4026 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4027 set_fpu_control_word(old_fpucw);
4029 return hr;
4032 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4033 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4034 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4035 DWORD IndexCount, DWORD Flags)
4037 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4039 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4040 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4042 return IDirect3DDevice7_DrawIndexedPrimitiveStrided((IDirect3DDevice7 *)This,
4043 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4046 /*****************************************************************************
4047 * IDirect3DDevice7::DrawPrimitiveVB
4049 * Draws primitives from a vertex buffer to the screen.
4051 * Version 3 and 7
4053 * Params:
4054 * PrimitiveType: Type of primitive to be rendered.
4055 * D3DVertexBuf: Source Vertex Buffer
4056 * StartVertex: Index of the first vertex from the buffer to be rendered
4057 * NumVertices: Number of vertices to be rendered
4058 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4060 * Return values
4061 * D3D_OK on success
4062 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4064 *****************************************************************************/
4065 static HRESULT
4066 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4067 D3DPRIMITIVETYPE PrimitiveType,
4068 IDirect3DVertexBuffer7 *D3DVertexBuf,
4069 DWORD StartVertex,
4070 DWORD NumVertices,
4071 DWORD Flags)
4073 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4074 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4075 HRESULT hr;
4076 DWORD stride;
4078 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4079 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4081 /* Sanity checks */
4082 if(!vb)
4084 ERR("(%p) No Vertex buffer specified\n", This);
4085 return DDERR_INVALIDPARAMS;
4087 stride = get_flexible_vertex_size(vb->fvf);
4089 EnterCriticalSection(&ddraw_cs);
4090 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4091 if (FAILED(hr))
4093 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4094 LeaveCriticalSection(&ddraw_cs);
4095 return hr;
4098 /* Set the vertex stream source */
4099 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4100 if(hr != D3D_OK)
4102 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4103 LeaveCriticalSection(&ddraw_cs);
4104 return hr;
4107 /* Now draw the primitives */
4108 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4109 hr = wined3d_device_draw_primitive(This->wined3d_device, StartVertex, NumVertices);
4110 LeaveCriticalSection(&ddraw_cs);
4111 return hr;
4114 static HRESULT WINAPI
4115 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4116 D3DPRIMITIVETYPE PrimitiveType,
4117 IDirect3DVertexBuffer7 *D3DVertexBuf,
4118 DWORD StartVertex,
4119 DWORD NumVertices,
4120 DWORD Flags)
4122 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4125 static HRESULT WINAPI
4126 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4127 D3DPRIMITIVETYPE PrimitiveType,
4128 IDirect3DVertexBuffer7 *D3DVertexBuf,
4129 DWORD StartVertex,
4130 DWORD NumVertices,
4131 DWORD Flags)
4133 HRESULT hr;
4134 WORD old_fpucw;
4136 old_fpucw = d3d_fpu_setup();
4137 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4138 set_fpu_control_word(old_fpucw);
4140 return hr;
4143 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4144 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex,
4145 DWORD NumVertices, DWORD Flags)
4147 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4148 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4150 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4151 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4153 return IDirect3DDevice7_DrawPrimitiveVB((IDirect3DDevice7 *)This,
4154 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4158 /*****************************************************************************
4159 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4161 * Draws primitives from a vertex buffer to the screen
4163 * Params:
4164 * PrimitiveType: Type of primitive to be rendered.
4165 * D3DVertexBuf: Source Vertex Buffer
4166 * StartVertex: Index of the first vertex from the buffer to be rendered
4167 * NumVertices: Number of vertices to be rendered
4168 * Indices: Array of DWORDs used to index into the Vertices
4169 * IndexCount: Number of indices in Indices
4170 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4172 * Return values
4174 *****************************************************************************/
4175 static HRESULT
4176 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4177 D3DPRIMITIVETYPE PrimitiveType,
4178 IDirect3DVertexBuffer7 *D3DVertexBuf,
4179 DWORD StartVertex,
4180 DWORD NumVertices,
4181 WORD *Indices,
4182 DWORD IndexCount,
4183 DWORD Flags)
4185 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4186 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4187 DWORD stride = get_flexible_vertex_size(vb->fvf);
4188 struct wined3d_resource *wined3d_resource;
4189 struct wined3d_resource_desc desc;
4190 WORD *LockedIndices;
4191 HRESULT hr;
4193 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4194 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4196 /* Steps:
4197 * 1) Upload the Indices to the index buffer
4198 * 2) Set the index source
4199 * 3) Set the Vertex Buffer as the Stream source
4200 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4203 EnterCriticalSection(&ddraw_cs);
4205 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4206 if (FAILED(hr))
4208 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4209 LeaveCriticalSection(&ddraw_cs);
4210 return hr;
4213 /* check that the buffer is large enough to hold the indices,
4214 * reallocate if necessary. */
4215 wined3d_resource = wined3d_buffer_get_resource(This->indexbuffer);
4216 wined3d_resource_get_desc(wined3d_resource, &desc);
4217 if (desc.size < IndexCount * sizeof(WORD))
4219 UINT size = max(desc.size * 2, IndexCount * sizeof(WORD));
4220 struct wined3d_buffer *buffer;
4222 TRACE("Growing index buffer to %u bytes\n", size);
4224 hr = wined3d_buffer_create_ib(This->wined3d_device, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4225 WINED3DPOOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
4226 if (FAILED(hr))
4228 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4229 LeaveCriticalSection(&ddraw_cs);
4230 return hr;
4233 wined3d_buffer_decref(This->indexbuffer);
4234 This->indexbuffer = buffer;
4237 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4238 * method could be created which takes an user pointer containing the
4239 * indices or a SetData-Method for the index buffer, which overrides the
4240 * index buffer data with our pointer. */
4241 hr = wined3d_buffer_map(This->indexbuffer, 0, IndexCount * sizeof(WORD),
4242 (BYTE **)&LockedIndices, 0);
4243 if (FAILED(hr))
4245 ERR("Failed to map buffer, hr %#x.\n", hr);
4246 LeaveCriticalSection(&ddraw_cs);
4247 return hr;
4249 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4250 wined3d_buffer_unmap(This->indexbuffer);
4252 /* Set the index stream */
4253 wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4254 hr = wined3d_device_set_index_buffer(This->wined3d_device, This->indexbuffer, WINED3DFMT_R16_UINT);
4256 /* Set the vertex stream source */
4257 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4258 if (FAILED(hr))
4260 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4261 LeaveCriticalSection(&ddraw_cs);
4262 return hr;
4266 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4267 hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, 0, IndexCount);
4269 LeaveCriticalSection(&ddraw_cs);
4270 return hr;
4273 static HRESULT WINAPI
4274 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4275 D3DPRIMITIVETYPE PrimitiveType,
4276 IDirect3DVertexBuffer7 *D3DVertexBuf,
4277 DWORD StartVertex,
4278 DWORD NumVertices,
4279 WORD *Indices,
4280 DWORD IndexCount,
4281 DWORD Flags)
4283 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4286 static HRESULT WINAPI
4287 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4288 D3DPRIMITIVETYPE PrimitiveType,
4289 IDirect3DVertexBuffer7 *D3DVertexBuf,
4290 DWORD StartVertex,
4291 DWORD NumVertices,
4292 WORD *Indices,
4293 DWORD IndexCount,
4294 DWORD Flags)
4296 HRESULT hr;
4297 WORD old_fpucw;
4299 old_fpucw = d3d_fpu_setup();
4300 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4301 set_fpu_control_word(old_fpucw);
4303 return hr;
4306 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4307 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4308 DWORD IndexCount, DWORD Flags)
4310 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4311 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4313 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4314 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4316 return IDirect3DDevice7_DrawIndexedPrimitiveVB((IDirect3DDevice7 *)This,
4317 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount,
4318 Flags);
4321 /*****************************************************************************
4322 * IDirect3DDevice7::ComputeSphereVisibility
4324 * Calculates the visibility of spheres in the current viewport. The spheres
4325 * are passed in the Centers and Radii arrays, the results are passed back
4326 * in the ReturnValues array. Return values are either completely visible,
4327 * partially visible or completely invisible.
4328 * The return value consist of a combination of D3DCLIP_* flags, or it's
4329 * 0 if the sphere is completely visible(according to the SDK, not checked)
4331 * Version 3 and 7
4333 * Params:
4334 * Centers: Array containing the sphere centers
4335 * Radii: Array containing the sphere radii
4336 * NumSpheres: The number of centers and radii in the arrays
4337 * Flags: Some flags
4338 * ReturnValues: Array to write the results to
4340 * Returns:
4341 * D3D_OK
4342 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4343 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4344 * is singular)
4346 *****************************************************************************/
4348 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4350 float distance, norm;
4352 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4353 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4355 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4356 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4357 return 0;
4360 static HRESULT WINAPI
4361 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4362 D3DVECTOR *Centers,
4363 D3DVALUE *Radii,
4364 DWORD NumSpheres,
4365 DWORD Flags,
4366 DWORD *ReturnValues)
4368 D3DMATRIX m, temp;
4369 D3DVALUE origin_plane[6];
4370 D3DVECTOR vec[6];
4371 HRESULT hr;
4372 UINT i, j;
4374 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4375 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4377 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4378 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4379 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4380 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4381 multiply_matrix(&m, &temp, &m);
4383 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4384 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4385 multiply_matrix(&m, &temp, &m);
4387 /* Left plane */
4388 vec[0].u1.x = m._14 + m._11;
4389 vec[0].u2.y = m._24 + m._21;
4390 vec[0].u3.z = m._34 + m._31;
4391 origin_plane[0] = m._44 + m._41;
4393 /* Right plane */
4394 vec[1].u1.x = m._14 - m._11;
4395 vec[1].u2.y = m._24 - m._21;
4396 vec[1].u3.z = m._34 - m._31;
4397 origin_plane[1] = m._44 - m._41;
4399 /* Top plane */
4400 vec[2].u1.x = m._14 - m._12;
4401 vec[2].u2.y = m._24 - m._22;
4402 vec[2].u3.z = m._34 - m._32;
4403 origin_plane[2] = m._44 - m._42;
4405 /* Bottom plane */
4406 vec[3].u1.x = m._14 + m._12;
4407 vec[3].u2.y = m._24 + m._22;
4408 vec[3].u3.z = m._34 + m._32;
4409 origin_plane[3] = m._44 + m._42;
4411 /* Front plane */
4412 vec[4].u1.x = m._13;
4413 vec[4].u2.y = m._23;
4414 vec[4].u3.z = m._33;
4415 origin_plane[4] = m._43;
4417 /* Back plane*/
4418 vec[5].u1.x = m._14 - m._13;
4419 vec[5].u2.y = m._24 - m._23;
4420 vec[5].u3.z = m._34 - m._33;
4421 origin_plane[5] = m._44 - m._43;
4423 for(i=0; i<NumSpheres; i++)
4425 ReturnValues[i] = 0;
4426 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4429 return D3D_OK;
4432 static HRESULT WINAPI IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4433 D3DVECTOR *Centers, D3DVALUE *Radii, DWORD NumSpheres, DWORD Flags, DWORD *ReturnValues)
4435 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4437 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4438 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4440 return IDirect3DDevice7_ComputeSphereVisibility((IDirect3DDevice7 *)This,
4441 Centers, Radii, NumSpheres, Flags, ReturnValues);
4444 /*****************************************************************************
4445 * IDirect3DDevice7::GetTexture
4447 * Returns the texture interface handle assigned to a texture stage.
4448 * The returned texture is AddRefed. This is taken from old ddraw,
4449 * not checked in Windows.
4451 * Version 3 and 7
4453 * Params:
4454 * Stage: Texture stage to read the texture from
4455 * Texture: Address to store the interface pointer at
4457 * Returns:
4458 * D3D_OK on success
4459 * DDERR_INVALIDPARAMS if Texture is NULL
4460 * For details, see IWineD3DDevice::GetTexture
4462 *****************************************************************************/
4463 static HRESULT
4464 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4465 DWORD Stage,
4466 IDirectDrawSurface7 **Texture)
4468 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4469 struct wined3d_texture *wined3d_texture;
4470 HRESULT hr;
4472 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4474 if(!Texture)
4476 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4477 return DDERR_INVALIDPARAMS;
4480 EnterCriticalSection(&ddraw_cs);
4481 hr = wined3d_device_get_texture(This->wined3d_device, Stage, &wined3d_texture);
4482 if (FAILED(hr) || !wined3d_texture)
4484 *Texture = NULL;
4485 LeaveCriticalSection(&ddraw_cs);
4486 return hr;
4489 *Texture = wined3d_texture_get_parent(wined3d_texture);
4490 IDirectDrawSurface7_AddRef(*Texture);
4491 wined3d_texture_decref(wined3d_texture);
4492 LeaveCriticalSection(&ddraw_cs);
4493 return hr;
4496 static HRESULT WINAPI
4497 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4498 DWORD Stage,
4499 IDirectDrawSurface7 **Texture)
4501 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4504 static HRESULT WINAPI
4505 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4506 DWORD Stage,
4507 IDirectDrawSurface7 **Texture)
4509 HRESULT hr;
4510 WORD old_fpucw;
4512 old_fpucw = d3d_fpu_setup();
4513 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4514 set_fpu_control_word(old_fpucw);
4516 return hr;
4519 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface, DWORD Stage,
4520 IDirect3DTexture2 **Texture2)
4522 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4523 HRESULT ret;
4524 IDirectDrawSurface7 *ret_val;
4525 IDirectDrawSurfaceImpl *ret_val_impl;
4527 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4529 ret = IDirect3DDevice7_GetTexture((IDirect3DDevice7 *)This, Stage, &ret_val);
4531 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4532 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4534 TRACE("Returning texture %p.\n", *Texture2);
4536 return ret;
4539 /*****************************************************************************
4540 * IDirect3DDevice7::SetTexture
4542 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4544 * Version 3 and 7
4546 * Params:
4547 * Stage: The stage to assign the texture to
4548 * Texture: Interface pointer to the texture surface
4550 * Returns
4551 * D3D_OK on success
4552 * For details, see IWineD3DDevice::SetTexture
4554 *****************************************************************************/
4555 static HRESULT
4556 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4557 DWORD Stage,
4558 IDirectDrawSurface7 *Texture)
4560 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4561 IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
4562 HRESULT hr;
4564 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4566 /* Texture may be NULL here */
4567 EnterCriticalSection(&ddraw_cs);
4568 hr = wined3d_device_set_texture(This->wined3d_device,
4569 Stage, surf ? surf->wined3d_texture : NULL);
4570 LeaveCriticalSection(&ddraw_cs);
4571 return hr;
4574 static HRESULT WINAPI
4575 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4576 DWORD Stage,
4577 IDirectDrawSurface7 *Texture)
4579 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4582 static HRESULT WINAPI
4583 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4584 DWORD Stage,
4585 IDirectDrawSurface7 *Texture)
4587 HRESULT hr;
4588 WORD old_fpucw;
4590 old_fpucw = d3d_fpu_setup();
4591 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4592 set_fpu_control_word(old_fpucw);
4594 return hr;
4597 static HRESULT WINAPI
4598 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4599 DWORD Stage,
4600 IDirect3DTexture2 *Texture2)
4602 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4603 IDirectDrawSurfaceImpl *tex = unsafe_impl_from_IDirect3DTexture2(Texture2);
4604 DWORD texmapblend;
4605 HRESULT hr;
4607 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4609 EnterCriticalSection(&ddraw_cs);
4611 if (This->legacyTextureBlending)
4612 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4614 hr = IDirect3DDevice7_SetTexture((IDirect3DDevice7 *)This, Stage, &tex->IDirectDrawSurface7_iface);
4616 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4618 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4619 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4620 struct wined3d_texture *tex = NULL;
4621 BOOL tex_alpha = FALSE;
4622 DDPIXELFORMAT ddfmt;
4623 HRESULT result;
4625 result = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
4626 if (result == WINED3D_OK && tex)
4628 struct wined3d_resource *sub_resource;
4630 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4632 struct wined3d_resource_desc desc;
4634 wined3d_resource_get_desc(sub_resource, &desc);
4635 ddfmt.dwSize = sizeof(ddfmt);
4636 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4637 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4640 wined3d_texture_decref(tex);
4643 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4644 if (tex_alpha)
4645 wined3d_device_set_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4646 else
4647 wined3d_device_set_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4650 LeaveCriticalSection(&ddraw_cs);
4652 return hr;
4655 static const struct tss_lookup
4657 BOOL sampler_state;
4658 DWORD state;
4660 tss_lookup[] =
4662 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
4663 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
4664 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
4665 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
4666 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
4667 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
4668 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
4669 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4670 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4671 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4672 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4673 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4674 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
4675 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
4676 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
4677 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
4678 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
4679 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
4680 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
4681 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4682 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4683 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4684 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4685 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4686 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4689 /*****************************************************************************
4690 * IDirect3DDevice7::GetTextureStageState
4692 * Retrieves a state from a texture stage.
4694 * Version 3 and 7
4696 * Params:
4697 * Stage: The stage to retrieve the state from
4698 * TexStageStateType: The state type to retrieve
4699 * State: Address to store the state's value at
4701 * Returns:
4702 * D3D_OK on success
4703 * DDERR_INVALIDPARAMS if State is NULL
4704 * For details, see IWineD3DDevice::GetTextureStageState
4706 *****************************************************************************/
4707 static HRESULT
4708 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4709 DWORD Stage,
4710 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4711 DWORD *State)
4713 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4714 HRESULT hr;
4715 const struct tss_lookup *l;
4717 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4718 iface, Stage, TexStageStateType, State);
4720 if(!State)
4721 return DDERR_INVALIDPARAMS;
4723 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4725 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4726 return DD_OK;
4729 l = &tss_lookup[TexStageStateType];
4731 EnterCriticalSection(&ddraw_cs);
4733 if (l->sampler_state)
4735 hr = wined3d_device_get_sampler_state(This->wined3d_device, Stage, l->state, State);
4737 switch(TexStageStateType)
4739 /* Mipfilter is a sampler state with different values */
4740 case D3DTSS_MIPFILTER:
4742 switch(*State)
4744 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4745 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4746 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4747 default:
4748 ERR("Unexpected mipfilter value %#x\n", *State);
4749 *State = D3DTFP_NONE;
4750 break;
4752 break;
4755 /* Magfilter has slightly different values */
4756 case D3DTSS_MAGFILTER:
4758 switch(*State)
4760 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4761 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4762 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4763 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4764 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4765 default:
4766 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4767 *State = D3DTFG_POINT;
4768 break;
4770 break;
4773 default:
4774 break;
4777 else
4779 hr = wined3d_device_get_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4782 LeaveCriticalSection(&ddraw_cs);
4783 return hr;
4786 static HRESULT WINAPI
4787 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4788 DWORD Stage,
4789 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4790 DWORD *State)
4792 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4795 static HRESULT WINAPI
4796 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4797 DWORD Stage,
4798 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4799 DWORD *State)
4801 HRESULT hr;
4802 WORD old_fpucw;
4804 old_fpucw = d3d_fpu_setup();
4805 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4806 set_fpu_control_word(old_fpucw);
4808 return hr;
4811 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4812 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD *State)
4814 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4816 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4817 iface, Stage, TexStageStateType, State);
4819 return IDirect3DDevice7_GetTextureStageState((IDirect3DDevice7 *)This,
4820 Stage, TexStageStateType, State);
4823 /*****************************************************************************
4824 * IDirect3DDevice7::SetTextureStageState
4826 * Sets a texture stage state. Some stage types need to be handled specially,
4827 * because they do not exist in WineD3D and were moved to another place
4829 * Version 3 and 7
4831 * Params:
4832 * Stage: The stage to modify
4833 * TexStageStateType: The state to change
4834 * State: The new value for the state
4836 * Returns:
4837 * D3D_OK on success
4838 * For details, see IWineD3DDevice::SetTextureStageState
4840 *****************************************************************************/
4841 static HRESULT
4842 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4843 DWORD Stage,
4844 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4845 DWORD State)
4847 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4848 const struct tss_lookup *l;
4849 HRESULT hr;
4851 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4852 iface, Stage, TexStageStateType, State);
4854 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4856 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4857 return DD_OK;
4860 l = &tss_lookup[TexStageStateType];
4862 EnterCriticalSection(&ddraw_cs);
4864 if (l->sampler_state)
4866 switch(TexStageStateType)
4868 /* Mipfilter is a sampler state with different values */
4869 case D3DTSS_MIPFILTER:
4871 switch(State)
4873 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
4874 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
4875 case 0: /* Unchecked */
4876 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
4877 default:
4878 ERR("Unexpected mipfilter value %d\n", State);
4879 State = WINED3DTEXF_NONE;
4880 break;
4882 break;
4885 /* Magfilter has slightly different values */
4886 case D3DTSS_MAGFILTER:
4888 switch(State)
4890 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
4891 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
4892 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
4893 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
4894 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
4895 default:
4896 ERR("Unexpected d3d7 mag filter type %d\n", State);
4897 State = WINED3DTEXF_POINT;
4898 break;
4900 break;
4903 case D3DTSS_ADDRESS:
4904 wined3d_device_set_sampler_state(This->wined3d_device, Stage, WINED3DSAMP_ADDRESSV, State);
4905 break;
4907 default:
4908 break;
4911 hr = wined3d_device_set_sampler_state(This->wined3d_device, Stage, l->state, State);
4913 else
4915 hr = wined3d_device_set_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4918 LeaveCriticalSection(&ddraw_cs);
4919 return hr;
4922 static HRESULT WINAPI
4923 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4924 DWORD Stage,
4925 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4926 DWORD State)
4928 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4931 static HRESULT WINAPI
4932 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4933 DWORD Stage,
4934 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4935 DWORD State)
4937 HRESULT hr;
4938 WORD old_fpucw;
4940 old_fpucw = d3d_fpu_setup();
4941 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4942 set_fpu_control_word(old_fpucw);
4944 return hr;
4947 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
4948 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD State)
4950 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4952 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4953 iface, Stage, TexStageStateType, State);
4955 return IDirect3DDevice7_SetTextureStageState((IDirect3DDevice7 *)This,
4956 Stage, TexStageStateType, State);
4959 /*****************************************************************************
4960 * IDirect3DDevice7::ValidateDevice
4962 * SDK: "Reports the device's ability to render the currently set
4963 * texture-blending operations in a single pass". Whatever that means
4964 * exactly...
4966 * Version 3 and 7
4968 * Params:
4969 * NumPasses: Address to write the number of necessary passes for the
4970 * desired effect to.
4972 * Returns:
4973 * D3D_OK on success
4974 * See IWineD3DDevice::ValidateDevice for more details
4976 *****************************************************************************/
4977 static HRESULT
4978 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
4979 DWORD *NumPasses)
4981 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4982 HRESULT hr;
4984 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
4986 EnterCriticalSection(&ddraw_cs);
4987 hr = wined3d_device_validate_device(This->wined3d_device, NumPasses);
4988 LeaveCriticalSection(&ddraw_cs);
4989 return hr;
4992 static HRESULT WINAPI
4993 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
4994 DWORD *NumPasses)
4996 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4999 static HRESULT WINAPI
5000 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
5001 DWORD *NumPasses)
5003 HRESULT hr;
5004 WORD old_fpucw;
5006 old_fpucw = d3d_fpu_setup();
5007 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5008 set_fpu_control_word(old_fpucw);
5010 return hr;
5013 static HRESULT WINAPI IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *Passes)
5015 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
5017 TRACE("iface %p, pass_count %p.\n", iface, Passes);
5019 return IDirect3DDevice7_ValidateDevice((IDirect3DDevice7 *)This, Passes);
5022 /*****************************************************************************
5023 * IDirect3DDevice7::Clear
5025 * Fills the render target, the z buffer and the stencil buffer with a
5026 * clear color / value
5028 * Version 7 only
5030 * Params:
5031 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5032 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5033 * Flags: Some flags, as usual
5034 * Color: Clear color for the render target
5035 * Z: Clear value for the Z buffer
5036 * Stencil: Clear value to store in each stencil buffer entry
5038 * Returns:
5039 * D3D_OK on success
5040 * For details, see IWineD3DDevice::Clear
5042 *****************************************************************************/
5043 static HRESULT
5044 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
5045 DWORD Count,
5046 D3DRECT *Rects,
5047 DWORD Flags,
5048 D3DCOLOR Color,
5049 D3DVALUE Z,
5050 DWORD Stencil)
5052 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5053 HRESULT hr;
5055 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5056 iface, Count, Rects, Flags, Color, Z, Stencil);
5058 EnterCriticalSection(&ddraw_cs);
5059 hr = wined3d_device_clear(This->wined3d_device, Count, (RECT *)Rects, Flags, Color, Z, Stencil);
5060 LeaveCriticalSection(&ddraw_cs);
5061 return hr;
5064 static HRESULT WINAPI
5065 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5066 DWORD Count,
5067 D3DRECT *Rects,
5068 DWORD Flags,
5069 D3DCOLOR Color,
5070 D3DVALUE Z,
5071 DWORD Stencil)
5073 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5076 static HRESULT WINAPI
5077 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5078 DWORD Count,
5079 D3DRECT *Rects,
5080 DWORD Flags,
5081 D3DCOLOR Color,
5082 D3DVALUE Z,
5083 DWORD Stencil)
5085 HRESULT hr;
5086 WORD old_fpucw;
5088 old_fpucw = d3d_fpu_setup();
5089 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5090 set_fpu_control_word(old_fpucw);
5092 return hr;
5095 /*****************************************************************************
5096 * IDirect3DDevice7::SetViewport
5098 * Sets the current viewport.
5100 * Version 7 only, but IDirect3DViewport uses this call for older
5101 * versions
5103 * Params:
5104 * Data: The new viewport to set
5106 * Returns:
5107 * D3D_OK on success
5108 * DDERR_INVALIDPARAMS if Data is NULL
5109 * For more details, see IWineDDDevice::SetViewport
5111 *****************************************************************************/
5112 static HRESULT
5113 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5114 D3DVIEWPORT7 *Data)
5116 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5117 HRESULT hr;
5119 TRACE("iface %p, viewport %p.\n", iface, Data);
5121 if(!Data)
5122 return DDERR_INVALIDPARAMS;
5124 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5125 EnterCriticalSection(&ddraw_cs);
5126 hr = wined3d_device_set_viewport(This->wined3d_device, (WINED3DVIEWPORT *)Data);
5127 LeaveCriticalSection(&ddraw_cs);
5128 return hr;
5131 static HRESULT WINAPI
5132 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5133 D3DVIEWPORT7 *Data)
5135 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5138 static HRESULT WINAPI
5139 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5140 D3DVIEWPORT7 *Data)
5142 HRESULT hr;
5143 WORD old_fpucw;
5145 old_fpucw = d3d_fpu_setup();
5146 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5147 set_fpu_control_word(old_fpucw);
5149 return hr;
5152 /*****************************************************************************
5153 * IDirect3DDevice::GetViewport
5155 * Returns the current viewport
5157 * Version 7
5159 * Params:
5160 * Data: D3D7Viewport structure to write the viewport information to
5162 * Returns:
5163 * D3D_OK on success
5164 * DDERR_INVALIDPARAMS if Data is NULL
5165 * For more details, see IWineD3DDevice::GetViewport
5167 *****************************************************************************/
5168 static HRESULT
5169 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5170 D3DVIEWPORT7 *Data)
5172 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5173 HRESULT hr;
5175 TRACE("iface %p, viewport %p.\n", iface, Data);
5177 if(!Data)
5178 return DDERR_INVALIDPARAMS;
5180 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5181 EnterCriticalSection(&ddraw_cs);
5182 hr = wined3d_device_get_viewport(This->wined3d_device, (WINED3DVIEWPORT *)Data);
5184 LeaveCriticalSection(&ddraw_cs);
5185 return hr_ddraw_from_wined3d(hr);
5188 static HRESULT WINAPI
5189 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5190 D3DVIEWPORT7 *Data)
5192 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5195 static HRESULT WINAPI
5196 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5197 D3DVIEWPORT7 *Data)
5199 HRESULT hr;
5200 WORD old_fpucw;
5202 old_fpucw = d3d_fpu_setup();
5203 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5204 set_fpu_control_word(old_fpucw);
5206 return hr;
5209 /*****************************************************************************
5210 * IDirect3DDevice7::SetMaterial
5212 * Sets the Material
5214 * Version 7
5216 * Params:
5217 * Mat: The material to set
5219 * Returns:
5220 * D3D_OK on success
5221 * DDERR_INVALIDPARAMS if Mat is NULL.
5222 * For more details, see IWineD3DDevice::SetMaterial
5224 *****************************************************************************/
5225 static HRESULT
5226 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5227 D3DMATERIAL7 *Mat)
5229 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5230 HRESULT hr;
5232 TRACE("iface %p, material %p.\n", iface, Mat);
5234 if (!Mat) return DDERR_INVALIDPARAMS;
5235 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5236 EnterCriticalSection(&ddraw_cs);
5237 hr = wined3d_device_set_material(This->wined3d_device, (WINED3DMATERIAL *)Mat);
5238 LeaveCriticalSection(&ddraw_cs);
5239 return hr_ddraw_from_wined3d(hr);
5242 static HRESULT WINAPI
5243 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5244 D3DMATERIAL7 *Mat)
5246 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5249 static HRESULT WINAPI
5250 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5251 D3DMATERIAL7 *Mat)
5253 HRESULT hr;
5254 WORD old_fpucw;
5256 old_fpucw = d3d_fpu_setup();
5257 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5258 set_fpu_control_word(old_fpucw);
5260 return hr;
5263 /*****************************************************************************
5264 * IDirect3DDevice7::GetMaterial
5266 * Returns the current material
5268 * Version 7
5270 * Params:
5271 * Mat: D3DMATERIAL7 structure to write the material parameters to
5273 * Returns:
5274 * D3D_OK on success
5275 * DDERR_INVALIDPARAMS if Mat is NULL
5276 * For more details, see IWineD3DDevice::GetMaterial
5278 *****************************************************************************/
5279 static HRESULT
5280 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5281 D3DMATERIAL7 *Mat)
5283 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5284 HRESULT hr;
5286 TRACE("iface %p, material %p.\n", iface, Mat);
5288 EnterCriticalSection(&ddraw_cs);
5289 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5290 hr = wined3d_device_get_material(This->wined3d_device, (WINED3DMATERIAL *)Mat);
5291 LeaveCriticalSection(&ddraw_cs);
5292 return hr_ddraw_from_wined3d(hr);
5295 static HRESULT WINAPI
5296 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5297 D3DMATERIAL7 *Mat)
5299 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5302 static HRESULT WINAPI
5303 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5304 D3DMATERIAL7 *Mat)
5306 HRESULT hr;
5307 WORD old_fpucw;
5309 old_fpucw = d3d_fpu_setup();
5310 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5311 set_fpu_control_word(old_fpucw);
5313 return hr;
5316 /*****************************************************************************
5317 * IDirect3DDevice7::SetLight
5319 * Assigns a light to a light index, but doesn't activate it yet.
5321 * Version 7, IDirect3DLight uses this method for older versions
5323 * Params:
5324 * LightIndex: The index of the new light
5325 * Light: A D3DLIGHT7 structure describing the light
5327 * Returns:
5328 * D3D_OK on success
5329 * For more details, see IWineD3DDevice::SetLight
5331 *****************************************************************************/
5332 static HRESULT
5333 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5334 DWORD LightIndex,
5335 D3DLIGHT7 *Light)
5337 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5338 HRESULT hr;
5340 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5342 EnterCriticalSection(&ddraw_cs);
5343 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5344 hr = wined3d_device_set_light(This->wined3d_device, LightIndex, (WINED3DLIGHT *)Light);
5345 LeaveCriticalSection(&ddraw_cs);
5346 return hr_ddraw_from_wined3d(hr);
5349 static HRESULT WINAPI
5350 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5351 DWORD LightIndex,
5352 D3DLIGHT7 *Light)
5354 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5357 static HRESULT WINAPI
5358 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5359 DWORD LightIndex,
5360 D3DLIGHT7 *Light)
5362 HRESULT hr;
5363 WORD old_fpucw;
5365 old_fpucw = d3d_fpu_setup();
5366 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5367 set_fpu_control_word(old_fpucw);
5369 return hr;
5372 /*****************************************************************************
5373 * IDirect3DDevice7::GetLight
5375 * Returns the light assigned to a light index
5377 * Params:
5378 * Light: Structure to write the light information to
5380 * Returns:
5381 * D3D_OK on success
5382 * DDERR_INVALIDPARAMS if Light is NULL
5383 * For details, see IWineD3DDevice::GetLight
5385 *****************************************************************************/
5386 static HRESULT
5387 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5388 DWORD LightIndex,
5389 D3DLIGHT7 *Light)
5391 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5392 HRESULT rc;
5394 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5396 EnterCriticalSection(&ddraw_cs);
5397 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5398 rc = wined3d_device_get_light(This->wined3d_device, LightIndex, (WINED3DLIGHT *)Light);
5400 /* Translate the result. WineD3D returns other values than D3D7 */
5401 LeaveCriticalSection(&ddraw_cs);
5402 return hr_ddraw_from_wined3d(rc);
5405 static HRESULT WINAPI
5406 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5407 DWORD LightIndex,
5408 D3DLIGHT7 *Light)
5410 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5413 static HRESULT WINAPI
5414 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5415 DWORD LightIndex,
5416 D3DLIGHT7 *Light)
5418 HRESULT hr;
5419 WORD old_fpucw;
5421 old_fpucw = d3d_fpu_setup();
5422 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5423 set_fpu_control_word(old_fpucw);
5425 return hr;
5428 /*****************************************************************************
5429 * IDirect3DDevice7::BeginStateBlock
5431 * Begins recording to a stateblock
5433 * Version 7
5435 * Returns:
5436 * D3D_OK on success
5437 * For details see IWineD3DDevice::BeginStateBlock
5439 *****************************************************************************/
5440 static HRESULT
5441 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5443 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5444 HRESULT hr;
5446 TRACE("iface %p.\n", iface);
5448 EnterCriticalSection(&ddraw_cs);
5449 hr = wined3d_device_begin_stateblock(This->wined3d_device);
5450 LeaveCriticalSection(&ddraw_cs);
5451 return hr_ddraw_from_wined3d(hr);
5454 static HRESULT WINAPI
5455 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5457 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5460 static HRESULT WINAPI
5461 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5463 HRESULT hr;
5464 WORD old_fpucw;
5466 old_fpucw = d3d_fpu_setup();
5467 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5468 set_fpu_control_word(old_fpucw);
5470 return hr;
5473 /*****************************************************************************
5474 * IDirect3DDevice7::EndStateBlock
5476 * Stops recording to a state block and returns the created stateblock
5477 * handle.
5479 * Version 7
5481 * Params:
5482 * BlockHandle: Address to store the stateblock's handle to
5484 * Returns:
5485 * D3D_OK on success
5486 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5487 * See IWineD3DDevice::EndStateBlock for more details
5489 *****************************************************************************/
5490 static HRESULT
5491 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5492 DWORD *BlockHandle)
5494 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5495 struct wined3d_stateblock *wined3d_sb;
5496 HRESULT hr;
5497 DWORD h;
5499 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5501 if(!BlockHandle)
5503 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5504 return DDERR_INVALIDPARAMS;
5507 EnterCriticalSection(&ddraw_cs);
5509 hr = wined3d_device_end_stateblock(This->wined3d_device, &wined3d_sb);
5510 if (FAILED(hr))
5512 WARN("Failed to end stateblock, hr %#x.\n", hr);
5513 LeaveCriticalSection(&ddraw_cs);
5514 *BlockHandle = 0;
5515 return hr_ddraw_from_wined3d(hr);
5518 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5519 if (h == DDRAW_INVALID_HANDLE)
5521 ERR("Failed to allocate a stateblock handle.\n");
5522 wined3d_stateblock_decref(wined3d_sb);
5523 LeaveCriticalSection(&ddraw_cs);
5524 *BlockHandle = 0;
5525 return DDERR_OUTOFMEMORY;
5528 LeaveCriticalSection(&ddraw_cs);
5529 *BlockHandle = h + 1;
5531 return hr_ddraw_from_wined3d(hr);
5534 static HRESULT WINAPI
5535 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5536 DWORD *BlockHandle)
5538 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5541 static HRESULT WINAPI
5542 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5543 DWORD *BlockHandle)
5545 HRESULT hr;
5546 WORD old_fpucw;
5548 old_fpucw = d3d_fpu_setup();
5549 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5550 set_fpu_control_word(old_fpucw);
5552 return hr;
5555 /*****************************************************************************
5556 * IDirect3DDevice7::PreLoad
5558 * Allows the app to signal that a texture will be used soon, to allow
5559 * the Direct3DDevice to load it to the video card in the meantime.
5561 * Version 7
5563 * Params:
5564 * Texture: The texture to preload
5566 * Returns:
5567 * D3D_OK on success
5568 * DDERR_INVALIDPARAMS if Texture is NULL
5569 * See IWineD3DSurface::PreLoad for details
5571 *****************************************************************************/
5572 static HRESULT
5573 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5574 IDirectDrawSurface7 *Texture)
5576 IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
5578 TRACE("iface %p, texture %p.\n", iface, Texture);
5580 if(!Texture)
5581 return DDERR_INVALIDPARAMS;
5583 EnterCriticalSection(&ddraw_cs);
5584 wined3d_surface_preload(surf->wined3d_surface);
5585 LeaveCriticalSection(&ddraw_cs);
5586 return D3D_OK;
5589 static HRESULT WINAPI
5590 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5591 IDirectDrawSurface7 *Texture)
5593 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5596 static HRESULT WINAPI
5597 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5598 IDirectDrawSurface7 *Texture)
5600 HRESULT hr;
5601 WORD old_fpucw;
5603 old_fpucw = d3d_fpu_setup();
5604 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5605 set_fpu_control_word(old_fpucw);
5607 return hr;
5610 /*****************************************************************************
5611 * IDirect3DDevice7::ApplyStateBlock
5613 * Activates the state stored in a state block handle.
5615 * Params:
5616 * BlockHandle: The stateblock handle to activate
5618 * Returns:
5619 * D3D_OK on success
5620 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5622 *****************************************************************************/
5623 static HRESULT
5624 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5625 DWORD BlockHandle)
5627 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5628 struct wined3d_stateblock *wined3d_sb;
5629 HRESULT hr;
5631 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5633 EnterCriticalSection(&ddraw_cs);
5635 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5636 if (!wined3d_sb)
5638 WARN("Invalid stateblock handle.\n");
5639 LeaveCriticalSection(&ddraw_cs);
5640 return D3DERR_INVALIDSTATEBLOCK;
5643 hr = wined3d_stateblock_apply(wined3d_sb);
5644 LeaveCriticalSection(&ddraw_cs);
5646 return hr_ddraw_from_wined3d(hr);
5649 static HRESULT WINAPI
5650 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5651 DWORD BlockHandle)
5653 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5656 static HRESULT WINAPI
5657 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5658 DWORD BlockHandle)
5660 HRESULT hr;
5661 WORD old_fpucw;
5663 old_fpucw = d3d_fpu_setup();
5664 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5665 set_fpu_control_word(old_fpucw);
5667 return hr;
5670 /*****************************************************************************
5671 * IDirect3DDevice7::CaptureStateBlock
5673 * Updates a stateblock's values to the values currently set for the device
5675 * Version 7
5677 * Params:
5678 * BlockHandle: Stateblock to update
5680 * Returns:
5681 * D3D_OK on success
5682 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5683 * See IWineD3DDevice::CaptureStateBlock for more details
5685 *****************************************************************************/
5686 static HRESULT
5687 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5688 DWORD BlockHandle)
5690 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5691 struct wined3d_stateblock *wined3d_sb;
5692 HRESULT hr;
5694 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5696 EnterCriticalSection(&ddraw_cs);
5698 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5699 if (!wined3d_sb)
5701 WARN("Invalid stateblock handle.\n");
5702 LeaveCriticalSection(&ddraw_cs);
5703 return D3DERR_INVALIDSTATEBLOCK;
5706 hr = wined3d_stateblock_capture(wined3d_sb);
5707 LeaveCriticalSection(&ddraw_cs);
5708 return hr_ddraw_from_wined3d(hr);
5711 static HRESULT WINAPI
5712 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5713 DWORD BlockHandle)
5715 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5718 static HRESULT WINAPI
5719 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5720 DWORD BlockHandle)
5722 HRESULT hr;
5723 WORD old_fpucw;
5725 old_fpucw = d3d_fpu_setup();
5726 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5727 set_fpu_control_word(old_fpucw);
5729 return hr;
5732 /*****************************************************************************
5733 * IDirect3DDevice7::DeleteStateBlock
5735 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5737 * Version 7
5739 * Params:
5740 * BlockHandle: Stateblock handle to delete
5742 * Returns:
5743 * D3D_OK on success
5744 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5746 *****************************************************************************/
5747 static HRESULT
5748 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5749 DWORD BlockHandle)
5751 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5752 struct wined3d_stateblock *wined3d_sb;
5753 ULONG ref;
5755 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5757 EnterCriticalSection(&ddraw_cs);
5759 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5760 if (!wined3d_sb)
5762 WARN("Invalid stateblock handle.\n");
5763 LeaveCriticalSection(&ddraw_cs);
5764 return D3DERR_INVALIDSTATEBLOCK;
5767 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5769 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5772 LeaveCriticalSection(&ddraw_cs);
5773 return D3D_OK;
5776 static HRESULT WINAPI
5777 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5778 DWORD BlockHandle)
5780 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5783 static HRESULT WINAPI
5784 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5785 DWORD BlockHandle)
5787 HRESULT hr;
5788 WORD old_fpucw;
5790 old_fpucw = d3d_fpu_setup();
5791 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5792 set_fpu_control_word(old_fpucw);
5794 return hr;
5797 /*****************************************************************************
5798 * IDirect3DDevice7::CreateStateBlock
5800 * Creates a new state block handle.
5802 * Version 7
5804 * Params:
5805 * Type: The state block type
5806 * BlockHandle: Address to write the created handle to
5808 * Returns:
5809 * D3D_OK on success
5810 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5812 *****************************************************************************/
5813 static HRESULT
5814 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5815 D3DSTATEBLOCKTYPE Type,
5816 DWORD *BlockHandle)
5818 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5819 struct wined3d_stateblock *wined3d_sb;
5820 HRESULT hr;
5821 DWORD h;
5823 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5825 if(!BlockHandle)
5827 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5828 return DDERR_INVALIDPARAMS;
5830 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5831 Type != D3DSBT_VERTEXSTATE ) {
5832 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5833 return DDERR_INVALIDPARAMS;
5836 EnterCriticalSection(&ddraw_cs);
5838 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5839 hr = wined3d_stateblock_create(This->wined3d_device, Type, &wined3d_sb);
5840 if (FAILED(hr))
5842 WARN("Failed to create stateblock, hr %#x.\n", hr);
5843 LeaveCriticalSection(&ddraw_cs);
5844 return hr_ddraw_from_wined3d(hr);
5847 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5848 if (h == DDRAW_INVALID_HANDLE)
5850 ERR("Failed to allocate stateblock handle.\n");
5851 wined3d_stateblock_decref(wined3d_sb);
5852 LeaveCriticalSection(&ddraw_cs);
5853 return DDERR_OUTOFMEMORY;
5856 *BlockHandle = h + 1;
5857 LeaveCriticalSection(&ddraw_cs);
5859 return hr_ddraw_from_wined3d(hr);
5862 static HRESULT WINAPI
5863 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5864 D3DSTATEBLOCKTYPE Type,
5865 DWORD *BlockHandle)
5867 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5870 static HRESULT WINAPI
5871 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5872 D3DSTATEBLOCKTYPE Type,
5873 DWORD *BlockHandle)
5875 HRESULT hr;
5876 WORD old_fpucw;
5878 old_fpucw = d3d_fpu_setup();
5879 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5880 set_fpu_control_word(old_fpucw);
5882 return hr;
5885 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5886 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
5887 IDirectDrawSurfaceImpl *src)
5889 IDirectDrawSurfaceImpl *src_level, *dest_level;
5890 IDirectDrawSurface7 *temp;
5891 DDSURFACEDESC2 ddsd;
5892 BOOL levelFound; /* at least one suitable sublevel in dest found */
5894 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5895 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5896 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5898 levelFound = FALSE;
5900 src_level = src;
5901 dest_level = dest;
5903 for (;src_level && dest_level;)
5905 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5906 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5908 levelFound = TRUE;
5910 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5911 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5912 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5914 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5916 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5919 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5920 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5921 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5923 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5925 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5928 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5929 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5931 return !dest_level && levelFound;
5934 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5935 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
5936 IDirectDrawSurfaceImpl *dest,
5937 IDirectDrawSurfaceImpl *src,
5938 const POINT *DestPoint,
5939 const RECT *SrcRect)
5941 IDirectDrawSurfaceImpl *src_level, *dest_level;
5942 IDirectDrawSurface7 *temp;
5943 DDSURFACEDESC2 ddsd;
5944 POINT point;
5945 RECT rect;
5946 HRESULT hr;
5947 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5948 DWORD ckeyflag;
5949 DDCOLORKEY ddckey;
5950 BOOL palette_missing = FALSE;
5952 /* Copy palette, if possible. */
5953 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
5954 IDirectDrawSurface7_GetPalette(&dest->IDirectDrawSurface7_iface, &pal);
5956 if (pal_src != NULL && pal != NULL)
5958 PALETTEENTRY palent[256];
5960 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5961 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5964 if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
5965 DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
5967 palette_missing = TRUE;
5970 if (pal) IDirectDrawPalette_Release(pal);
5971 if (pal_src) IDirectDrawPalette_Release(pal_src);
5973 /* Copy colorkeys, if present. */
5974 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5976 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5978 if (SUCCEEDED(hr))
5980 IDirectDrawSurface7_SetColorKey(&dest->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5984 src_level = src;
5985 dest_level = dest;
5987 point = *DestPoint;
5988 rect = *SrcRect;
5990 for (;src_level && dest_level;)
5992 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5993 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5995 /* Try UpdateSurface that may perform a more direct OpenGL
5996 * loading. But skip this if destination is paletted texture and
5997 * has no palette. Some games like Sacrifice set palette after
5998 * Load, and it is a waste of effort to try to load texture
5999 * without palette and generates warnings in wined3d. */
6000 if (!palette_missing)
6001 hr = wined3d_device_update_surface(device->wined3d_device, src_level->wined3d_surface,
6002 &rect, dest_level->wined3d_surface, &point);
6004 if (palette_missing || FAILED(hr))
6006 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
6007 wined3d_surface_bltfast(dest_level->wined3d_surface, point.x, point.y,
6008 src_level->wined3d_surface, &rect, 0);
6011 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6012 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6013 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6015 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6017 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6020 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6021 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6022 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6024 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6026 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6028 point.x /= 2;
6029 point.y /= 2;
6031 rect.top /= 2;
6032 rect.left /= 2;
6033 rect.right = (rect.right + 1) / 2;
6034 rect.bottom = (rect.bottom + 1) / 2;
6037 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6038 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6041 /*****************************************************************************
6042 * IDirect3DDevice7::Load
6044 * Loads a rectangular area from the source into the destination texture.
6045 * It can also copy the source to the faces of a cubic environment map
6047 * Version 7
6049 * Params:
6050 * DestTex: Destination texture
6051 * DestPoint: Point in the destination where the source image should be
6052 * written to
6053 * SrcTex: Source texture
6054 * SrcRect: Source rectangle
6055 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6056 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6057 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6059 * Returns:
6060 * D3D_OK on success
6061 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6064 *****************************************************************************/
6066 static HRESULT
6067 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6068 IDirectDrawSurface7 *DestTex,
6069 POINT *DestPoint,
6070 IDirectDrawSurface7 *SrcTex,
6071 RECT *SrcRect,
6072 DWORD Flags)
6074 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6075 IDirectDrawSurfaceImpl *dest = unsafe_impl_from_IDirectDrawSurface7(DestTex);
6076 IDirectDrawSurfaceImpl *src = unsafe_impl_from_IDirectDrawSurface7(SrcTex);
6077 POINT destpoint;
6078 RECT srcrect;
6080 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6081 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6083 if( (!src) || (!dest) )
6084 return DDERR_INVALIDPARAMS;
6086 EnterCriticalSection(&ddraw_cs);
6088 if (SrcRect) srcrect = *SrcRect;
6089 else
6091 srcrect.left = srcrect.top = 0;
6092 srcrect.right = src->surface_desc.dwWidth;
6093 srcrect.bottom = src->surface_desc.dwHeight;
6096 if (DestPoint) destpoint = *DestPoint;
6097 else
6099 destpoint.x = destpoint.y = 0;
6101 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6102 * destination can be a subset of mip levels, in which case actual coordinates used
6103 * for it may be divided. If any dimension of dest is larger than source, it can't be
6104 * mip level subset, so an error can be returned early.
6106 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6107 srcrect.right > src->surface_desc.dwWidth ||
6108 srcrect.bottom > src->surface_desc.dwHeight ||
6109 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6110 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6111 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6112 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6114 LeaveCriticalSection(&ddraw_cs);
6115 return DDERR_INVALIDPARAMS;
6118 /* Must be top level surfaces. */
6119 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6120 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6122 LeaveCriticalSection(&ddraw_cs);
6123 return DDERR_INVALIDPARAMS;
6126 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6128 DWORD src_face_flag, dest_face_flag;
6129 IDirectDrawSurfaceImpl *src_face, *dest_face;
6130 IDirectDrawSurface7 *temp;
6131 DDSURFACEDESC2 ddsd;
6132 int i;
6134 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6136 LeaveCriticalSection(&ddraw_cs);
6137 return DDERR_INVALIDPARAMS;
6140 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6141 * time it's actual surface loading. */
6142 for (i = 0; i < 2; i++)
6144 dest_face = dest;
6145 src_face = src;
6147 for (;dest_face && src_face;)
6149 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6150 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6152 if (src_face_flag == dest_face_flag)
6154 if (i == 0)
6156 /* Destination mip levels must be subset of source mip levels. */
6157 if (!is_mip_level_subset(dest_face, src_face))
6159 LeaveCriticalSection(&ddraw_cs);
6160 return DDERR_INVALIDPARAMS;
6163 else if (Flags & dest_face_flag)
6165 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6168 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6170 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6171 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6172 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6174 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6176 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6178 else
6180 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6182 src_face = NULL;
6186 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6188 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6189 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6190 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6192 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6194 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6196 else
6198 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6200 dest_face = NULL;
6204 if (i == 0)
6206 /* Native returns error if src faces are not subset of dest faces. */
6207 if (src_face)
6209 LeaveCriticalSection(&ddraw_cs);
6210 return DDERR_INVALIDPARAMS;
6215 LeaveCriticalSection(&ddraw_cs);
6216 return D3D_OK;
6218 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6220 LeaveCriticalSection(&ddraw_cs);
6221 return DDERR_INVALIDPARAMS;
6224 /* Handle non cube map textures. */
6226 /* Destination mip levels must be subset of source mip levels. */
6227 if (!is_mip_level_subset(dest, src))
6229 LeaveCriticalSection(&ddraw_cs);
6230 return DDERR_INVALIDPARAMS;
6233 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6235 LeaveCriticalSection(&ddraw_cs);
6236 return D3D_OK;
6239 static HRESULT WINAPI
6240 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6241 IDirectDrawSurface7 *DestTex,
6242 POINT *DestPoint,
6243 IDirectDrawSurface7 *SrcTex,
6244 RECT *SrcRect,
6245 DWORD Flags)
6247 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6250 static HRESULT WINAPI
6251 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6252 IDirectDrawSurface7 *DestTex,
6253 POINT *DestPoint,
6254 IDirectDrawSurface7 *SrcTex,
6255 RECT *SrcRect,
6256 DWORD Flags)
6258 HRESULT hr;
6259 WORD old_fpucw;
6261 old_fpucw = d3d_fpu_setup();
6262 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6263 set_fpu_control_word(old_fpucw);
6265 return hr;
6268 /*****************************************************************************
6269 * IDirect3DDevice7::LightEnable
6271 * Enables or disables a light
6273 * Version 7, IDirect3DLight uses this method too.
6275 * Params:
6276 * LightIndex: The index of the light to enable / disable
6277 * Enable: Enable or disable the light
6279 * Returns:
6280 * D3D_OK on success
6281 * For more details, see IWineD3DDevice::SetLightEnable
6283 *****************************************************************************/
6284 static HRESULT
6285 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6286 DWORD LightIndex,
6287 BOOL Enable)
6289 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6290 HRESULT hr;
6292 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6294 EnterCriticalSection(&ddraw_cs);
6295 hr = wined3d_device_set_light_enable(This->wined3d_device, LightIndex, Enable);
6296 LeaveCriticalSection(&ddraw_cs);
6297 return hr_ddraw_from_wined3d(hr);
6300 static HRESULT WINAPI
6301 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6302 DWORD LightIndex,
6303 BOOL Enable)
6305 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6308 static HRESULT WINAPI
6309 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6310 DWORD LightIndex,
6311 BOOL Enable)
6313 HRESULT hr;
6314 WORD old_fpucw;
6316 old_fpucw = d3d_fpu_setup();
6317 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6318 set_fpu_control_word(old_fpucw);
6320 return hr;
6323 /*****************************************************************************
6324 * IDirect3DDevice7::GetLightEnable
6326 * Retrieves if the light with the given index is enabled or not
6328 * Version 7
6330 * Params:
6331 * LightIndex: Index of desired light
6332 * Enable: Pointer to a BOOL which contains the result
6334 * Returns:
6335 * D3D_OK on success
6336 * DDERR_INVALIDPARAMS if Enable is NULL
6337 * See IWineD3DDevice::GetLightEnable for more details
6339 *****************************************************************************/
6340 static HRESULT
6341 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6342 DWORD LightIndex,
6343 BOOL* Enable)
6345 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6346 HRESULT hr;
6348 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6350 if(!Enable)
6351 return DDERR_INVALIDPARAMS;
6353 EnterCriticalSection(&ddraw_cs);
6354 hr = wined3d_device_get_light_enable(This->wined3d_device, LightIndex, Enable);
6355 LeaveCriticalSection(&ddraw_cs);
6356 return hr_ddraw_from_wined3d(hr);
6359 static HRESULT WINAPI
6360 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6361 DWORD LightIndex,
6362 BOOL* Enable)
6364 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6367 static HRESULT WINAPI
6368 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6369 DWORD LightIndex,
6370 BOOL* Enable)
6372 HRESULT hr;
6373 WORD old_fpucw;
6375 old_fpucw = d3d_fpu_setup();
6376 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6377 set_fpu_control_word(old_fpucw);
6379 return hr;
6382 /*****************************************************************************
6383 * IDirect3DDevice7::SetClipPlane
6385 * Sets custom clipping plane
6387 * Version 7
6389 * Params:
6390 * Index: The index of the clipping plane
6391 * PlaneEquation: An equation defining the clipping plane
6393 * Returns:
6394 * D3D_OK on success
6395 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6396 * See IWineD3DDevice::SetClipPlane for more details
6398 *****************************************************************************/
6399 static HRESULT
6400 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6401 DWORD Index,
6402 D3DVALUE* PlaneEquation)
6404 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6405 HRESULT hr;
6407 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6409 if(!PlaneEquation)
6410 return DDERR_INVALIDPARAMS;
6412 EnterCriticalSection(&ddraw_cs);
6413 hr = wined3d_device_set_clip_plane(This->wined3d_device, Index, PlaneEquation);
6414 LeaveCriticalSection(&ddraw_cs);
6415 return hr;
6418 static HRESULT WINAPI
6419 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6420 DWORD Index,
6421 D3DVALUE* PlaneEquation)
6423 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6426 static HRESULT WINAPI
6427 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6428 DWORD Index,
6429 D3DVALUE* PlaneEquation)
6431 HRESULT hr;
6432 WORD old_fpucw;
6434 old_fpucw = d3d_fpu_setup();
6435 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6436 set_fpu_control_word(old_fpucw);
6438 return hr;
6441 /*****************************************************************************
6442 * IDirect3DDevice7::GetClipPlane
6444 * Returns the clipping plane with a specific index
6446 * Params:
6447 * Index: The index of the desired plane
6448 * PlaneEquation: Address to store the plane equation to
6450 * Returns:
6451 * D3D_OK on success
6452 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6453 * See IWineD3DDevice::GetClipPlane for more details
6455 *****************************************************************************/
6456 static HRESULT
6457 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6458 DWORD Index,
6459 D3DVALUE* PlaneEquation)
6461 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6462 HRESULT hr;
6464 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6466 if(!PlaneEquation)
6467 return DDERR_INVALIDPARAMS;
6469 EnterCriticalSection(&ddraw_cs);
6470 hr = wined3d_device_get_clip_plane(This->wined3d_device, Index, PlaneEquation);
6471 LeaveCriticalSection(&ddraw_cs);
6472 return hr;
6475 static HRESULT WINAPI
6476 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6477 DWORD Index,
6478 D3DVALUE* PlaneEquation)
6480 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6483 static HRESULT WINAPI
6484 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6485 DWORD Index,
6486 D3DVALUE* PlaneEquation)
6488 HRESULT hr;
6489 WORD old_fpucw;
6491 old_fpucw = d3d_fpu_setup();
6492 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6493 set_fpu_control_word(old_fpucw);
6495 return hr;
6498 /*****************************************************************************
6499 * IDirect3DDevice7::GetInfo
6501 * Retrieves some information about the device. The DirectX sdk says that
6502 * this version returns S_FALSE for all retail builds of DirectX, that's what
6503 * this implementation does.
6505 * Params:
6506 * DevInfoID: Information type requested
6507 * DevInfoStruct: Pointer to a structure to store the info to
6508 * Size: Size of the structure
6510 * Returns:
6511 * S_FALSE, because it's a non-debug driver
6513 *****************************************************************************/
6514 static HRESULT WINAPI
6515 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6516 DWORD DevInfoID,
6517 void *DevInfoStruct,
6518 DWORD Size)
6520 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6521 iface, DevInfoID, DevInfoStruct, Size);
6523 if (TRACE_ON(ddraw))
6525 TRACE(" info requested : ");
6526 switch (DevInfoID)
6528 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6529 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6530 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6531 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6535 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6538 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6539 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6540 * are not duplicated.
6542 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6543 * has already been setup for optimal d3d operation.
6545 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6546 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6547 * by Sacrifice (game). */
6548 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6550 /*** IUnknown Methods ***/
6551 IDirect3DDeviceImpl_7_QueryInterface,
6552 IDirect3DDeviceImpl_7_AddRef,
6553 IDirect3DDeviceImpl_7_Release,
6554 /*** IDirect3DDevice7 ***/
6555 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6556 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6557 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6558 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6559 IDirect3DDeviceImpl_7_GetDirect3D,
6560 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6561 IDirect3DDeviceImpl_7_GetRenderTarget,
6562 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6563 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6564 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6565 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6566 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6567 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6568 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6569 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6570 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6571 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6572 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6573 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6574 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6575 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6576 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6577 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6578 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6579 IDirect3DDeviceImpl_7_SetClipStatus,
6580 IDirect3DDeviceImpl_7_GetClipStatus,
6581 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6582 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6583 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6584 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6585 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6586 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6587 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6588 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6589 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6590 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6591 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6592 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6593 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6594 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6595 IDirect3DDeviceImpl_7_Load_FPUSetup,
6596 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6597 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6598 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6599 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6600 IDirect3DDeviceImpl_7_GetInfo
6603 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6605 /*** IUnknown Methods ***/
6606 IDirect3DDeviceImpl_7_QueryInterface,
6607 IDirect3DDeviceImpl_7_AddRef,
6608 IDirect3DDeviceImpl_7_Release,
6609 /*** IDirect3DDevice7 ***/
6610 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6611 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6612 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6613 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6614 IDirect3DDeviceImpl_7_GetDirect3D,
6615 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6616 IDirect3DDeviceImpl_7_GetRenderTarget,
6617 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6618 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6619 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6620 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6621 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6622 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6623 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6624 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6625 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6626 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6627 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6628 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6629 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6630 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6631 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6632 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6633 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6634 IDirect3DDeviceImpl_7_SetClipStatus,
6635 IDirect3DDeviceImpl_7_GetClipStatus,
6636 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6637 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6638 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6639 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6640 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6641 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6642 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6643 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6644 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6645 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6646 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6647 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6648 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6649 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6650 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6651 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6652 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6653 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6654 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6655 IDirect3DDeviceImpl_7_GetInfo
6658 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6660 /*** IUnknown Methods ***/
6661 IDirect3DDeviceImpl_3_QueryInterface,
6662 IDirect3DDeviceImpl_3_AddRef,
6663 IDirect3DDeviceImpl_3_Release,
6664 /*** IDirect3DDevice3 ***/
6665 IDirect3DDeviceImpl_3_GetCaps,
6666 IDirect3DDeviceImpl_3_GetStats,
6667 IDirect3DDeviceImpl_3_AddViewport,
6668 IDirect3DDeviceImpl_3_DeleteViewport,
6669 IDirect3DDeviceImpl_3_NextViewport,
6670 IDirect3DDeviceImpl_3_EnumTextureFormats,
6671 IDirect3DDeviceImpl_3_BeginScene,
6672 IDirect3DDeviceImpl_3_EndScene,
6673 IDirect3DDeviceImpl_3_GetDirect3D,
6674 IDirect3DDeviceImpl_3_SetCurrentViewport,
6675 IDirect3DDeviceImpl_3_GetCurrentViewport,
6676 IDirect3DDeviceImpl_3_SetRenderTarget,
6677 IDirect3DDeviceImpl_3_GetRenderTarget,
6678 IDirect3DDeviceImpl_3_Begin,
6679 IDirect3DDeviceImpl_3_BeginIndexed,
6680 IDirect3DDeviceImpl_3_Vertex,
6681 IDirect3DDeviceImpl_3_Index,
6682 IDirect3DDeviceImpl_3_End,
6683 IDirect3DDeviceImpl_3_GetRenderState,
6684 IDirect3DDeviceImpl_3_SetRenderState,
6685 IDirect3DDeviceImpl_3_GetLightState,
6686 IDirect3DDeviceImpl_3_SetLightState,
6687 IDirect3DDeviceImpl_3_SetTransform,
6688 IDirect3DDeviceImpl_3_GetTransform,
6689 IDirect3DDeviceImpl_3_MultiplyTransform,
6690 IDirect3DDeviceImpl_3_DrawPrimitive,
6691 IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6692 IDirect3DDeviceImpl_3_SetClipStatus,
6693 IDirect3DDeviceImpl_3_GetClipStatus,
6694 IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6695 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6696 IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6697 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6698 IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6699 IDirect3DDeviceImpl_3_GetTexture,
6700 IDirect3DDeviceImpl_3_SetTexture,
6701 IDirect3DDeviceImpl_3_GetTextureStageState,
6702 IDirect3DDeviceImpl_3_SetTextureStageState,
6703 IDirect3DDeviceImpl_3_ValidateDevice
6706 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6708 /*** IUnknown Methods ***/
6709 IDirect3DDeviceImpl_2_QueryInterface,
6710 IDirect3DDeviceImpl_2_AddRef,
6711 IDirect3DDeviceImpl_2_Release,
6712 /*** IDirect3DDevice2 ***/
6713 IDirect3DDeviceImpl_2_GetCaps,
6714 IDirect3DDeviceImpl_2_SwapTextureHandles,
6715 IDirect3DDeviceImpl_2_GetStats,
6716 IDirect3DDeviceImpl_2_AddViewport,
6717 IDirect3DDeviceImpl_2_DeleteViewport,
6718 IDirect3DDeviceImpl_2_NextViewport,
6719 IDirect3DDeviceImpl_2_EnumTextureFormats,
6720 IDirect3DDeviceImpl_2_BeginScene,
6721 IDirect3DDeviceImpl_2_EndScene,
6722 IDirect3DDeviceImpl_2_GetDirect3D,
6723 IDirect3DDeviceImpl_2_SetCurrentViewport,
6724 IDirect3DDeviceImpl_2_GetCurrentViewport,
6725 IDirect3DDeviceImpl_2_SetRenderTarget,
6726 IDirect3DDeviceImpl_2_GetRenderTarget,
6727 IDirect3DDeviceImpl_2_Begin,
6728 IDirect3DDeviceImpl_2_BeginIndexed,
6729 IDirect3DDeviceImpl_2_Vertex,
6730 IDirect3DDeviceImpl_2_Index,
6731 IDirect3DDeviceImpl_2_End,
6732 IDirect3DDeviceImpl_2_GetRenderState,
6733 IDirect3DDeviceImpl_2_SetRenderState,
6734 IDirect3DDeviceImpl_2_GetLightState,
6735 IDirect3DDeviceImpl_2_SetLightState,
6736 IDirect3DDeviceImpl_2_SetTransform,
6737 IDirect3DDeviceImpl_2_GetTransform,
6738 IDirect3DDeviceImpl_2_MultiplyTransform,
6739 IDirect3DDeviceImpl_2_DrawPrimitive,
6740 IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6741 IDirect3DDeviceImpl_2_SetClipStatus,
6742 IDirect3DDeviceImpl_2_GetClipStatus
6745 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6747 /*** IUnknown Methods ***/
6748 IDirect3DDeviceImpl_1_QueryInterface,
6749 IDirect3DDeviceImpl_1_AddRef,
6750 IDirect3DDeviceImpl_1_Release,
6751 /*** IDirect3DDevice1 ***/
6752 IDirect3DDeviceImpl_1_Initialize,
6753 IDirect3DDeviceImpl_1_GetCaps,
6754 IDirect3DDeviceImpl_1_SwapTextureHandles,
6755 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6756 IDirect3DDeviceImpl_1_GetStats,
6757 IDirect3DDeviceImpl_1_Execute,
6758 IDirect3DDeviceImpl_1_AddViewport,
6759 IDirect3DDeviceImpl_1_DeleteViewport,
6760 IDirect3DDeviceImpl_1_NextViewport,
6761 IDirect3DDeviceImpl_1_Pick,
6762 IDirect3DDeviceImpl_1_GetPickRecords,
6763 IDirect3DDeviceImpl_1_EnumTextureFormats,
6764 IDirect3DDeviceImpl_1_CreateMatrix,
6765 IDirect3DDeviceImpl_1_SetMatrix,
6766 IDirect3DDeviceImpl_1_GetMatrix,
6767 IDirect3DDeviceImpl_1_DeleteMatrix,
6768 IDirect3DDeviceImpl_1_BeginScene,
6769 IDirect3DDeviceImpl_1_EndScene,
6770 IDirect3DDeviceImpl_1_GetDirect3D
6773 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6775 if (!iface) return NULL;
6776 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6777 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, lpVtbl);
6780 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6782 if (!iface) return NULL;
6783 assert(iface->lpVtbl == &d3d_device3_vtbl);
6784 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice3_iface);
6787 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6789 if (!iface) return NULL;
6790 assert(iface->lpVtbl == &d3d_device2_vtbl);
6791 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice2_iface);
6794 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6796 if (!iface) return NULL;
6797 assert(iface->lpVtbl == &d3d_device1_vtbl);
6798 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice_iface);
6801 /*****************************************************************************
6802 * IDirect3DDeviceImpl_UpdateDepthStencil
6804 * Checks the current render target for attached depth stencils and sets the
6805 * WineD3D depth stencil accordingly.
6807 * Returns:
6808 * The depth stencil state to set if creating the device
6810 *****************************************************************************/
6811 WINED3DZBUFFERTYPE
6812 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6814 IDirectDrawSurface7 *depthStencil = NULL;
6815 IDirectDrawSurfaceImpl *dsi;
6816 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6818 IDirectDrawSurface7_GetAttachedSurface(&This->target->IDirectDrawSurface7_iface, &depthcaps, &depthStencil);
6819 if(!depthStencil)
6821 TRACE("Setting wined3d depth stencil to NULL\n");
6822 wined3d_device_set_depth_stencil(This->wined3d_device, NULL);
6823 return WINED3DZB_FALSE;
6826 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6827 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
6828 wined3d_device_set_depth_stencil(This->wined3d_device, dsi->wined3d_surface);
6830 IDirectDrawSurface7_Release(depthStencil);
6831 return WINED3DZB_TRUE;
6834 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
6836 HRESULT hr;
6838 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6839 device->lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6840 else
6841 device->lpVtbl = &d3d_device7_fpu_setup_vtbl;
6843 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6844 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6845 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6846 device->ref = 1;
6847 device->ddraw = ddraw;
6848 device->target = target;
6849 list_init(&device->viewport_list);
6851 if (!ddraw_handle_table_init(&device->handle_table, 64))
6853 ERR("Failed to initialize handle table.\n");
6854 return DDERR_OUTOFMEMORY;
6857 device->legacyTextureBlending = FALSE;
6859 /* Create an index buffer, it's needed for indexed drawing */
6860 hr = wined3d_buffer_create_ib(ddraw->wined3d_device, 0x40000 /* Length. Don't know how long it should be */,
6861 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, NULL,
6862 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
6863 if (FAILED(hr))
6865 ERR("Failed to create an index buffer, hr %#x.\n", hr);
6866 ddraw_handle_table_destroy(&device->handle_table);
6867 return hr;
6870 /* This is for convenience. */
6871 device->wined3d_device = ddraw->wined3d_device;
6872 wined3d_device_incref(ddraw->wined3d_device);
6874 /* Render to the back buffer */
6875 hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
6876 if (FAILED(hr))
6878 ERR("Failed to set render target, hr %#x.\n", hr);
6879 wined3d_buffer_decref(device->indexbuffer);
6880 ddraw_handle_table_destroy(&device->handle_table);
6881 return hr;
6884 /* FIXME: This is broken. The target AddRef() makes some sense, because
6885 * we store a pointer during initialization, but then that's also where
6886 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6887 /* AddRef the render target. Also AddRef the render target from ddraw,
6888 * because if it is released before the app releases the D3D device, the
6889 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6891 * In most cases, those surfaces are the same anyway, but this will simply
6892 * add another ref which is released when the device is destroyed. */
6893 IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
6894 IDirectDrawSurface7_AddRef(&ddraw->d3d_target->IDirectDrawSurface7_iface);
6896 ddraw->d3ddevice = device;
6898 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3DRS_ZENABLE,
6899 IDirect3DDeviceImpl_UpdateDepthStencil(device));
6901 return D3D_OK;