shdocvw/tests: Avoid using a freed IUniformResourceLocatorA variable.
[wine.git] / dlls / ddraw / device.c
bloba7eb2ddabcaf6ff332fee1114d6cfff578400087
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 Interfac\x01s */
120 else if( IsEqualGUID( &IID_IDirectDraw7, refiid ) )
122 *obj = This->ddraw;
123 TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
125 else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
127 *obj = &This->ddraw->IDirectDraw4_vtbl;
128 TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
130 else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
132 *obj = &This->ddraw->IDirectDraw2_vtbl;
133 TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
135 else if( IsEqualGUID( &IID_IDirectDraw, refiid ) )
137 *obj = &This->ddraw->IDirectDraw_vtbl;
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_vtbl;
145 TRACE("(%p) Returning IDirect3D interface at %p\n", This, *obj);
147 else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) )
149 *obj = &This->ddraw->IDirect3D2_vtbl;
150 TRACE("(%p) Returning IDirect3D2 interface at %p\n", This, *obj);
152 else if ( IsEqualGUID( &IID_IDirect3D3 , refiid ) )
154 *obj = &This->ddraw->IDirect3D3_vtbl;
155 TRACE("(%p) Returning IDirect3D3 interface at %p\n", This, *obj);
157 else if ( IsEqualGUID( &IID_IDirect3D7 , refiid ) )
159 *obj = &This->ddraw->IDirect3D7_vtbl;
160 TRACE("(%p) Returning IDirect3D7 interface at %p\n", This, *obj);
163 /* Direct3DDevice */
164 else if ( IsEqualGUID( &IID_IDirect3DDevice , refiid ) )
166 *obj = &This->IDirect3DDevice_vtbl;
167 TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
169 else if ( IsEqualGUID( &IID_IDirect3DDevice2 , refiid ) ) {
170 *obj = &This->IDirect3DDevice2_vtbl;
171 TRACE("(%p) Returning IDirect3DDevice2 interface at %p\n", This, *obj);
173 else if ( IsEqualGUID( &IID_IDirect3DDevice3 , refiid ) ) {
174 *obj = &This->IDirect3DDevice3_vtbl;
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
195 Thunk_IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface,
196 REFIID riid,
197 void **obj)
199 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
201 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device3(iface), riid, obj);
204 static HRESULT WINAPI
205 Thunk_IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface,
206 REFIID riid,
207 void **obj)
209 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
211 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device2(iface), riid, obj);
214 static HRESULT WINAPI
215 Thunk_IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface,
216 REFIID riid,
217 void **obp)
219 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
221 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device1(iface), riid, obp);
224 /*****************************************************************************
225 * IDirect3DDevice7::AddRef
227 * Increases the refcount....
228 * The most exciting Method, definitely
230 * Exists in Version 1, 2, 3 and 7
232 * Returns:
233 * The new refcount
235 *****************************************************************************/
236 static ULONG WINAPI
237 IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
239 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
240 ULONG ref = InterlockedIncrement(&This->ref);
242 TRACE("%p increasing refcount to %u.\n", This, ref);
244 return ref;
247 static ULONG WINAPI
248 Thunk_IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
250 TRACE("iface %p.\n", iface);
252 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device3(iface));
255 static ULONG WINAPI
256 Thunk_IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
258 TRACE("iface %p.\n", iface);
260 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device2(iface));
263 static ULONG WINAPI
264 Thunk_IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
266 TRACE("iface %p.\n", iface);
268 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device1(iface));
271 /*****************************************************************************
272 * IDirect3DDevice7::Release
274 * Decreases the refcount of the interface
275 * When the refcount is reduced to 0, the object is destroyed.
277 * Exists in Version 1, 2, 3 and 7
279 * Returns:d
280 * The new refcount
282 *****************************************************************************/
283 static ULONG WINAPI
284 IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
286 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
287 ULONG ref = InterlockedDecrement(&This->ref);
289 TRACE("%p decreasing refcount to %u.\n", This, ref);
291 /* This method doesn't destroy the WineD3DDevice, because it's still in use for
292 * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
293 * when the render target is released
295 if (ref == 0)
297 IParent *IndexBufferParent;
298 DWORD i;
300 EnterCriticalSection(&ddraw_cs);
301 /* Free the index buffer. */
302 IWineD3DDevice_SetIndexBuffer(This->wineD3DDevice, NULL, WINED3DFMT_UNKNOWN);
303 IndexBufferParent = IWineD3DBuffer_GetParent(This->indexbuffer);
304 if (IParent_Release(IndexBufferParent))
306 ERR(" (%p) Something is still holding the index buffer parent %p\n", This, IndexBufferParent);
309 /* There is no need to unset the vertex buffer here, IWineD3DDevice_Uninit3D will do that when
310 * destroying the primary stateblock. If a vertex buffer is destroyed while it is bound
311 * IDirect3DVertexBuffer::Release will unset it.
314 /* Set the device up to render to the front buffer since the back
315 * buffer will vanish soon. */
316 IWineD3DDevice_SetRenderTarget(This->wineD3DDevice, 0,
317 This->ddraw->d3d_target->WineD3DSurface, TRUE);
319 /* Release the WineD3DDevice. This won't destroy it */
320 if(IWineD3DDevice_Release(This->wineD3DDevice) <= 0)
322 ERR(" (%p) The wineD3D device %p was destroyed unexpectedly. Prepare for trouble\n", This, This->wineD3DDevice);
325 /* The texture handles should be unset by now, but there might be some bits
326 * missing in our reference counting(needs test). Do a sanity check. */
327 for (i = 0; i < This->handle_table.entry_count; ++i)
329 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
331 switch (entry->type)
333 case DDRAW_HANDLE_FREE:
334 break;
336 case DDRAW_HANDLE_MATERIAL:
338 IDirect3DMaterialImpl *m = entry->object;
339 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
340 m->Handle = 0;
341 break;
344 case DDRAW_HANDLE_MATRIX:
346 /* No FIXME here because this might happen because of sloppy applications. */
347 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
348 IDirect3DDevice_DeleteMatrix((IDirect3DDevice *)&This->IDirect3DDevice_vtbl, i + 1);
349 break;
352 case DDRAW_HANDLE_STATEBLOCK:
354 /* No FIXME here because this might happen because of sloppy applications. */
355 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
356 IDirect3DDevice7_DeleteStateBlock(iface, i + 1);
357 break;
360 case DDRAW_HANDLE_SURFACE:
362 IDirectDrawSurfaceImpl *surf = entry->object;
363 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
364 surf->Handle = 0;
365 break;
368 default:
369 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
370 break;
374 ddraw_handle_table_destroy(&This->handle_table);
376 TRACE("Releasing target %p %p\n", This->target, This->ddraw->d3d_target);
377 /* Release the render target and the WineD3D render target
378 * (See IDirect3D7::CreateDevice for more comments on this)
380 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->target);
381 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->ddraw->d3d_target);
382 TRACE("Target release done\n");
384 This->ddraw->d3ddevice = NULL;
386 /* Now free the structure */
387 HeapFree(GetProcessHeap(), 0, This);
388 LeaveCriticalSection(&ddraw_cs);
391 TRACE("Done\n");
392 return ref;
395 static ULONG WINAPI
396 Thunk_IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
398 TRACE("iface %p.\n", iface);
400 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device3(iface));
403 static ULONG WINAPI
404 Thunk_IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
406 TRACE("iface %p.\n", iface);
408 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device2(iface));
411 static ULONG WINAPI
412 Thunk_IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
414 TRACE("iface %p.\n", iface);
416 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device1(iface));
419 /*****************************************************************************
420 * IDirect3DDevice Methods
421 *****************************************************************************/
423 /*****************************************************************************
424 * IDirect3DDevice::Initialize
426 * Initializes a Direct3DDevice. This implementation is a no-op, as all
427 * initialization is done at create time.
429 * Exists in Version 1
431 * Parameters:
432 * No idea what they mean, as the MSDN page is gone
434 * Returns: DD_OK
436 *****************************************************************************/
437 static HRESULT WINAPI
438 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
439 IDirect3D *Direct3D, GUID *guid,
440 D3DDEVICEDESC *Desc)
442 /* It shouldn't be crucial, but print a FIXME, I'm interested if
443 * any game calls it and when. */
444 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
445 iface, Direct3D, debugstr_guid(guid), Desc);
447 return D3D_OK;
450 /*****************************************************************************
451 * IDirect3DDevice7::GetCaps
453 * Retrieves the device's capabilities
455 * This implementation is used for Version 7 only, the older versions have
456 * their own implementation.
458 * Parameters:
459 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
461 * Returns:
462 * D3D_OK on success
463 * D3DERR_* if a problem occurs. See WineD3D
465 *****************************************************************************/
466 static HRESULT
467 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
468 D3DDEVICEDESC7 *Desc)
470 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
471 D3DDEVICEDESC OldDesc;
473 TRACE("iface %p, device_desc %p.\n", iface, Desc);
475 /* Call the same function used by IDirect3D, this saves code */
476 return IDirect3DImpl_GetCaps(This->ddraw->wineD3D, &OldDesc, Desc);
479 static HRESULT WINAPI
480 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
481 D3DDEVICEDESC7 *Desc)
483 return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
486 static HRESULT WINAPI
487 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
488 D3DDEVICEDESC7 *Desc)
490 HRESULT hr;
491 WORD old_fpucw;
493 old_fpucw = d3d_fpu_setup();
494 hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
495 set_fpu_control_word(old_fpucw);
497 return hr;
499 /*****************************************************************************
500 * IDirect3DDevice3::GetCaps
502 * Retrieves the capabilities of the hardware device and the emulation
503 * device. For Wine, hardware and emulation are the same (it's all HW).
505 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
507 * Parameters:
508 * HWDesc: Structure to fill with the HW caps
509 * HelDesc: Structure to fill with the hardware emulation caps
511 * Returns:
512 * D3D_OK on success
513 * D3DERR_* if a problem occurs. See WineD3D
515 *****************************************************************************/
516 static HRESULT WINAPI
517 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
518 D3DDEVICEDESC *HWDesc,
519 D3DDEVICEDESC *HelDesc)
521 IDirect3DDeviceImpl *This = device_from_device3(iface);
522 D3DDEVICEDESC7 newDesc;
523 HRESULT hr;
525 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
527 hr = IDirect3DImpl_GetCaps(This->ddraw->wineD3D, HWDesc, &newDesc);
528 if(hr != D3D_OK) return hr;
530 *HelDesc = *HWDesc;
531 return D3D_OK;
534 static HRESULT WINAPI
535 Thunk_IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
536 D3DDEVICEDESC *D3DHWDevDesc,
537 D3DDEVICEDESC *D3DHELDevDesc)
539 IDirect3DDeviceImpl *This = device_from_device2(iface);
540 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
541 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
544 static HRESULT WINAPI
545 Thunk_IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
546 D3DDEVICEDESC *D3DHWDevDesc,
547 D3DDEVICEDESC *D3DHELDevDesc)
549 IDirect3DDeviceImpl *This = device_from_device1(iface);
550 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
551 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
554 /*****************************************************************************
555 * IDirect3DDevice2::SwapTextureHandles
557 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
559 * Parameters:
560 * Tex1, Tex2: The 2 Textures to swap
562 * Returns:
563 * D3D_OK
565 *****************************************************************************/
566 static HRESULT WINAPI
567 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
568 IDirect3DTexture2 *Tex1,
569 IDirect3DTexture2 *Tex2)
571 IDirect3DDeviceImpl *This = device_from_device2(iface);
572 IDirectDrawSurfaceImpl *surf1 = surface_from_texture2(Tex1);
573 IDirectDrawSurfaceImpl *surf2 = surface_from_texture2(Tex2);
574 DWORD h1, h2;
576 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, Tex1, Tex2);
578 EnterCriticalSection(&ddraw_cs);
580 h1 = surf1->Handle - 1;
581 h2 = surf2->Handle - 1;
582 This->handle_table.entries[h1].object = surf2;
583 This->handle_table.entries[h2].object = surf1;
584 surf2->Handle = h1 + 1;
585 surf1->Handle = h2 + 1;
587 LeaveCriticalSection(&ddraw_cs);
589 return D3D_OK;
592 static HRESULT WINAPI
593 Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
594 IDirect3DTexture *D3DTex1,
595 IDirect3DTexture *D3DTex2)
597 IDirect3DDeviceImpl *This = device_from_device1(iface);
598 IDirectDrawSurfaceImpl *surf1 = surface_from_texture1(D3DTex1);
599 IDirectDrawSurfaceImpl *surf2 = surface_from_texture1(D3DTex2);
600 IDirect3DTexture2 *t1 = surf1 ? (IDirect3DTexture2 *)&surf1->IDirect3DTexture2_vtbl : NULL;
601 IDirect3DTexture2 *t2 = surf2 ? (IDirect3DTexture2 *)&surf2->IDirect3DTexture2_vtbl : NULL;
603 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, D3DTex1, D3DTex2);
605 return IDirect3DDevice2_SwapTextureHandles((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, t1, t2);
608 /*****************************************************************************
609 * IDirect3DDevice3::GetStats
611 * This method seems to retrieve some stats from the device.
612 * The MSDN documentation doesn't exist any more, but the D3DSTATS
613 * structure suggests that the amount of drawn primitives and processed
614 * vertices is returned.
616 * Exists in Version 1, 2 and 3
618 * Parameters:
619 * Stats: Pointer to a D3DSTATS structure to be filled
621 * Returns:
622 * D3D_OK on success
623 * DDERR_INVALIDPARAMS if Stats == NULL
625 *****************************************************************************/
626 static HRESULT WINAPI
627 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
628 D3DSTATS *Stats)
630 FIXME("iface %p, stats %p stub!\n", iface, Stats);
632 if(!Stats)
633 return DDERR_INVALIDPARAMS;
635 /* Fill the Stats with 0 */
636 Stats->dwTrianglesDrawn = 0;
637 Stats->dwLinesDrawn = 0;
638 Stats->dwPointsDrawn = 0;
639 Stats->dwSpansDrawn = 0;
640 Stats->dwVerticesProcessed = 0;
642 return D3D_OK;
645 static HRESULT WINAPI
646 Thunk_IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface,
647 D3DSTATS *Stats)
649 IDirect3DDeviceImpl *This = device_from_device2(iface);
651 TRACE("iface %p, stats %p.\n", iface, Stats);
653 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
656 static HRESULT WINAPI
657 Thunk_IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface,
658 D3DSTATS *Stats)
660 IDirect3DDeviceImpl *This = device_from_device1(iface);
662 TRACE("iface %p, stats %p.\n", iface, Stats);
664 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
667 /*****************************************************************************
668 * IDirect3DDevice::CreateExecuteBuffer
670 * Creates an IDirect3DExecuteBuffer, used for rendering with a
671 * Direct3DDevice.
673 * Version 1 only.
675 * Params:
676 * Desc: Buffer description
677 * ExecuteBuffer: Address to return the Interface pointer at
678 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
679 * support
681 * Returns:
682 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
683 * DDERR_OUTOFMEMORY if we ran out of memory
684 * D3D_OK on success
686 *****************************************************************************/
687 static HRESULT WINAPI
688 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
689 D3DEXECUTEBUFFERDESC *Desc,
690 IDirect3DExecuteBuffer **ExecuteBuffer,
691 IUnknown *UnkOuter)
693 IDirect3DDeviceImpl *This = device_from_device1(iface);
694 IDirect3DExecuteBufferImpl* object;
695 HRESULT hr;
697 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
698 iface, Desc, ExecuteBuffer, UnkOuter);
700 if(UnkOuter)
701 return CLASS_E_NOAGGREGATION;
703 /* Allocate the new Execute Buffer */
704 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
705 if(!object)
707 ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
708 return DDERR_OUTOFMEMORY;
711 hr = d3d_execute_buffer_init(object, This, Desc);
712 if (FAILED(hr))
714 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
715 HeapFree(GetProcessHeap(), 0, object);
716 return hr;
719 *ExecuteBuffer = (IDirect3DExecuteBuffer *)object;
721 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
723 return D3D_OK;
726 /*****************************************************************************
727 * IDirect3DDevice::Execute
729 * Executes all the stuff in an execute buffer.
731 * Params:
732 * ExecuteBuffer: The buffer to execute
733 * Viewport: The viewport used for rendering
734 * Flags: Some flags
736 * Returns:
737 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
738 * D3D_OK on success
740 *****************************************************************************/
741 static HRESULT WINAPI
742 IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
743 IDirect3DExecuteBuffer *ExecuteBuffer,
744 IDirect3DViewport *Viewport,
745 DWORD Flags)
747 IDirect3DDeviceImpl *This = device_from_device1(iface);
748 IDirect3DExecuteBufferImpl *Direct3DExecuteBufferImpl = (IDirect3DExecuteBufferImpl *)ExecuteBuffer;
749 IDirect3DViewportImpl *Direct3DViewportImpl = (IDirect3DViewportImpl *)Viewport;
751 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, Viewport, Flags);
753 if(!Direct3DExecuteBufferImpl)
754 return DDERR_INVALIDPARAMS;
756 /* Execute... */
757 EnterCriticalSection(&ddraw_cs);
758 IDirect3DExecuteBufferImpl_Execute(Direct3DExecuteBufferImpl, This, Direct3DViewportImpl);
759 LeaveCriticalSection(&ddraw_cs);
761 return D3D_OK;
764 /*****************************************************************************
765 * IDirect3DDevice3::AddViewport
767 * Add a Direct3DViewport to the device's viewport list. These viewports
768 * are wrapped to IDirect3DDevice7 viewports in viewport.c
770 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
771 * are the same interfaces.
773 * Params:
774 * Viewport: The viewport to add
776 * Returns:
777 * DDERR_INVALIDPARAMS if Viewport == NULL
778 * D3D_OK on success
780 *****************************************************************************/
781 static HRESULT WINAPI
782 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
783 IDirect3DViewport3 *Viewport)
785 IDirect3DDeviceImpl *This = device_from_device3(iface);
786 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
788 TRACE("iface %p, viewport %p.\n", iface, Viewport);
790 /* Sanity check */
791 if(!vp)
792 return DDERR_INVALIDPARAMS;
794 EnterCriticalSection(&ddraw_cs);
795 vp->next = This->viewport_list;
796 This->viewport_list = vp;
797 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
798 so set active_device here. */
799 LeaveCriticalSection(&ddraw_cs);
801 return D3D_OK;
804 static HRESULT WINAPI
805 Thunk_IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
806 IDirect3DViewport2 *Direct3DViewport2)
808 IDirect3DDeviceImpl *This = device_from_device2(iface);
809 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
811 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
813 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
816 static HRESULT WINAPI
817 Thunk_IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
818 IDirect3DViewport *Direct3DViewport)
820 IDirect3DDeviceImpl *This = device_from_device1(iface);
821 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
823 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
825 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
828 /*****************************************************************************
829 * IDirect3DDevice3::DeleteViewport
831 * Deletes a Direct3DViewport from the device's viewport list.
833 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
834 * are equal.
836 * Params:
837 * Viewport: The viewport to delete
839 * Returns:
840 * D3D_OK on success
841 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
843 *****************************************************************************/
844 static HRESULT WINAPI
845 IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface,
846 IDirect3DViewport3 *Viewport)
848 IDirect3DDeviceImpl *This = device_from_device3(iface);
849 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *) Viewport;
850 IDirect3DViewportImpl *cur_viewport, *prev_viewport = NULL;
852 TRACE("iface %p, viewport %p.\n", iface, Viewport);
854 EnterCriticalSection(&ddraw_cs);
855 cur_viewport = This->viewport_list;
856 while (cur_viewport != NULL)
858 if (cur_viewport == vp)
860 if (prev_viewport == NULL) This->viewport_list = cur_viewport->next;
861 else prev_viewport->next = cur_viewport->next;
862 /* TODO : add desactivate of the viewport and all associated lights... */
863 LeaveCriticalSection(&ddraw_cs);
864 return D3D_OK;
866 prev_viewport = cur_viewport;
867 cur_viewport = cur_viewport->next;
870 LeaveCriticalSection(&ddraw_cs);
871 return DDERR_INVALIDPARAMS;
874 static HRESULT WINAPI
875 Thunk_IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
876 IDirect3DViewport2 *Direct3DViewport2)
878 IDirect3DDeviceImpl *This = device_from_device2(iface);
879 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
881 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
883 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
886 static HRESULT WINAPI
887 Thunk_IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
888 IDirect3DViewport *Direct3DViewport)
890 IDirect3DDeviceImpl *This = device_from_device1(iface);
891 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
893 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
895 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
898 /*****************************************************************************
899 * IDirect3DDevice3::NextViewport
901 * Returns a viewport from the viewport list, depending on the
902 * passed viewport and the flags.
904 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
905 * are equal.
907 * Params:
908 * Viewport: Viewport to use for beginning the search
909 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
911 * Returns:
912 * D3D_OK on success
913 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
915 *****************************************************************************/
916 static HRESULT WINAPI
917 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
918 IDirect3DViewport3 *Viewport3,
919 IDirect3DViewport3 **lplpDirect3DViewport3,
920 DWORD Flags)
922 IDirect3DDeviceImpl *This = device_from_device3(iface);
923 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport3;
924 IDirect3DViewportImpl *res = NULL;
926 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
927 iface, Viewport3, lplpDirect3DViewport3, Flags);
929 if(!vp)
931 *lplpDirect3DViewport3 = NULL;
932 return DDERR_INVALIDPARAMS;
936 EnterCriticalSection(&ddraw_cs);
937 switch (Flags)
939 case D3DNEXT_NEXT:
941 res = vp->next;
943 break;
944 case D3DNEXT_HEAD:
946 res = This->viewport_list;
948 break;
949 case D3DNEXT_TAIL:
951 IDirect3DViewportImpl *cur_viewport = This->viewport_list;
952 if (cur_viewport != NULL)
954 while (cur_viewport->next != NULL) cur_viewport = cur_viewport->next;
956 res = cur_viewport;
958 break;
959 default:
960 *lplpDirect3DViewport3 = NULL;
961 LeaveCriticalSection(&ddraw_cs);
962 return DDERR_INVALIDPARAMS;
965 *lplpDirect3DViewport3 = (IDirect3DViewport3 *)res;
966 LeaveCriticalSection(&ddraw_cs);
967 return D3D_OK;
970 static HRESULT WINAPI
971 Thunk_IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
972 IDirect3DViewport2 *Viewport2,
973 IDirect3DViewport2 **lplpDirect3DViewport2,
974 DWORD Flags)
976 IDirect3DDeviceImpl *This = device_from_device2(iface);
977 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport2;
978 IDirect3DViewport3 *res;
979 HRESULT hr;
981 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
982 iface, Viewport2, lplpDirect3DViewport2, Flags);
984 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
985 (IDirect3DViewport3 *)vp, &res, Flags);
986 *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
987 return hr;
990 static HRESULT WINAPI
991 Thunk_IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
992 IDirect3DViewport *Viewport,
993 IDirect3DViewport **lplpDirect3DViewport,
994 DWORD Flags)
996 IDirect3DDeviceImpl *This = device_from_device1(iface);
997 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
998 IDirect3DViewport3 *res;
999 HRESULT hr;
1001 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
1002 iface, Viewport, lplpDirect3DViewport, Flags);
1004 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1005 (IDirect3DViewport3 *)vp, &res, Flags);
1006 *lplpDirect3DViewport = (IDirect3DViewport *)res;
1007 return hr;
1010 /*****************************************************************************
1011 * IDirect3DDevice::Pick
1013 * Executes an execute buffer without performing rendering. Instead, a
1014 * list of primitives that intersect with (x1,y1) of the passed rectangle
1015 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
1016 * this list.
1018 * Version 1 only
1020 * Params:
1021 * ExecuteBuffer: Buffer to execute
1022 * Viewport: Viewport to use for execution
1023 * Flags: None are defined, according to the SDK
1024 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
1025 * x2 and y2 are ignored.
1027 * Returns:
1028 * D3D_OK because it's a stub
1030 *****************************************************************************/
1031 static HRESULT WINAPI
1032 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
1033 IDirect3DExecuteBuffer *ExecuteBuffer,
1034 IDirect3DViewport *Viewport,
1035 DWORD Flags,
1036 D3DRECT *Rect)
1038 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
1039 iface, ExecuteBuffer, Viewport, Flags, wine_dbgstr_rect((RECT *)Rect));
1041 return D3D_OK;
1044 /*****************************************************************************
1045 * IDirect3DDevice::GetPickRecords
1047 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1049 * Version 1 only
1051 * Params:
1052 * Count: Pointer to a DWORD containing the numbers of pick records to
1053 * retrieve
1054 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1056 * Returns:
1057 * D3D_OK, because it's a stub
1059 *****************************************************************************/
1060 static HRESULT WINAPI
1061 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1062 DWORD *Count,
1063 D3DPICKRECORD *D3DPickRec)
1065 FIXME("iface %p, count %p, records %p stub!\n", iface, Count, D3DPickRec);
1067 return D3D_OK;
1070 /*****************************************************************************
1071 * IDirect3DDevice7::EnumTextureformats
1073 * Enumerates the supported texture formats. It has a list of all possible
1074 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1075 * WineD3D supports it. If so, then it is passed to the app.
1077 * This is for Version 7 and 3, older versions have a different
1078 * callback function and their own implementation
1080 * Params:
1081 * Callback: Callback to call for each enumerated format
1082 * Arg: Argument to pass to the callback
1084 * Returns:
1085 * D3D_OK on success
1086 * DDERR_INVALIDPARAMS if Callback == NULL
1088 *****************************************************************************/
1089 static HRESULT
1090 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1091 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1092 void *Arg)
1094 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1095 HRESULT hr;
1096 WINED3DDISPLAYMODE mode;
1097 unsigned int i;
1099 static const enum wined3d_format_id FormatList[] =
1101 /* 32 bit */
1102 WINED3DFMT_B8G8R8A8_UNORM,
1103 WINED3DFMT_B8G8R8X8_UNORM,
1104 /* 24 bit */
1105 WINED3DFMT_B8G8R8_UNORM,
1106 /* 16 Bit */
1107 WINED3DFMT_B5G5R5A1_UNORM,
1108 WINED3DFMT_B4G4R4A4_UNORM,
1109 WINED3DFMT_B5G6R5_UNORM,
1110 WINED3DFMT_B5G5R5X1_UNORM,
1111 /* 8 Bit */
1112 WINED3DFMT_B2G3R3_UNORM,
1113 WINED3DFMT_P8_UINT,
1114 /* FOURCC codes */
1115 WINED3DFMT_DXT1,
1116 WINED3DFMT_DXT3,
1117 WINED3DFMT_DXT5,
1120 static const enum wined3d_format_id BumpFormatList[] =
1122 WINED3DFMT_R8G8_SNORM,
1123 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1124 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1125 WINED3DFMT_R16G16_SNORM,
1126 WINED3DFMT_R10G11B11_SNORM,
1127 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1130 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1132 if(!Callback)
1133 return DDERR_INVALIDPARAMS;
1135 EnterCriticalSection(&ddraw_cs);
1137 memset(&mode, 0, sizeof(mode));
1138 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1140 &mode);
1141 if(FAILED(hr)) {
1142 LeaveCriticalSection(&ddraw_cs);
1143 WARN("Cannot get the current adapter format\n");
1144 return hr;
1147 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1149 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1150 WINED3DADAPTER_DEFAULT,
1151 WINED3DDEVTYPE_HAL,
1152 mode.Format,
1153 0 /* Usage */,
1154 WINED3DRTYPE_TEXTURE,
1155 FormatList[i],
1156 SURFACE_OPENGL);
1157 if(hr == D3D_OK)
1159 DDPIXELFORMAT pformat;
1161 memset(&pformat, 0, sizeof(pformat));
1162 pformat.dwSize = sizeof(pformat);
1163 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1165 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1166 hr = Callback(&pformat, Arg);
1167 if(hr != DDENUMRET_OK)
1169 TRACE("Format enumeration cancelled by application\n");
1170 LeaveCriticalSection(&ddraw_cs);
1171 return D3D_OK;
1176 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1178 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1179 WINED3DADAPTER_DEFAULT,
1180 WINED3DDEVTYPE_HAL,
1181 mode.Format,
1182 WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1183 WINED3DRTYPE_TEXTURE,
1184 BumpFormatList[i],
1185 SURFACE_OPENGL);
1186 if(hr == D3D_OK)
1188 DDPIXELFORMAT pformat;
1190 memset(&pformat, 0, sizeof(pformat));
1191 pformat.dwSize = sizeof(pformat);
1192 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1194 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1195 hr = Callback(&pformat, Arg);
1196 if(hr != DDENUMRET_OK)
1198 TRACE("Format enumeration cancelled by application\n");
1199 LeaveCriticalSection(&ddraw_cs);
1200 return D3D_OK;
1204 TRACE("End of enumeration\n");
1205 LeaveCriticalSection(&ddraw_cs);
1206 return D3D_OK;
1209 static HRESULT WINAPI
1210 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1211 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1212 void *Arg)
1214 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1217 static HRESULT WINAPI
1218 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1219 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1220 void *Arg)
1222 HRESULT hr;
1223 WORD old_fpucw;
1225 old_fpucw = d3d_fpu_setup();
1226 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1227 set_fpu_control_word(old_fpucw);
1229 return hr;
1232 static HRESULT WINAPI
1233 Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1234 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1235 void *Arg)
1237 IDirect3DDeviceImpl *This = device_from_device3(iface);
1239 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1241 return IDirect3DDevice7_EnumTextureFormats((IDirect3DDevice7 *)This, Callback, Arg);
1244 /*****************************************************************************
1245 * IDirect3DDevice2::EnumTextureformats
1247 * EnumTextureFormats for Version 1 and 2, see
1248 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1250 * This version has a different callback and does not enumerate FourCC
1251 * formats
1253 *****************************************************************************/
1254 static HRESULT WINAPI
1255 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1256 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1257 void *Arg)
1259 IDirect3DDeviceImpl *This = device_from_device2(iface);
1260 HRESULT hr;
1261 unsigned int i;
1262 WINED3DDISPLAYMODE mode;
1264 static const enum wined3d_format_id FormatList[] =
1266 /* 32 bit */
1267 WINED3DFMT_B8G8R8A8_UNORM,
1268 WINED3DFMT_B8G8R8X8_UNORM,
1269 /* 24 bit */
1270 WINED3DFMT_B8G8R8_UNORM,
1271 /* 16 Bit */
1272 WINED3DFMT_B5G5R5A1_UNORM,
1273 WINED3DFMT_B4G4R4A4_UNORM,
1274 WINED3DFMT_B5G6R5_UNORM,
1275 WINED3DFMT_B5G5R5X1_UNORM,
1276 /* 8 Bit */
1277 WINED3DFMT_B2G3R3_UNORM,
1278 WINED3DFMT_P8_UINT,
1279 /* FOURCC codes - Not in this version*/
1282 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1284 if(!Callback)
1285 return DDERR_INVALIDPARAMS;
1287 EnterCriticalSection(&ddraw_cs);
1289 memset(&mode, 0, sizeof(mode));
1290 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1292 &mode);
1293 if(FAILED(hr)) {
1294 LeaveCriticalSection(&ddraw_cs);
1295 WARN("Cannot get the current adapter format\n");
1296 return hr;
1299 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1301 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1302 0 /* Adapter */,
1303 WINED3DDEVTYPE_HAL,
1304 mode.Format,
1305 0 /* Usage */,
1306 WINED3DRTYPE_TEXTURE,
1307 FormatList[i],
1308 SURFACE_OPENGL);
1309 if(hr == D3D_OK)
1311 DDSURFACEDESC sdesc;
1313 memset(&sdesc, 0, sizeof(sdesc));
1314 sdesc.dwSize = sizeof(sdesc);
1315 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1316 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1317 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1318 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1320 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1321 hr = Callback(&sdesc, Arg);
1322 if(hr != DDENUMRET_OK)
1324 TRACE("Format enumeration cancelled by application\n");
1325 LeaveCriticalSection(&ddraw_cs);
1326 return D3D_OK;
1330 TRACE("End of enumeration\n");
1331 LeaveCriticalSection(&ddraw_cs);
1332 return D3D_OK;
1335 static HRESULT WINAPI
1336 Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1337 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1338 void *Arg)
1340 IDirect3DDeviceImpl *This = device_from_device1(iface);
1342 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1344 return IDirect3DDevice2_EnumTextureFormats((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, Callback, Arg);
1347 /*****************************************************************************
1348 * IDirect3DDevice::CreateMatrix
1350 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1351 * allocated for the handle.
1353 * Version 1 only
1355 * Params
1356 * D3DMatHandle: Address to return the handle at
1358 * Returns:
1359 * D3D_OK on success
1360 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1362 *****************************************************************************/
1363 static HRESULT WINAPI
1364 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1366 IDirect3DDeviceImpl *This = device_from_device1(iface);
1367 D3DMATRIX *Matrix;
1368 DWORD h;
1370 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1372 if(!D3DMatHandle)
1373 return DDERR_INVALIDPARAMS;
1375 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1376 if(!Matrix)
1378 ERR("Out of memory when allocating a D3DMATRIX\n");
1379 return DDERR_OUTOFMEMORY;
1382 EnterCriticalSection(&ddraw_cs);
1384 h = ddraw_allocate_handle(&This->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1385 if (h == DDRAW_INVALID_HANDLE)
1387 ERR("Failed to allocate a matrix handle.\n");
1388 HeapFree(GetProcessHeap(), 0, Matrix);
1389 LeaveCriticalSection(&ddraw_cs);
1390 return DDERR_OUTOFMEMORY;
1393 *D3DMatHandle = h + 1;
1395 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1397 LeaveCriticalSection(&ddraw_cs);
1398 return D3D_OK;
1401 /*****************************************************************************
1402 * IDirect3DDevice::SetMatrix
1404 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1405 * allocated for the handle
1407 * Version 1 only
1409 * Params:
1410 * D3DMatHandle: Handle to set the matrix to
1411 * D3DMatrix: Matrix to set
1413 * Returns:
1414 * D3D_OK on success
1415 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1416 * to set is NULL
1418 *****************************************************************************/
1419 static HRESULT WINAPI
1420 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1421 D3DMATRIXHANDLE D3DMatHandle,
1422 D3DMATRIX *D3DMatrix)
1424 IDirect3DDeviceImpl *This = device_from_device1(iface);
1425 D3DMATRIX *m;
1427 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1429 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1431 EnterCriticalSection(&ddraw_cs);
1433 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1434 if (!m)
1436 WARN("Invalid matrix handle.\n");
1437 LeaveCriticalSection(&ddraw_cs);
1438 return DDERR_INVALIDPARAMS;
1441 if (TRACE_ON(ddraw))
1442 dump_D3DMATRIX(D3DMatrix);
1444 *m = *D3DMatrix;
1446 if(This->world == D3DMatHandle)
1448 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1449 WINED3DTS_WORLDMATRIX(0),
1450 (WINED3DMATRIX *) D3DMatrix);
1452 if(This->view == D3DMatHandle)
1454 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1455 WINED3DTS_VIEW,
1456 (WINED3DMATRIX *) D3DMatrix);
1458 if(This->proj == D3DMatHandle)
1460 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1461 WINED3DTS_PROJECTION,
1462 (WINED3DMATRIX *) D3DMatrix);
1465 LeaveCriticalSection(&ddraw_cs);
1466 return D3D_OK;
1469 /*****************************************************************************
1470 * IDirect3DDevice::GetMatrix
1472 * Returns the content of a D3DMATRIX handle
1474 * Version 1 only
1476 * Params:
1477 * D3DMatHandle: Matrix handle to read the content from
1478 * D3DMatrix: Address to store the content at
1480 * Returns:
1481 * D3D_OK on success
1482 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1484 *****************************************************************************/
1485 static HRESULT WINAPI
1486 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1487 D3DMATRIXHANDLE D3DMatHandle,
1488 D3DMATRIX *D3DMatrix)
1490 IDirect3DDeviceImpl *This = device_from_device1(iface);
1491 D3DMATRIX *m;
1493 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1495 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1497 EnterCriticalSection(&ddraw_cs);
1499 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1500 if (!m)
1502 WARN("Invalid matrix handle.\n");
1503 LeaveCriticalSection(&ddraw_cs);
1504 return DDERR_INVALIDPARAMS;
1507 *D3DMatrix = *m;
1509 LeaveCriticalSection(&ddraw_cs);
1510 return D3D_OK;
1513 /*****************************************************************************
1514 * IDirect3DDevice::DeleteMatrix
1516 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1518 * Version 1 only
1520 * Params:
1521 * D3DMatHandle: Handle to destroy
1523 * Returns:
1524 * D3D_OK on success
1525 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1527 *****************************************************************************/
1528 static HRESULT WINAPI
1529 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1530 D3DMATRIXHANDLE D3DMatHandle)
1532 IDirect3DDeviceImpl *This = device_from_device1(iface);
1533 D3DMATRIX *m;
1535 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1537 EnterCriticalSection(&ddraw_cs);
1539 m = ddraw_free_handle(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1540 if (!m)
1542 WARN("Invalid matrix handle.\n");
1543 LeaveCriticalSection(&ddraw_cs);
1544 return DDERR_INVALIDPARAMS;
1547 LeaveCriticalSection(&ddraw_cs);
1549 HeapFree(GetProcessHeap(), 0, m);
1551 return D3D_OK;
1554 /*****************************************************************************
1555 * IDirect3DDevice7::BeginScene
1557 * This method must be called before any rendering is performed.
1558 * IDirect3DDevice::EndScene has to be called after the scene is complete
1560 * Version 1, 2, 3 and 7
1562 * Returns:
1563 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1564 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1565 * started scene).
1567 *****************************************************************************/
1568 static HRESULT
1569 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1571 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1572 HRESULT hr;
1574 TRACE("iface %p.\n", iface);
1576 EnterCriticalSection(&ddraw_cs);
1577 hr = IWineD3DDevice_BeginScene(This->wineD3DDevice);
1578 LeaveCriticalSection(&ddraw_cs);
1579 if(hr == WINED3D_OK) return D3D_OK;
1580 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1583 static HRESULT WINAPI
1584 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1586 return IDirect3DDeviceImpl_7_BeginScene(iface);
1589 static HRESULT WINAPI
1590 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1592 HRESULT hr;
1593 WORD old_fpucw;
1595 old_fpucw = d3d_fpu_setup();
1596 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1597 set_fpu_control_word(old_fpucw);
1599 return hr;
1602 static HRESULT WINAPI
1603 Thunk_IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1605 TRACE("iface %p.\n", iface);
1607 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device3(iface));
1610 static HRESULT WINAPI
1611 Thunk_IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1613 TRACE("iface %p.\n", iface);
1615 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device2(iface));
1618 static HRESULT WINAPI
1619 Thunk_IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1621 TRACE("iface %p.\n", iface);
1623 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device1(iface));
1626 /*****************************************************************************
1627 * IDirect3DDevice7::EndScene
1629 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1630 * This method must be called after rendering is finished.
1632 * Version 1, 2, 3 and 7
1634 * Returns:
1635 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1636 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1637 * that only if the scene was already ended.
1639 *****************************************************************************/
1640 static HRESULT
1641 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1643 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1644 HRESULT hr;
1646 TRACE("iface %p.\n", iface);
1648 EnterCriticalSection(&ddraw_cs);
1649 hr = IWineD3DDevice_EndScene(This->wineD3DDevice);
1650 LeaveCriticalSection(&ddraw_cs);
1651 if(hr == WINED3D_OK) return D3D_OK;
1652 else return D3DERR_SCENE_NOT_IN_SCENE;
1655 static HRESULT WINAPI DECLSPEC_HOTPATCH
1656 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1658 return IDirect3DDeviceImpl_7_EndScene(iface);
1661 static HRESULT WINAPI DECLSPEC_HOTPATCH
1662 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1664 HRESULT hr;
1665 WORD old_fpucw;
1667 old_fpucw = d3d_fpu_setup();
1668 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1669 set_fpu_control_word(old_fpucw);
1671 return hr;
1674 static HRESULT WINAPI DECLSPEC_HOTPATCH
1675 Thunk_IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1677 TRACE("iface %p.\n", iface);
1679 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device3(iface));
1682 static HRESULT WINAPI DECLSPEC_HOTPATCH
1683 Thunk_IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1685 TRACE("iface %p.\n", iface);
1687 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device2(iface));
1690 static HRESULT WINAPI DECLSPEC_HOTPATCH
1691 Thunk_IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1693 TRACE("iface %p.\n", iface);
1695 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device1(iface));
1698 /*****************************************************************************
1699 * IDirect3DDevice7::GetDirect3D
1701 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1702 * this device.
1704 * Params:
1705 * Direct3D7: Address to store the interface pointer at
1707 * Returns:
1708 * D3D_OK on success
1709 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1711 *****************************************************************************/
1712 static HRESULT WINAPI
1713 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1714 IDirect3D7 **Direct3D7)
1716 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1718 TRACE("iface %p, d3d %p.\n", iface, Direct3D7);
1720 if(!Direct3D7)
1721 return DDERR_INVALIDPARAMS;
1723 *Direct3D7 = (IDirect3D7 *)&This->ddraw->IDirect3D7_vtbl;
1724 IDirect3D7_AddRef(*Direct3D7);
1726 TRACE(" returning interface %p\n", *Direct3D7);
1727 return D3D_OK;
1730 static HRESULT WINAPI
1731 Thunk_IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1732 IDirect3D3 **Direct3D3)
1734 IDirect3DDeviceImpl *This = device_from_device3(iface);
1735 HRESULT ret;
1736 IDirect3D7 *ret_ptr;
1738 TRACE("iface %p, d3d %p.\n", iface, Direct3D3);
1740 ret = IDirect3DDevice7_GetDirect3D((IDirect3DDevice7 *)This, &ret_ptr);
1741 if(ret != D3D_OK)
1742 return ret;
1743 *Direct3D3 = ret_ptr ? (IDirect3D3 *)&ddraw_from_d3d7(ret_ptr)->IDirect3D3_vtbl : NULL;
1744 TRACE(" returning interface %p\n", *Direct3D3);
1745 return D3D_OK;
1748 static HRESULT WINAPI
1749 Thunk_IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1750 IDirect3D2 **Direct3D2)
1752 IDirect3DDeviceImpl *This = device_from_device2(iface);
1753 HRESULT ret;
1754 IDirect3D7 *ret_ptr;
1756 TRACE("iface %p, d3d %p.\n", iface, Direct3D2);
1758 ret = IDirect3DDevice7_GetDirect3D((IDirect3DDevice7 *)This, &ret_ptr);
1759 if(ret != D3D_OK)
1760 return ret;
1761 *Direct3D2 = ret_ptr ? (IDirect3D2 *)&ddraw_from_d3d7(ret_ptr)->IDirect3D2_vtbl : NULL;
1762 TRACE(" returning interface %p\n", *Direct3D2);
1763 return D3D_OK;
1766 static HRESULT WINAPI
1767 Thunk_IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1768 IDirect3D **Direct3D)
1770 IDirect3DDeviceImpl *This = device_from_device1(iface);
1771 HRESULT ret;
1772 IDirect3D7 *ret_ptr;
1774 TRACE("iface %p, d3d %p.\n", iface, Direct3D);
1776 ret = IDirect3DDevice7_GetDirect3D((IDirect3DDevice7 *)This, &ret_ptr);
1777 if(ret != D3D_OK)
1778 return ret;
1779 *Direct3D = ret_ptr ? (IDirect3D *)&ddraw_from_d3d7(ret_ptr)->IDirect3D_vtbl : NULL;
1780 TRACE(" returning interface %p\n", *Direct3D);
1781 return D3D_OK;
1784 /*****************************************************************************
1785 * IDirect3DDevice3::SetCurrentViewport
1787 * Sets a Direct3DViewport as the current viewport.
1788 * For the thunks note that all viewport interface versions are equal
1790 * Params:
1791 * Direct3DViewport3: The viewport to set
1793 * Version 2 and 3
1795 * Returns:
1796 * D3D_OK on success
1797 * (Is a NULL viewport valid?)
1799 *****************************************************************************/
1800 static HRESULT WINAPI
1801 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1802 IDirect3DViewport3 *Direct3DViewport3)
1804 IDirect3DDeviceImpl *This = device_from_device3(iface);
1805 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport3;
1807 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1809 EnterCriticalSection(&ddraw_cs);
1810 /* Do nothing if the specified viewport is the same as the current one */
1811 if (This->current_viewport == vp )
1813 LeaveCriticalSection(&ddraw_cs);
1814 return D3D_OK;
1817 /* Should check if the viewport was added or not */
1819 /* Release previous viewport and AddRef the new one */
1820 if (This->current_viewport)
1822 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1823 (IDirect3DViewport3 *)This->current_viewport);
1824 IDirect3DViewport3_Release((IDirect3DViewport3 *)This->current_viewport);
1826 IDirect3DViewport3_AddRef(Direct3DViewport3);
1828 /* Set this viewport as the current viewport */
1829 This->current_viewport = vp;
1831 /* Activate this viewport */
1832 This->current_viewport->active_device = This;
1833 viewport_activate(This->current_viewport, FALSE);
1835 LeaveCriticalSection(&ddraw_cs);
1836 return D3D_OK;
1839 static HRESULT WINAPI
1840 Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1841 IDirect3DViewport2 *Direct3DViewport2)
1843 IDirect3DDeviceImpl *This = device_from_device2(iface);
1844 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
1846 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1848 return IDirect3DDevice3_SetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1849 (IDirect3DViewport3 *)vp);
1852 /*****************************************************************************
1853 * IDirect3DDevice3::GetCurrentViewport
1855 * Returns the currently active viewport.
1857 * Version 2 and 3
1859 * Params:
1860 * Direct3DViewport3: Address to return the interface pointer at
1862 * Returns:
1863 * D3D_OK on success
1864 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1866 *****************************************************************************/
1867 static HRESULT WINAPI
1868 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1869 IDirect3DViewport3 **Direct3DViewport3)
1871 IDirect3DDeviceImpl *This = device_from_device3(iface);
1873 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1875 if(!Direct3DViewport3)
1876 return DDERR_INVALIDPARAMS;
1878 EnterCriticalSection(&ddraw_cs);
1879 *Direct3DViewport3 = (IDirect3DViewport3 *)This->current_viewport;
1881 /* AddRef the returned viewport */
1882 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1884 TRACE(" returning interface %p\n", *Direct3DViewport3);
1886 LeaveCriticalSection(&ddraw_cs);
1887 return D3D_OK;
1890 static HRESULT WINAPI
1891 Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1892 IDirect3DViewport2 **Direct3DViewport2)
1894 IDirect3DDeviceImpl *This = device_from_device2(iface);
1895 HRESULT hr;
1897 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1899 hr = IDirect3DDevice3_GetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1900 (IDirect3DViewport3 **)Direct3DViewport2);
1901 if(hr != D3D_OK) return hr;
1902 return D3D_OK;
1905 /*****************************************************************************
1906 * IDirect3DDevice7::SetRenderTarget
1908 * Sets the render target for the Direct3DDevice.
1909 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1910 * IDirectDrawSurface3 == IDirectDrawSurface
1912 * Version 2, 3 and 7
1914 * Params:
1915 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1916 * render target
1917 * Flags: Some flags
1919 * Returns:
1920 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1922 *****************************************************************************/
1923 static HRESULT
1924 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1925 IDirectDrawSurface7 *NewTarget,
1926 DWORD Flags)
1928 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1929 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewTarget;
1930 HRESULT hr;
1932 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, Flags);
1934 EnterCriticalSection(&ddraw_cs);
1935 /* Flags: Not used */
1937 if(This->target == Target)
1939 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1940 LeaveCriticalSection(&ddraw_cs);
1941 return D3D_OK;
1944 hr = IWineD3DDevice_SetRenderTarget(This->wineD3DDevice,
1946 Target ? Target->WineD3DSurface : NULL,
1947 FALSE);
1948 if(hr != D3D_OK)
1950 LeaveCriticalSection(&ddraw_cs);
1951 return hr;
1953 IDirectDrawSurface7_AddRef(NewTarget);
1954 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->target);
1955 This->target = Target;
1956 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1957 LeaveCriticalSection(&ddraw_cs);
1958 return D3D_OK;
1961 static HRESULT WINAPI
1962 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1963 IDirectDrawSurface7 *NewTarget,
1964 DWORD Flags)
1966 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1969 static HRESULT WINAPI
1970 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1971 IDirectDrawSurface7 *NewTarget,
1972 DWORD Flags)
1974 HRESULT hr;
1975 WORD old_fpucw;
1977 old_fpucw = d3d_fpu_setup();
1978 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1979 set_fpu_control_word(old_fpucw);
1981 return hr;
1984 static HRESULT WINAPI
1985 Thunk_IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
1986 IDirectDrawSurface4 *NewRenderTarget,
1987 DWORD Flags)
1989 IDirect3DDeviceImpl *This = device_from_device3(iface);
1990 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
1992 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1994 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
1997 static HRESULT WINAPI
1998 Thunk_IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
1999 IDirectDrawSurface *NewRenderTarget,
2000 DWORD Flags)
2002 IDirect3DDeviceImpl *This = device_from_device2(iface);
2003 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
2005 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
2007 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
2010 /*****************************************************************************
2011 * IDirect3DDevice7::GetRenderTarget
2013 * Returns the current render target.
2014 * This is handled locally, because the WineD3D render target's parent
2015 * is an IParent
2017 * Version 2, 3 and 7
2019 * Params:
2020 * RenderTarget: Address to store the surface interface pointer
2022 * Returns:
2023 * D3D_OK on success
2024 * DDERR_INVALIDPARAMS if RenderTarget == NULL
2026 *****************************************************************************/
2027 static HRESULT WINAPI
2028 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
2029 IDirectDrawSurface7 **RenderTarget)
2031 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2033 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2035 if(!RenderTarget)
2036 return DDERR_INVALIDPARAMS;
2038 EnterCriticalSection(&ddraw_cs);
2039 *RenderTarget = (IDirectDrawSurface7 *)This->target;
2040 IDirectDrawSurface7_AddRef(*RenderTarget);
2042 LeaveCriticalSection(&ddraw_cs);
2043 return D3D_OK;
2046 static HRESULT WINAPI
2047 Thunk_IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
2048 IDirectDrawSurface4 **RenderTarget)
2050 IDirect3DDeviceImpl *This = device_from_device3(iface);
2051 HRESULT hr;
2053 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2055 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
2056 if(hr != D3D_OK) return hr;
2057 return D3D_OK;
2060 static HRESULT WINAPI
2061 Thunk_IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
2062 IDirectDrawSurface **RenderTarget)
2064 IDirect3DDeviceImpl *This = device_from_device2(iface);
2065 HRESULT hr;
2067 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2069 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
2070 if(hr != D3D_OK) return hr;
2071 *RenderTarget = *RenderTarget ?
2072 (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)*RenderTarget)->IDirectDrawSurface3_vtbl : NULL;
2073 return D3D_OK;
2076 /*****************************************************************************
2077 * IDirect3DDevice3::Begin
2079 * Begins a description block of vertices. This is similar to glBegin()
2080 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2081 * described with IDirect3DDevice::Vertex are drawn.
2083 * Version 2 and 3
2085 * Params:
2086 * PrimitiveType: The type of primitives to draw
2087 * VertexTypeDesc: A flexible vertex format description of the vertices
2088 * Flags: Some flags..
2090 * Returns:
2091 * D3D_OK on success
2093 *****************************************************************************/
2094 static HRESULT WINAPI
2095 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2096 D3DPRIMITIVETYPE PrimitiveType,
2097 DWORD VertexTypeDesc,
2098 DWORD Flags)
2100 IDirect3DDeviceImpl *This = device_from_device3(iface);
2102 TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
2103 iface, PrimitiveType, VertexTypeDesc, Flags);
2105 EnterCriticalSection(&ddraw_cs);
2106 This->primitive_type = PrimitiveType;
2107 This->vertex_type = VertexTypeDesc;
2108 This->render_flags = Flags;
2109 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2110 This->nb_vertices = 0;
2111 LeaveCriticalSection(&ddraw_cs);
2113 return D3D_OK;
2116 static HRESULT WINAPI
2117 Thunk_IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface,
2118 D3DPRIMITIVETYPE d3dpt,
2119 D3DVERTEXTYPE dwVertexTypeDesc,
2120 DWORD dwFlags)
2122 DWORD FVF;
2123 IDirect3DDeviceImpl *This = device_from_device2(iface);
2125 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2126 iface, d3dpt, dwVertexTypeDesc, dwFlags);
2128 switch(dwVertexTypeDesc)
2130 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2131 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2132 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2133 default:
2134 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2135 return DDERR_INVALIDPARAMS; /* Should never happen */
2138 return IDirect3DDevice3_Begin((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, d3dpt, FVF, dwFlags);
2141 /*****************************************************************************
2142 * IDirect3DDevice3::BeginIndexed
2144 * Draws primitives based on vertices in a vertex array which are specified
2145 * by indices.
2147 * Version 2 and 3
2149 * Params:
2150 * PrimitiveType: Primitive type to draw
2151 * VertexType: A FVF description of the vertex format
2152 * Vertices: pointer to an array containing the vertices
2153 * NumVertices: The number of vertices in the vertex array
2154 * Flags: Some flags ...
2156 * Returns:
2157 * D3D_OK, because it's a stub
2159 *****************************************************************************/
2160 static HRESULT WINAPI
2161 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2162 D3DPRIMITIVETYPE PrimitiveType,
2163 DWORD VertexType,
2164 void *Vertices,
2165 DWORD NumVertices,
2166 DWORD Flags)
2168 FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2169 iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2171 return D3D_OK;
2175 static HRESULT WINAPI
2176 Thunk_IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2177 D3DPRIMITIVETYPE d3dptPrimitiveType,
2178 D3DVERTEXTYPE d3dvtVertexType,
2179 void *lpvVertices,
2180 DWORD dwNumVertices,
2181 DWORD dwFlags)
2183 DWORD FVF;
2184 IDirect3DDeviceImpl *This = device_from_device2(iface);
2186 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2187 iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2189 switch(d3dvtVertexType)
2191 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2192 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2193 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2194 default:
2195 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2196 return DDERR_INVALIDPARAMS; /* Should never happen */
2199 return IDirect3DDevice3_BeginIndexed((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2200 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2203 /*****************************************************************************
2204 * IDirect3DDevice3::Vertex
2206 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2207 * drawn vertices in a vertex buffer. If the buffer is too small, its
2208 * size is increased.
2210 * Version 2 and 3
2212 * Params:
2213 * Vertex: Pointer to the vertex
2215 * Returns:
2216 * D3D_OK, on success
2217 * DDERR_INVALIDPARAMS if Vertex is NULL
2219 *****************************************************************************/
2220 static HRESULT WINAPI
2221 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2222 void *Vertex)
2224 IDirect3DDeviceImpl *This = device_from_device3(iface);
2226 TRACE("iface %p, vertex %p.\n", iface, Vertex);
2228 if(!Vertex)
2229 return DDERR_INVALIDPARAMS;
2231 EnterCriticalSection(&ddraw_cs);
2232 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2234 BYTE *old_buffer;
2235 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2236 old_buffer = This->vertex_buffer;
2237 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2238 if (old_buffer)
2240 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2241 HeapFree(GetProcessHeap(), 0, old_buffer);
2245 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2247 LeaveCriticalSection(&ddraw_cs);
2248 return D3D_OK;
2251 static HRESULT WINAPI
2252 Thunk_IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface,
2253 void *lpVertexType)
2255 IDirect3DDeviceImpl *This = device_from_device2(iface);
2257 TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
2259 return IDirect3DDevice3_Vertex((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, lpVertexType);
2262 /*****************************************************************************
2263 * IDirect3DDevice3::Index
2265 * Specifies an index to a vertex to be drawn. The vertex array has to
2266 * be specified with BeginIndexed first.
2268 * Parameters:
2269 * VertexIndex: The index of the vertex to draw
2271 * Returns:
2272 * D3D_OK because it's a stub
2274 *****************************************************************************/
2275 static HRESULT WINAPI
2276 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2277 WORD VertexIndex)
2279 FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
2281 return D3D_OK;
2284 static HRESULT WINAPI
2285 Thunk_IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface,
2286 WORD wVertexIndex)
2288 IDirect3DDeviceImpl *This = device_from_device2(iface);
2290 TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
2292 return IDirect3DDevice3_Index((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, wVertexIndex);
2295 /*****************************************************************************
2296 * IDirect3DDevice3::End
2298 * Ends a draw begun with IDirect3DDevice3::Begin or
2299 * IDirect3DDevice::BeginIndexed. The vertices specified with
2300 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2301 * the IDirect3DDevice7::DrawPrimitive method. So far only
2302 * non-indexed mode is supported
2304 * Version 2 and 3
2306 * Params:
2307 * Flags: Some flags, as usual. Don't know which are defined
2309 * Returns:
2310 * The return value of IDirect3DDevice7::DrawPrimitive
2312 *****************************************************************************/
2313 static HRESULT WINAPI
2314 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2315 DWORD Flags)
2317 IDirect3DDeviceImpl *This = device_from_device3(iface);
2319 TRACE("iface %p, flags %#x.\n", iface, Flags);
2321 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This, This->primitive_type,
2322 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2325 static HRESULT WINAPI
2326 Thunk_IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface,
2327 DWORD dwFlags)
2329 IDirect3DDeviceImpl *This = device_from_device2(iface);
2331 TRACE("iface %p, flags %#x.\n", iface, dwFlags);
2333 return IDirect3DDevice3_End((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, dwFlags);
2336 /*****************************************************************************
2337 * IDirect3DDevice7::GetRenderState
2339 * Returns the value of a render state. The possible render states are
2340 * defined in include/d3dtypes.h
2342 * Version 2, 3 and 7
2344 * Params:
2345 * RenderStateType: Render state to return the current setting of
2346 * Value: Address to store the value at
2348 * Returns:
2349 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2350 * DDERR_INVALIDPARAMS if Value == NULL
2352 *****************************************************************************/
2353 static HRESULT
2354 IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2355 D3DRENDERSTATETYPE RenderStateType,
2356 DWORD *Value)
2358 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2359 HRESULT hr;
2361 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2363 if(!Value)
2364 return DDERR_INVALIDPARAMS;
2366 EnterCriticalSection(&ddraw_cs);
2367 switch(RenderStateType)
2369 case D3DRENDERSTATE_TEXTUREMAG:
2371 WINED3DTEXTUREFILTERTYPE tex_mag;
2373 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2374 0, WINED3DSAMP_MAGFILTER,
2375 &tex_mag);
2377 switch (tex_mag)
2379 case WINED3DTEXF_POINT:
2380 *Value = D3DFILTER_NEAREST;
2381 break;
2382 case WINED3DTEXF_LINEAR:
2383 *Value = D3DFILTER_LINEAR;
2384 break;
2385 default:
2386 ERR("Unhandled texture mag %d !\n",tex_mag);
2387 *Value = 0;
2389 break;
2392 case D3DRENDERSTATE_TEXTUREMIN:
2394 WINED3DTEXTUREFILTERTYPE tex_min;
2395 WINED3DTEXTUREFILTERTYPE tex_mip;
2397 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2398 0, WINED3DSAMP_MINFILTER, &tex_min);
2399 if (FAILED(hr))
2401 LeaveCriticalSection(&ddraw_cs);
2402 return hr;
2404 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2405 0, WINED3DSAMP_MIPFILTER, &tex_mip);
2407 switch (tex_min)
2409 case WINED3DTEXF_POINT:
2410 switch (tex_mip)
2412 case WINED3DTEXF_NONE:
2413 *Value = D3DFILTER_NEAREST;
2414 break;
2415 case WINED3DTEXF_POINT:
2416 *Value = D3DFILTER_MIPNEAREST;
2417 break;
2418 case WINED3DTEXF_LINEAR:
2419 *Value = D3DFILTER_LINEARMIPNEAREST;
2420 break;
2421 default:
2422 ERR("Unhandled mip filter %#x.\n", tex_mip);
2423 *Value = D3DFILTER_NEAREST;
2424 break;
2426 break;
2427 case WINED3DTEXF_LINEAR:
2428 switch (tex_mip)
2430 case WINED3DTEXF_NONE:
2431 *Value = D3DFILTER_LINEAR;
2432 break;
2433 case WINED3DTEXF_POINT:
2434 *Value = D3DFILTER_MIPLINEAR;
2435 break;
2436 case WINED3DTEXF_LINEAR:
2437 *Value = D3DFILTER_LINEARMIPLINEAR;
2438 break;
2439 default:
2440 ERR("Unhandled mip filter %#x.\n", tex_mip);
2441 *Value = D3DFILTER_LINEAR;
2442 break;
2444 break;
2445 default:
2446 ERR("Unhandled texture min filter %#x.\n",tex_min);
2447 *Value = D3DFILTER_NEAREST;
2448 break;
2450 break;
2453 case D3DRENDERSTATE_TEXTUREADDRESS:
2454 case D3DRENDERSTATE_TEXTUREADDRESSU:
2455 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2456 0, WINED3DSAMP_ADDRESSU,
2457 Value);
2458 break;
2459 case D3DRENDERSTATE_TEXTUREADDRESSV:
2460 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2461 0, WINED3DSAMP_ADDRESSV,
2462 Value);
2463 break;
2465 case D3DRENDERSTATE_BORDERCOLOR:
2466 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2467 hr = E_NOTIMPL;
2468 break;
2470 case D3DRENDERSTATE_TEXTUREHANDLE:
2471 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2472 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2473 hr = DDERR_INVALIDPARAMS;
2474 break;
2476 default:
2477 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2478 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2480 FIXME("Unhandled stipple pattern render state (%#x).\n",
2481 RenderStateType);
2482 hr = E_NOTIMPL;
2483 break;
2485 hr = IWineD3DDevice_GetRenderState(This->wineD3DDevice,
2486 RenderStateType,
2487 Value);
2489 LeaveCriticalSection(&ddraw_cs);
2490 return hr;
2493 static HRESULT WINAPI
2494 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2495 D3DRENDERSTATETYPE RenderStateType,
2496 DWORD *Value)
2498 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2501 static HRESULT WINAPI
2502 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2503 D3DRENDERSTATETYPE RenderStateType,
2504 DWORD *Value)
2506 HRESULT hr;
2507 WORD old_fpucw;
2509 old_fpucw = d3d_fpu_setup();
2510 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2511 set_fpu_control_word(old_fpucw);
2513 return hr;
2516 static HRESULT WINAPI
2517 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2518 D3DRENDERSTATETYPE dwRenderStateType,
2519 DWORD *lpdwRenderState)
2521 IDirect3DDeviceImpl *This = device_from_device3(iface);
2522 HRESULT hr;
2524 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2526 switch(dwRenderStateType)
2528 case D3DRENDERSTATE_TEXTUREHANDLE:
2530 /* This state is wrapped to SetTexture in SetRenderState, so
2531 * it has to be wrapped to GetTexture here
2533 IWineD3DBaseTexture *tex = NULL;
2534 *lpdwRenderState = 0;
2536 EnterCriticalSection(&ddraw_cs);
2538 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, 0, &tex);
2539 if (SUCCEEDED(hr) && tex)
2541 /* The parent of the texture is the IDirectDrawSurface7
2542 * interface of the ddraw surface. */
2543 IDirectDrawSurfaceImpl *parent = IWineD3DBaseTexture_GetParent(tex);
2544 if (parent) *lpdwRenderState = parent->Handle;
2545 IWineD3DBaseTexture_Release(tex);
2548 LeaveCriticalSection(&ddraw_cs);
2550 return hr;
2553 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2555 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2556 the mapping to get the value. */
2557 DWORD colorop, colorarg1, colorarg2;
2558 DWORD alphaop, alphaarg1, alphaarg2;
2560 EnterCriticalSection(&ddraw_cs);
2562 This->legacyTextureBlending = TRUE;
2564 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, &colorop);
2565 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, &colorarg1);
2566 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, &colorarg2);
2567 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, &alphaop);
2568 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2569 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2571 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2572 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2574 *lpdwRenderState = D3DTBLEND_DECAL;
2576 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2577 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2579 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2581 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2582 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2584 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2586 else
2588 HRESULT hr;
2589 BOOL tex_alpha = FALSE;
2590 IWineD3DBaseTexture *tex = NULL;
2591 WINED3DSURFACE_DESC desc;
2592 DDPIXELFORMAT ddfmt;
2594 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2596 &tex);
2598 if(hr == WINED3D_OK && tex)
2600 hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2601 if (SUCCEEDED(hr))
2603 ddfmt.dwSize = sizeof(ddfmt);
2604 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2605 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2608 IWineD3DBaseTexture_Release(tex);
2611 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2612 alphaop == (tex_alpha ? WINED3DTOP_SELECTARG1 : WINED3DTOP_SELECTARG2) &&
2613 alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2615 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2618 *lpdwRenderState = D3DTBLEND_MODULATE;
2621 LeaveCriticalSection(&ddraw_cs);
2623 return D3D_OK;
2626 default:
2627 return IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, dwRenderStateType, lpdwRenderState);
2631 static HRESULT WINAPI
2632 Thunk_IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2633 D3DRENDERSTATETYPE dwRenderStateType,
2634 DWORD *lpdwRenderState)
2636 IDirect3DDeviceImpl *This = device_from_device2(iface);
2638 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2640 return IDirect3DDevice3_GetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2641 dwRenderStateType, lpdwRenderState);
2644 /*****************************************************************************
2645 * IDirect3DDevice7::SetRenderState
2647 * Sets a render state. The possible render states are defined in
2648 * include/d3dtypes.h
2650 * Version 2, 3 and 7
2652 * Params:
2653 * RenderStateType: State to set
2654 * Value: Value to assign to that state
2656 * Returns:
2657 * D3D_OK on success,
2658 * for details see IWineD3DDevice::SetRenderState
2660 *****************************************************************************/
2661 static HRESULT
2662 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2663 D3DRENDERSTATETYPE RenderStateType,
2664 DWORD Value)
2666 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2667 HRESULT hr;
2669 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2671 EnterCriticalSection(&ddraw_cs);
2672 /* Some render states need special care */
2673 switch(RenderStateType)
2676 * The ddraw texture filter mapping works like this:
2677 * D3DFILTER_NEAREST Point min/mag, no mip
2678 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2679 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2681 * D3DFILTER_LINEAR Linear min/mag, no mip
2682 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2683 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2685 * This is the opposite of the GL naming convention,
2686 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2688 case D3DRENDERSTATE_TEXTUREMAG:
2690 WINED3DTEXTUREFILTERTYPE tex_mag;
2692 switch (Value)
2694 case D3DFILTER_NEAREST:
2695 case D3DFILTER_MIPNEAREST:
2696 case D3DFILTER_LINEARMIPNEAREST:
2697 tex_mag = WINED3DTEXF_POINT;
2698 break;
2699 case D3DFILTER_LINEAR:
2700 case D3DFILTER_MIPLINEAR:
2701 case D3DFILTER_LINEARMIPLINEAR:
2702 tex_mag = WINED3DTEXF_LINEAR;
2703 break;
2704 default:
2705 tex_mag = WINED3DTEXF_POINT;
2706 ERR("Unhandled texture mag %d !\n",Value);
2707 break;
2710 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2711 0, WINED3DSAMP_MAGFILTER,
2712 tex_mag);
2713 break;
2716 case D3DRENDERSTATE_TEXTUREMIN:
2718 WINED3DTEXTUREFILTERTYPE tex_min;
2719 WINED3DTEXTUREFILTERTYPE tex_mip;
2721 switch ((D3DTEXTUREFILTER) Value)
2723 case D3DFILTER_NEAREST:
2724 tex_min = WINED3DTEXF_POINT;
2725 tex_mip = WINED3DTEXF_NONE;
2726 break;
2727 case D3DFILTER_LINEAR:
2728 tex_min = WINED3DTEXF_LINEAR;
2729 tex_mip = WINED3DTEXF_NONE;
2730 break;
2731 case D3DFILTER_MIPNEAREST:
2732 tex_min = WINED3DTEXF_POINT;
2733 tex_mip = WINED3DTEXF_POINT;
2734 break;
2735 case D3DFILTER_MIPLINEAR:
2736 tex_min = WINED3DTEXF_LINEAR;
2737 tex_mip = WINED3DTEXF_POINT;
2738 break;
2739 case D3DFILTER_LINEARMIPNEAREST:
2740 tex_min = WINED3DTEXF_POINT;
2741 tex_mip = WINED3DTEXF_LINEAR;
2742 break;
2743 case D3DFILTER_LINEARMIPLINEAR:
2744 tex_min = WINED3DTEXF_LINEAR;
2745 tex_mip = WINED3DTEXF_LINEAR;
2746 break;
2748 default:
2749 ERR("Unhandled texture min %d !\n",Value);
2750 tex_min = WINED3DTEXF_POINT;
2751 tex_mip = WINED3DTEXF_NONE;
2752 break;
2755 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2756 0, WINED3DSAMP_MIPFILTER, tex_mip);
2757 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2758 0, WINED3DSAMP_MINFILTER,
2759 tex_min);
2760 break;
2763 case D3DRENDERSTATE_TEXTUREADDRESS:
2764 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2765 0, WINED3DSAMP_ADDRESSV,
2766 Value);
2767 /* Drop through */
2768 case D3DRENDERSTATE_TEXTUREADDRESSU:
2769 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2770 0, WINED3DSAMP_ADDRESSU,
2771 Value);
2772 break;
2773 case D3DRENDERSTATE_TEXTUREADDRESSV:
2774 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2775 0, WINED3DSAMP_ADDRESSV,
2776 Value);
2777 break;
2779 case D3DRENDERSTATE_BORDERCOLOR:
2780 /* This should probably just forward to the corresponding sampler
2781 * state. Needs tests. */
2782 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2783 hr = E_NOTIMPL;
2784 break;
2786 case D3DRENDERSTATE_TEXTUREHANDLE:
2787 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2788 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2789 hr = DDERR_INVALIDPARAMS;
2790 break;
2792 default:
2793 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2794 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2796 FIXME("Unhandled stipple pattern render state (%#x).\n",
2797 RenderStateType);
2798 hr = E_NOTIMPL;
2799 break;
2802 hr = IWineD3DDevice_SetRenderState(This->wineD3DDevice,
2803 RenderStateType,
2804 Value);
2805 break;
2807 LeaveCriticalSection(&ddraw_cs);
2808 return hr;
2811 static HRESULT WINAPI
2812 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2813 D3DRENDERSTATETYPE RenderStateType,
2814 DWORD Value)
2816 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2819 static HRESULT WINAPI
2820 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2821 D3DRENDERSTATETYPE RenderStateType,
2822 DWORD Value)
2824 HRESULT hr;
2825 WORD old_fpucw;
2827 old_fpucw = d3d_fpu_setup();
2828 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2829 set_fpu_control_word(old_fpucw);
2831 return hr;
2834 static HRESULT WINAPI
2835 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2836 D3DRENDERSTATETYPE RenderStateType,
2837 DWORD Value)
2839 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2840 for this state can be directly mapped to texture stage colorop and alphaop, but
2841 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2842 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2843 alphaarg when needed.
2845 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2847 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2848 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2849 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2850 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2851 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2852 in device - TRUE if the app is using TEXTUREMAPBLEND.
2854 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2855 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2856 unless some broken game will be found that cares. */
2858 HRESULT hr;
2859 IDirect3DDeviceImpl *This = device_from_device3(iface);
2861 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2863 EnterCriticalSection(&ddraw_cs);
2865 switch(RenderStateType)
2867 case D3DRENDERSTATE_TEXTUREHANDLE:
2869 IDirectDrawSurfaceImpl *surf;
2871 if(Value == 0)
2873 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
2875 NULL);
2876 break;
2879 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2880 if (!surf)
2882 WARN("Invalid texture handle.\n");
2883 hr = DDERR_INVALIDPARAMS;
2884 break;
2887 hr = IDirect3DDevice3_SetTexture(iface, 0, (IDirect3DTexture2 *)&surf->IDirect3DTexture2_vtbl);
2888 break;
2891 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2893 This->legacyTextureBlending = TRUE;
2895 switch ( (D3DTEXTUREBLEND) Value)
2897 case D3DTBLEND_MODULATE:
2899 BOOL tex_alpha = FALSE;
2900 IWineD3DBaseTexture *tex = NULL;
2901 WINED3DSURFACE_DESC desc;
2902 DDPIXELFORMAT ddfmt;
2904 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2906 &tex);
2908 if(hr == WINED3D_OK && tex)
2910 memset(&desc, 0, sizeof(desc));
2911 hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2912 if (SUCCEEDED(hr))
2914 ddfmt.dwSize = sizeof(ddfmt);
2915 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2916 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2919 IWineD3DBaseTexture_Release(tex);
2922 if (tex_alpha)
2923 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2924 else
2925 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2926 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2927 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2928 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2929 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2930 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2932 break;
2935 case D3DTBLEND_ADD:
2936 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2937 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2938 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2939 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2940 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2941 break;
2943 case D3DTBLEND_MODULATEALPHA:
2944 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2945 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2946 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2947 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2948 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2949 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2950 break;
2952 case D3DTBLEND_COPY:
2953 case D3DTBLEND_DECAL:
2954 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2955 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2956 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2957 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2958 break;
2960 case D3DTBLEND_DECALALPHA:
2961 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2962 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2963 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2964 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2965 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2966 break;
2968 default:
2969 ERR("Unhandled texture environment %d !\n",Value);
2972 hr = D3D_OK;
2973 break;
2976 default:
2977 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, RenderStateType, Value);
2978 break;
2981 LeaveCriticalSection(&ddraw_cs);
2983 return hr;
2986 static HRESULT WINAPI
2987 Thunk_IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2988 D3DRENDERSTATETYPE RenderStateType,
2989 DWORD Value)
2991 IDirect3DDeviceImpl *This = device_from_device2(iface);
2993 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2995 return IDirect3DDevice3_SetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, RenderStateType, Value);
2998 /*****************************************************************************
2999 * Direct3DDevice3::SetLightState
3001 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
3002 * light states are forwarded to Direct3DDevice7 render states
3004 * Version 2 and 3
3006 * Params:
3007 * LightStateType: The light state to change
3008 * Value: The value to assign to that light state
3010 * Returns:
3011 * D3D_OK on success
3012 * DDERR_INVALIDPARAMS if the parameters were incorrect
3013 * Also check IDirect3DDevice7::SetRenderState
3015 *****************************************************************************/
3016 static HRESULT WINAPI
3017 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
3018 D3DLIGHTSTATETYPE LightStateType,
3019 DWORD Value)
3021 IDirect3DDeviceImpl *This = device_from_device3(iface);
3022 HRESULT hr;
3024 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3026 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3028 TRACE("Unexpected Light State Type\n");
3029 return DDERR_INVALIDPARAMS;
3032 EnterCriticalSection(&ddraw_cs);
3033 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3035 IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
3036 if (!m)
3038 WARN("Invalid material handle.\n");
3039 LeaveCriticalSection(&ddraw_cs);
3040 return DDERR_INVALIDPARAMS;
3043 TRACE(" activating material %p.\n", m);
3044 material_activate(m);
3046 This->material = Value;
3048 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3050 switch (Value)
3052 case D3DCOLOR_MONO:
3053 ERR("DDCOLOR_MONO should not happen!\n");
3054 break;
3055 case D3DCOLOR_RGB:
3056 /* We are already in this mode */
3057 TRACE("Setting color model to RGB (no-op).\n");
3058 break;
3059 default:
3060 ERR("Unknown color model!\n");
3061 LeaveCriticalSection(&ddraw_cs);
3062 return DDERR_INVALIDPARAMS;
3065 else
3067 D3DRENDERSTATETYPE rs;
3068 switch (LightStateType)
3070 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3071 rs = D3DRENDERSTATE_AMBIENT;
3072 break;
3073 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3074 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3075 break;
3076 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3077 rs = D3DRENDERSTATE_FOGSTART;
3078 break;
3079 case D3DLIGHTSTATE_FOGEND: /* 6 */
3080 rs = D3DRENDERSTATE_FOGEND;
3081 break;
3082 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3083 rs = D3DRENDERSTATE_FOGDENSITY;
3084 break;
3085 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3086 rs = D3DRENDERSTATE_COLORVERTEX;
3087 break;
3088 default:
3089 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3090 LeaveCriticalSection(&ddraw_cs);
3091 return DDERR_INVALIDPARAMS;
3094 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, rs, Value);
3095 LeaveCriticalSection(&ddraw_cs);
3096 return hr;
3099 LeaveCriticalSection(&ddraw_cs);
3100 return D3D_OK;
3103 static HRESULT WINAPI
3104 Thunk_IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3105 D3DLIGHTSTATETYPE LightStateType,
3106 DWORD Value)
3108 IDirect3DDeviceImpl *This = device_from_device2(iface);
3110 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3112 return IDirect3DDevice3_SetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3115 /*****************************************************************************
3116 * IDirect3DDevice3::GetLightState
3118 * Returns the current setting of a light state. The state is read from
3119 * the Direct3DDevice7 render state.
3121 * Version 2 and 3
3123 * Params:
3124 * LightStateType: The light state to return
3125 * Value: The address to store the light state setting at
3127 * Returns:
3128 * D3D_OK on success
3129 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3130 * Also see IDirect3DDevice7::GetRenderState
3132 *****************************************************************************/
3133 static HRESULT WINAPI
3134 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3135 D3DLIGHTSTATETYPE LightStateType,
3136 DWORD *Value)
3138 IDirect3DDeviceImpl *This = device_from_device3(iface);
3139 HRESULT hr;
3141 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3143 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3145 TRACE("Unexpected Light State Type\n");
3146 return DDERR_INVALIDPARAMS;
3149 if(!Value)
3150 return DDERR_INVALIDPARAMS;
3152 EnterCriticalSection(&ddraw_cs);
3153 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3155 *Value = This->material;
3157 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3159 *Value = D3DCOLOR_RGB;
3161 else
3163 D3DRENDERSTATETYPE rs;
3164 switch (LightStateType)
3166 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3167 rs = D3DRENDERSTATE_AMBIENT;
3168 break;
3169 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3170 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3171 break;
3172 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3173 rs = D3DRENDERSTATE_FOGSTART;
3174 break;
3175 case D3DLIGHTSTATE_FOGEND: /* 6 */
3176 rs = D3DRENDERSTATE_FOGEND;
3177 break;
3178 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3179 rs = D3DRENDERSTATE_FOGDENSITY;
3180 break;
3181 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3182 rs = D3DRENDERSTATE_COLORVERTEX;
3183 break;
3184 default:
3185 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3186 LeaveCriticalSection(&ddraw_cs);
3187 return DDERR_INVALIDPARAMS;
3190 hr = IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, rs, Value);
3191 LeaveCriticalSection(&ddraw_cs);
3192 return hr;
3195 LeaveCriticalSection(&ddraw_cs);
3196 return D3D_OK;
3199 static HRESULT WINAPI
3200 Thunk_IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3201 D3DLIGHTSTATETYPE LightStateType,
3202 DWORD *Value)
3204 IDirect3DDeviceImpl *This = device_from_device2(iface);
3206 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3208 return IDirect3DDevice3_GetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3211 /*****************************************************************************
3212 * IDirect3DDevice7::SetTransform
3214 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3215 * in include/d3dtypes.h.
3216 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3217 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3218 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3220 * Version 2, 3 and 7
3222 * Params:
3223 * TransformStateType: transform state to set
3224 * Matrix: Matrix to assign to the state
3226 * Returns:
3227 * D3D_OK on success
3228 * DDERR_INVALIDPARAMS if Matrix == NULL
3229 * For details see IWineD3DDevice::SetTransform
3231 *****************************************************************************/
3232 static HRESULT
3233 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3234 D3DTRANSFORMSTATETYPE TransformStateType,
3235 D3DMATRIX *Matrix)
3237 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3238 D3DTRANSFORMSTATETYPE type;
3239 HRESULT hr;
3241 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3243 switch(TransformStateType)
3245 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3246 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3247 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3248 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3249 default: type = TransformStateType;
3252 if(!Matrix)
3253 return DDERR_INVALIDPARAMS;
3255 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3256 EnterCriticalSection(&ddraw_cs);
3257 hr = IWineD3DDevice_SetTransform(This->wineD3DDevice,
3258 type,
3259 (WINED3DMATRIX*) Matrix);
3260 LeaveCriticalSection(&ddraw_cs);
3261 return hr;
3264 static HRESULT WINAPI
3265 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3266 D3DTRANSFORMSTATETYPE TransformStateType,
3267 D3DMATRIX *Matrix)
3269 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3272 static HRESULT WINAPI
3273 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3274 D3DTRANSFORMSTATETYPE TransformStateType,
3275 D3DMATRIX *Matrix)
3277 HRESULT hr;
3278 WORD old_fpucw;
3280 old_fpucw = d3d_fpu_setup();
3281 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3282 set_fpu_control_word(old_fpucw);
3284 return hr;
3287 static HRESULT WINAPI
3288 Thunk_IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3289 D3DTRANSFORMSTATETYPE TransformStateType,
3290 D3DMATRIX *D3DMatrix)
3292 IDirect3DDeviceImpl *This = device_from_device3(iface);
3294 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3296 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3299 static HRESULT WINAPI
3300 Thunk_IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3301 D3DTRANSFORMSTATETYPE TransformStateType,
3302 D3DMATRIX *D3DMatrix)
3304 IDirect3DDeviceImpl *This = device_from_device2(iface);
3306 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3308 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3311 /*****************************************************************************
3312 * IDirect3DDevice7::GetTransform
3314 * Returns the matrix assigned to a transform state
3315 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3316 * SetTransform
3318 * Params:
3319 * TransformStateType: State to read the matrix from
3320 * Matrix: Address to store the matrix at
3322 * Returns:
3323 * D3D_OK on success
3324 * DDERR_INVALIDPARAMS if Matrix == NULL
3325 * For details, see IWineD3DDevice::GetTransform
3327 *****************************************************************************/
3328 static HRESULT
3329 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3330 D3DTRANSFORMSTATETYPE TransformStateType,
3331 D3DMATRIX *Matrix)
3333 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3334 D3DTRANSFORMSTATETYPE type;
3335 HRESULT hr;
3337 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3339 switch(TransformStateType)
3341 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3342 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3343 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3344 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3345 default: type = TransformStateType;
3348 if(!Matrix)
3349 return DDERR_INVALIDPARAMS;
3351 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3352 EnterCriticalSection(&ddraw_cs);
3353 hr = IWineD3DDevice_GetTransform(This->wineD3DDevice, type, (WINED3DMATRIX*) Matrix);
3354 LeaveCriticalSection(&ddraw_cs);
3355 return hr;
3358 static HRESULT WINAPI
3359 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3360 D3DTRANSFORMSTATETYPE TransformStateType,
3361 D3DMATRIX *Matrix)
3363 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3366 static HRESULT WINAPI
3367 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3368 D3DTRANSFORMSTATETYPE TransformStateType,
3369 D3DMATRIX *Matrix)
3371 HRESULT hr;
3372 WORD old_fpucw;
3374 old_fpucw = d3d_fpu_setup();
3375 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3376 set_fpu_control_word(old_fpucw);
3378 return hr;
3381 static HRESULT WINAPI
3382 Thunk_IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3383 D3DTRANSFORMSTATETYPE TransformStateType,
3384 D3DMATRIX *D3DMatrix)
3386 IDirect3DDeviceImpl *This = device_from_device3(iface);
3388 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3390 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3393 static HRESULT WINAPI
3394 Thunk_IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3395 D3DTRANSFORMSTATETYPE TransformStateType,
3396 D3DMATRIX *D3DMatrix)
3398 IDirect3DDeviceImpl *This = device_from_device2(iface);
3400 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3402 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3405 /*****************************************************************************
3406 * IDirect3DDevice7::MultiplyTransform
3408 * Multiplies the already-set transform matrix of a transform state
3409 * with another matrix. For the world matrix, see SetTransform
3411 * Version 2, 3 and 7
3413 * Params:
3414 * TransformStateType: Transform state to multiply
3415 * D3DMatrix Matrix to multiply with.
3417 * Returns
3418 * D3D_OK on success
3419 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3420 * For details, see IWineD3DDevice::MultiplyTransform
3422 *****************************************************************************/
3423 static HRESULT
3424 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3425 D3DTRANSFORMSTATETYPE TransformStateType,
3426 D3DMATRIX *D3DMatrix)
3428 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3429 HRESULT hr;
3430 D3DTRANSFORMSTATETYPE type;
3432 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3434 switch(TransformStateType)
3436 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3437 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3438 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3439 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3440 default: type = TransformStateType;
3443 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3444 EnterCriticalSection(&ddraw_cs);
3445 hr = IWineD3DDevice_MultiplyTransform(This->wineD3DDevice,
3446 type,
3447 (WINED3DMATRIX*) D3DMatrix);
3448 LeaveCriticalSection(&ddraw_cs);
3449 return hr;
3452 static HRESULT WINAPI
3453 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3454 D3DTRANSFORMSTATETYPE TransformStateType,
3455 D3DMATRIX *D3DMatrix)
3457 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3460 static HRESULT WINAPI
3461 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3462 D3DTRANSFORMSTATETYPE TransformStateType,
3463 D3DMATRIX *D3DMatrix)
3465 HRESULT hr;
3466 WORD old_fpucw;
3468 old_fpucw = d3d_fpu_setup();
3469 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3470 set_fpu_control_word(old_fpucw);
3472 return hr;
3475 static HRESULT WINAPI
3476 Thunk_IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3477 D3DTRANSFORMSTATETYPE TransformStateType,
3478 D3DMATRIX *D3DMatrix)
3480 IDirect3DDeviceImpl *This = device_from_device3(iface);
3482 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3484 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3487 static HRESULT WINAPI
3488 Thunk_IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3489 D3DTRANSFORMSTATETYPE TransformStateType,
3490 D3DMATRIX *D3DMatrix)
3492 IDirect3DDeviceImpl *This = device_from_device2(iface);
3494 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3496 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3499 /*****************************************************************************
3500 * IDirect3DDevice7::DrawPrimitive
3502 * Draws primitives based on vertices in an application-provided pointer
3504 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3505 * an FVF format for D3D7
3507 * Params:
3508 * PrimitiveType: The type of the primitives to draw
3509 * Vertex type: Flexible vertex format vertex description
3510 * Vertices: Pointer to the vertex array
3511 * VertexCount: The number of vertices to draw
3512 * Flags: As usual a few flags
3514 * Returns:
3515 * D3D_OK on success
3516 * DDERR_INVALIDPARAMS if Vertices is NULL
3517 * For details, see IWineD3DDevice::DrawPrimitiveUP
3519 *****************************************************************************/
3520 static HRESULT
3521 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3522 D3DPRIMITIVETYPE PrimitiveType,
3523 DWORD VertexType,
3524 void *Vertices,
3525 DWORD VertexCount,
3526 DWORD Flags)
3528 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3529 UINT stride;
3530 HRESULT hr;
3532 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3533 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3535 if(!Vertices)
3536 return DDERR_INVALIDPARAMS;
3538 /* Get the stride */
3539 stride = get_flexible_vertex_size(VertexType);
3541 /* Set the FVF */
3542 EnterCriticalSection(&ddraw_cs);
3543 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice, ddraw_find_decl(This->ddraw, VertexType));
3544 if(hr != D3D_OK)
3546 LeaveCriticalSection(&ddraw_cs);
3547 return hr;
3550 /* This method translates to the user pointer draw of WineD3D */
3551 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3552 hr = IWineD3DDevice_DrawPrimitiveUP(This->wineD3DDevice, VertexCount, Vertices, stride);
3553 LeaveCriticalSection(&ddraw_cs);
3554 return hr;
3557 static HRESULT WINAPI
3558 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3559 D3DPRIMITIVETYPE PrimitiveType,
3560 DWORD VertexType,
3561 void *Vertices,
3562 DWORD VertexCount,
3563 DWORD Flags)
3565 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3568 static HRESULT WINAPI
3569 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3570 D3DPRIMITIVETYPE PrimitiveType,
3571 DWORD VertexType,
3572 void *Vertices,
3573 DWORD VertexCount,
3574 DWORD Flags)
3576 HRESULT hr;
3577 WORD old_fpucw;
3579 old_fpucw = d3d_fpu_setup();
3580 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3581 set_fpu_control_word(old_fpucw);
3583 return hr;
3586 static HRESULT WINAPI
3587 Thunk_IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3588 D3DPRIMITIVETYPE PrimitiveType,
3589 DWORD VertexType,
3590 void *Vertices,
3591 DWORD VertexCount,
3592 DWORD Flags)
3594 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3595 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3597 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3598 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3601 static HRESULT WINAPI
3602 Thunk_IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3603 D3DPRIMITIVETYPE PrimitiveType,
3604 D3DVERTEXTYPE VertexType,
3605 void *Vertices,
3606 DWORD VertexCount,
3607 DWORD Flags)
3609 DWORD FVF;
3611 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3612 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3614 switch(VertexType)
3616 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3617 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3618 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3619 default:
3620 ERR("Unexpected vertex type %d\n", VertexType);
3621 return DDERR_INVALIDPARAMS; /* Should never happen */
3624 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3625 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3628 /*****************************************************************************
3629 * IDirect3DDevice7::DrawIndexedPrimitive
3631 * Draws vertices from an application-provided pointer, based on the index
3632 * numbers in a WORD array.
3634 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3635 * an FVF format for D3D7
3637 * Params:
3638 * PrimitiveType: The primitive type to draw
3639 * VertexType: The FVF vertex description
3640 * Vertices: Pointer to the vertex array
3641 * VertexCount: ?
3642 * Indices: Pointer to the index array
3643 * IndexCount: Number of indices = Number of vertices to draw
3644 * Flags: As usual, some flags
3646 * Returns:
3647 * D3D_OK on success
3648 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3649 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3651 *****************************************************************************/
3652 static HRESULT
3653 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3654 D3DPRIMITIVETYPE PrimitiveType,
3655 DWORD VertexType,
3656 void *Vertices,
3657 DWORD VertexCount,
3658 WORD *Indices,
3659 DWORD IndexCount,
3660 DWORD Flags)
3662 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3663 HRESULT hr;
3665 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3666 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3668 /* Set the D3DDevice's FVF */
3669 EnterCriticalSection(&ddraw_cs);
3670 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice, ddraw_find_decl(This->ddraw, VertexType));
3671 if(FAILED(hr))
3673 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3674 LeaveCriticalSection(&ddraw_cs);
3675 return hr;
3678 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3679 hr = IWineD3DDevice_DrawIndexedPrimitiveUP(This->wineD3DDevice, IndexCount, Indices,
3680 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3681 LeaveCriticalSection(&ddraw_cs);
3682 return hr;
3685 static HRESULT WINAPI
3686 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3687 D3DPRIMITIVETYPE PrimitiveType,
3688 DWORD VertexType,
3689 void *Vertices,
3690 DWORD VertexCount,
3691 WORD *Indices,
3692 DWORD IndexCount,
3693 DWORD Flags)
3695 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3698 static HRESULT WINAPI
3699 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3700 D3DPRIMITIVETYPE PrimitiveType,
3701 DWORD VertexType,
3702 void *Vertices,
3703 DWORD VertexCount,
3704 WORD *Indices,
3705 DWORD IndexCount,
3706 DWORD Flags)
3708 HRESULT hr;
3709 WORD old_fpucw;
3711 old_fpucw = d3d_fpu_setup();
3712 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3713 set_fpu_control_word(old_fpucw);
3715 return hr;
3718 static HRESULT WINAPI
3719 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3720 D3DPRIMITIVETYPE PrimitiveType,
3721 DWORD VertexType,
3722 void *Vertices,
3723 DWORD VertexCount,
3724 WORD *Indices,
3725 DWORD IndexCount,
3726 DWORD Flags)
3728 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3729 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3731 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3732 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3735 static HRESULT WINAPI
3736 Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3737 D3DPRIMITIVETYPE PrimitiveType,
3738 D3DVERTEXTYPE VertexType,
3739 void *Vertices,
3740 DWORD VertexCount,
3741 WORD *Indices,
3742 DWORD IndexCount,
3743 DWORD Flags)
3745 DWORD FVF;
3747 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3748 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3750 switch(VertexType)
3752 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3753 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3754 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3755 default:
3756 ERR("Unexpected vertex type %d\n", VertexType);
3757 return DDERR_INVALIDPARAMS; /* Should never happen */
3760 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3761 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3764 /*****************************************************************************
3765 * IDirect3DDevice7::SetClipStatus
3767 * Sets the clip status. This defines things as clipping conditions and
3768 * the extents of the clipping region.
3770 * Version 2, 3 and 7
3772 * Params:
3773 * ClipStatus:
3775 * Returns:
3776 * D3D_OK because it's a stub
3777 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3779 *****************************************************************************/
3780 static HRESULT WINAPI
3781 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3782 D3DCLIPSTATUS *ClipStatus)
3784 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3786 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3787 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3789 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3790 return D3D_OK;
3793 static HRESULT WINAPI
3794 Thunk_IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3795 D3DCLIPSTATUS *ClipStatus)
3797 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3799 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3802 static HRESULT WINAPI
3803 Thunk_IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3804 D3DCLIPSTATUS *ClipStatus)
3806 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3808 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3811 /*****************************************************************************
3812 * IDirect3DDevice7::GetClipStatus
3814 * Returns the clip status
3816 * Params:
3817 * ClipStatus: Address to write the clip status to
3819 * Returns:
3820 * D3D_OK because it's a stub
3822 *****************************************************************************/
3823 static HRESULT WINAPI
3824 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3825 D3DCLIPSTATUS *ClipStatus)
3827 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3829 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3830 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3831 return D3D_OK;
3834 static HRESULT WINAPI
3835 Thunk_IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3836 D3DCLIPSTATUS *ClipStatus)
3838 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3840 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3843 static HRESULT WINAPI
3844 Thunk_IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3845 D3DCLIPSTATUS *ClipStatus)
3847 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3849 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3852 /*****************************************************************************
3853 * IDirect3DDevice::DrawPrimitiveStrided
3855 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3857 * Version 3 and 7
3859 * Params:
3860 * PrimitiveType: The primitive type to draw
3861 * VertexType: The FVF description of the vertices to draw (for the stride??)
3862 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3863 * the vertex data locations
3864 * VertexCount: The number of vertices to draw
3865 * Flags: Some flags
3867 * Returns:
3868 * D3D_OK, because it's a stub
3869 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3870 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3872 *****************************************************************************/
3873 static HRESULT
3874 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3875 D3DPRIMITIVETYPE PrimitiveType,
3876 DWORD VertexType,
3877 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3878 DWORD VertexCount,
3879 DWORD Flags)
3881 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3882 WineDirect3DVertexStridedData WineD3DStrided;
3883 DWORD i;
3884 HRESULT hr;
3886 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3887 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3889 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3890 /* Get the strided data right. the wined3d structure is a bit bigger
3891 * Watch out: The contents of the strided data are determined by the fvf,
3892 * not by the members set in D3DDrawPrimStrideData. So it's valid
3893 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3894 * not set in the fvf.
3896 if(VertexType & D3DFVF_POSITION_MASK)
3898 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3899 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3900 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3901 if (VertexType & D3DFVF_XYZRHW)
3903 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3904 WineD3DStrided.position_transformed = TRUE;
3905 } else
3906 WineD3DStrided.position_transformed = FALSE;
3909 if(VertexType & D3DFVF_NORMAL)
3911 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3912 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3913 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3916 if(VertexType & D3DFVF_DIFFUSE)
3918 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3919 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3920 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3923 if(VertexType & D3DFVF_SPECULAR)
3925 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3926 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3927 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3930 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3932 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3934 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3935 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3936 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3937 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3938 default: ERR("Unexpected texture coordinate size %d\n",
3939 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3941 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3942 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3945 /* WineD3D doesn't need the FVF here */
3946 EnterCriticalSection(&ddraw_cs);
3947 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3948 hr = IWineD3DDevice_DrawPrimitiveStrided(This->wineD3DDevice, VertexCount, &WineD3DStrided);
3949 LeaveCriticalSection(&ddraw_cs);
3950 return hr;
3953 static HRESULT WINAPI
3954 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3955 D3DPRIMITIVETYPE PrimitiveType,
3956 DWORD VertexType,
3957 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3958 DWORD VertexCount,
3959 DWORD Flags)
3961 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3964 static HRESULT WINAPI
3965 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3966 D3DPRIMITIVETYPE PrimitiveType,
3967 DWORD VertexType,
3968 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3969 DWORD VertexCount,
3970 DWORD Flags)
3972 HRESULT hr;
3973 WORD old_fpucw;
3975 old_fpucw = d3d_fpu_setup();
3976 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3977 set_fpu_control_word(old_fpucw);
3979 return hr;
3982 static HRESULT WINAPI
3983 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3984 D3DPRIMITIVETYPE PrimitiveType,
3985 DWORD VertexType,
3986 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3987 DWORD VertexCount,
3988 DWORD Flags)
3990 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3991 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3993 return IDirect3DDevice7_DrawPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
3994 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3997 /*****************************************************************************
3998 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
4000 * Draws primitives specified by strided data locations based on indices
4002 * Version 3 and 7
4004 * Params:
4005 * PrimitiveType:
4007 * Returns:
4008 * D3D_OK, because it's a stub
4009 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
4010 * (DDERR_INVALIDPARAMS if Indices is NULL)
4011 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
4013 *****************************************************************************/
4014 static HRESULT
4015 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
4016 D3DPRIMITIVETYPE PrimitiveType,
4017 DWORD VertexType,
4018 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4019 DWORD VertexCount,
4020 WORD *Indices,
4021 DWORD IndexCount,
4022 DWORD Flags)
4024 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4025 WineDirect3DVertexStridedData WineD3DStrided;
4026 DWORD i;
4027 HRESULT hr;
4029 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4030 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4032 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
4033 /* Get the strided data right. the wined3d structure is a bit bigger
4034 * Watch out: The contents of the strided data are determined by the fvf,
4035 * not by the members set in D3DDrawPrimStrideData. So it's valid
4036 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
4037 * not set in the fvf.
4039 if(VertexType & D3DFVF_POSITION_MASK)
4041 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
4042 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
4043 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
4044 if (VertexType & D3DFVF_XYZRHW)
4046 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
4047 WineD3DStrided.position_transformed = TRUE;
4048 } else
4049 WineD3DStrided.position_transformed = FALSE;
4052 if(VertexType & D3DFVF_NORMAL)
4054 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
4055 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
4056 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
4059 if(VertexType & D3DFVF_DIFFUSE)
4061 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
4062 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
4063 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
4066 if(VertexType & D3DFVF_SPECULAR)
4068 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
4069 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
4070 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
4073 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
4075 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
4077 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
4078 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
4079 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
4080 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
4081 default: ERR("Unexpected texture coordinate size %d\n",
4082 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4084 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4085 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4088 /* WineD3D doesn't need the FVF here */
4089 EnterCriticalSection(&ddraw_cs);
4090 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4091 hr = IWineD3DDevice_DrawIndexedPrimitiveStrided(This->wineD3DDevice,
4092 IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
4093 LeaveCriticalSection(&ddraw_cs);
4094 return hr;
4097 static HRESULT WINAPI
4098 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4099 D3DPRIMITIVETYPE PrimitiveType,
4100 DWORD VertexType,
4101 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4102 DWORD VertexCount,
4103 WORD *Indices,
4104 DWORD IndexCount,
4105 DWORD Flags)
4107 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4110 static HRESULT WINAPI
4111 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4112 D3DPRIMITIVETYPE PrimitiveType,
4113 DWORD VertexType,
4114 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4115 DWORD VertexCount,
4116 WORD *Indices,
4117 DWORD IndexCount,
4118 DWORD Flags)
4120 HRESULT hr;
4121 WORD old_fpucw;
4123 old_fpucw = d3d_fpu_setup();
4124 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4125 set_fpu_control_word(old_fpucw);
4127 return hr;
4130 static HRESULT WINAPI
4131 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4132 D3DPRIMITIVETYPE PrimitiveType,
4133 DWORD VertexType,
4134 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4135 DWORD VertexCount,
4136 WORD *Indices,
4137 DWORD IndexCount,
4138 DWORD Flags)
4140 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4141 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4143 return IDirect3DDevice7_DrawIndexedPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
4144 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4147 /*****************************************************************************
4148 * IDirect3DDevice7::DrawPrimitiveVB
4150 * Draws primitives from a vertex buffer to the screen.
4152 * Version 3 and 7
4154 * Params:
4155 * PrimitiveType: Type of primitive to be rendered.
4156 * D3DVertexBuf: Source Vertex Buffer
4157 * StartVertex: Index of the first vertex from the buffer to be rendered
4158 * NumVertices: Number of vertices to be rendered
4159 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4161 * Return values
4162 * D3D_OK on success
4163 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4165 *****************************************************************************/
4166 static HRESULT
4167 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4168 D3DPRIMITIVETYPE PrimitiveType,
4169 IDirect3DVertexBuffer7 *D3DVertexBuf,
4170 DWORD StartVertex,
4171 DWORD NumVertices,
4172 DWORD Flags)
4174 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4175 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4176 HRESULT hr;
4177 DWORD stride;
4179 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4180 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4182 /* Sanity checks */
4183 if(!vb)
4185 ERR("(%p) No Vertex buffer specified\n", This);
4186 return DDERR_INVALIDPARAMS;
4188 stride = get_flexible_vertex_size(vb->fvf);
4190 EnterCriticalSection(&ddraw_cs);
4191 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4192 vb->wineD3DVertexDeclaration);
4193 if(FAILED(hr))
4195 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4196 LeaveCriticalSection(&ddraw_cs);
4197 return hr;
4200 /* Set the vertex stream source */
4201 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4202 0 /* StreamNumber */,
4203 vb->wineD3DVertexBuffer,
4204 0 /* StartVertex - we pass this to DrawPrimitive */,
4205 stride);
4206 if(hr != D3D_OK)
4208 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4209 LeaveCriticalSection(&ddraw_cs);
4210 return hr;
4213 /* Now draw the primitives */
4214 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4215 hr = IWineD3DDevice_DrawPrimitive(This->wineD3DDevice, StartVertex, NumVertices);
4216 LeaveCriticalSection(&ddraw_cs);
4217 return hr;
4220 static HRESULT WINAPI
4221 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4222 D3DPRIMITIVETYPE PrimitiveType,
4223 IDirect3DVertexBuffer7 *D3DVertexBuf,
4224 DWORD StartVertex,
4225 DWORD NumVertices,
4226 DWORD Flags)
4228 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4231 static HRESULT WINAPI
4232 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4233 D3DPRIMITIVETYPE PrimitiveType,
4234 IDirect3DVertexBuffer7 *D3DVertexBuf,
4235 DWORD StartVertex,
4236 DWORD NumVertices,
4237 DWORD Flags)
4239 HRESULT hr;
4240 WORD old_fpucw;
4242 old_fpucw = d3d_fpu_setup();
4243 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4244 set_fpu_control_word(old_fpucw);
4246 return hr;
4249 static HRESULT WINAPI
4250 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4251 D3DPRIMITIVETYPE PrimitiveType,
4252 IDirect3DVertexBuffer *D3DVertexBuf,
4253 DWORD StartVertex,
4254 DWORD NumVertices,
4255 DWORD Flags)
4257 IDirect3DVertexBufferImpl *vb = D3DVertexBuf ? vb_from_vb1(D3DVertexBuf) : NULL;
4259 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4260 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4262 return IDirect3DDevice7_DrawPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4263 PrimitiveType, (IDirect3DVertexBuffer7 *)vb, StartVertex, NumVertices, Flags);
4267 /*****************************************************************************
4268 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4270 * Draws primitives from a vertex buffer to the screen
4272 * Params:
4273 * PrimitiveType: Type of primitive to be rendered.
4274 * D3DVertexBuf: Source Vertex Buffer
4275 * StartVertex: Index of the first vertex from the buffer to be rendered
4276 * NumVertices: Number of vertices to be rendered
4277 * Indices: Array of DWORDs used to index into the Vertices
4278 * IndexCount: Number of indices in Indices
4279 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4281 * Return values
4283 *****************************************************************************/
4284 static HRESULT
4285 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4286 D3DPRIMITIVETYPE PrimitiveType,
4287 IDirect3DVertexBuffer7 *D3DVertexBuf,
4288 DWORD StartVertex,
4289 DWORD NumVertices,
4290 WORD *Indices,
4291 DWORD IndexCount,
4292 DWORD Flags)
4294 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4295 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4296 DWORD stride = get_flexible_vertex_size(vb->fvf);
4297 WORD *LockedIndices;
4298 HRESULT hr;
4299 WINED3DBUFFER_DESC desc;
4301 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4302 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4304 /* Steps:
4305 * 1) Upload the Indices to the index buffer
4306 * 2) Set the index source
4307 * 3) Set the Vertex Buffer as the Stream source
4308 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4311 EnterCriticalSection(&ddraw_cs);
4313 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4314 vb->wineD3DVertexDeclaration);
4315 if(FAILED(hr))
4317 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4318 LeaveCriticalSection(&ddraw_cs);
4319 return hr;
4322 /* check that the buffer is large enough to hold the indices,
4323 * reallocate if necessary. */
4324 IWineD3DBuffer_GetDesc(This->indexbuffer, &desc);
4325 if (desc.Size < IndexCount * sizeof(WORD))
4327 UINT size = max(desc.Size * 2, IndexCount * sizeof(WORD));
4328 IWineD3DBuffer *buffer;
4329 IParentImpl *parent;
4331 TRACE("Growing index buffer to %u bytes\n", size);
4333 parent = IWineD3DBuffer_GetParent(This->indexbuffer);
4334 hr = IWineD3DDevice_CreateIndexBuffer(This->wineD3DDevice, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4335 WINED3DPOOL_DEFAULT, parent, &ddraw_null_wined3d_parent_ops, &buffer);
4336 if (FAILED(hr))
4338 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4339 LeaveCriticalSection(&ddraw_cs);
4340 return hr;
4343 IWineD3DBuffer_Release(This->indexbuffer);
4344 This->indexbuffer = buffer;
4346 parent->child = (IUnknown *)buffer;
4349 /* copy the index stream into the index buffer.
4350 * A new IWineD3DDevice method could be created
4351 * which takes an user pointer containing the indices
4352 * or a SetData-Method for the index buffer, which
4353 * overrides the index buffer data with our pointer.
4355 hr = IWineD3DBuffer_Map(This->indexbuffer,
4356 0 /* OffSetToLock */,
4357 IndexCount * sizeof(WORD),
4358 (BYTE **) &LockedIndices,
4359 0 /* Flags */);
4360 if(hr != D3D_OK)
4362 ERR("(%p) IWineD3DBuffer::Map failed with hr = %08x\n", This, hr);
4363 LeaveCriticalSection(&ddraw_cs);
4364 return hr;
4366 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4367 IWineD3DBuffer_Unmap(This->indexbuffer);
4369 /* Set the index stream */
4370 IWineD3DDevice_SetBaseVertexIndex(This->wineD3DDevice, StartVertex);
4371 hr = IWineD3DDevice_SetIndexBuffer(This->wineD3DDevice, This->indexbuffer,
4372 WINED3DFMT_R16_UINT);
4374 /* Set the vertex stream source */
4375 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4376 0 /* StreamNumber */,
4377 vb->wineD3DVertexBuffer,
4378 0 /* offset, we pass this to DrawIndexedPrimitive */,
4379 stride);
4380 if(hr != D3D_OK)
4382 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4383 LeaveCriticalSection(&ddraw_cs);
4384 return hr;
4388 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4389 hr = IWineD3DDevice_DrawIndexedPrimitive(This->wineD3DDevice, 0 /* StartIndex */, IndexCount);
4391 LeaveCriticalSection(&ddraw_cs);
4392 return hr;
4395 static HRESULT WINAPI
4396 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4397 D3DPRIMITIVETYPE PrimitiveType,
4398 IDirect3DVertexBuffer7 *D3DVertexBuf,
4399 DWORD StartVertex,
4400 DWORD NumVertices,
4401 WORD *Indices,
4402 DWORD IndexCount,
4403 DWORD Flags)
4405 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4408 static HRESULT WINAPI
4409 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4410 D3DPRIMITIVETYPE PrimitiveType,
4411 IDirect3DVertexBuffer7 *D3DVertexBuf,
4412 DWORD StartVertex,
4413 DWORD NumVertices,
4414 WORD *Indices,
4415 DWORD IndexCount,
4416 DWORD Flags)
4418 HRESULT hr;
4419 WORD old_fpucw;
4421 old_fpucw = d3d_fpu_setup();
4422 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4423 set_fpu_control_word(old_fpucw);
4425 return hr;
4428 static HRESULT WINAPI
4429 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4430 D3DPRIMITIVETYPE PrimitiveType,
4431 IDirect3DVertexBuffer *D3DVertexBuf,
4432 WORD *Indices,
4433 DWORD IndexCount,
4434 DWORD Flags)
4436 IDirect3DVertexBufferImpl *VB = vb_from_vb1(D3DVertexBuf);
4438 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4439 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4441 return IDirect3DDevice7_DrawIndexedPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4442 PrimitiveType, (IDirect3DVertexBuffer7 *)VB, 0, IndexCount, Indices, IndexCount, Flags);
4445 /*****************************************************************************
4446 * IDirect3DDevice7::ComputeSphereVisibility
4448 * Calculates the visibility of spheres in the current viewport. The spheres
4449 * are passed in the Centers and Radii arrays, the results are passed back
4450 * in the ReturnValues array. Return values are either completely visible,
4451 * partially visible or completely invisible.
4452 * The return value consist of a combination of D3DCLIP_* flags, or it's
4453 * 0 if the sphere is completely visible(according to the SDK, not checked)
4455 * Version 3 and 7
4457 * Params:
4458 * Centers: Array containing the sphere centers
4459 * Radii: Array containing the sphere radii
4460 * NumSpheres: The number of centers and radii in the arrays
4461 * Flags: Some flags
4462 * ReturnValues: Array to write the results to
4464 * Returns:
4465 * D3D_OK
4466 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4467 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4468 * is singular)
4470 *****************************************************************************/
4472 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4474 float distance, norm;
4476 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4477 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4479 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4480 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4481 return 0;
4484 static HRESULT WINAPI
4485 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4486 D3DVECTOR *Centers,
4487 D3DVALUE *Radii,
4488 DWORD NumSpheres,
4489 DWORD Flags,
4490 DWORD *ReturnValues)
4492 D3DMATRIX m, temp;
4493 D3DVALUE origin_plane[6];
4494 D3DVECTOR vec[6];
4495 HRESULT hr;
4496 UINT i, j;
4498 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4499 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4501 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4502 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4503 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4504 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4505 multiply_matrix(&m, &temp, &m);
4507 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4508 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4509 multiply_matrix(&m, &temp, &m);
4511 /* Left plane */
4512 vec[0].u1.x = m._14 + m._11;
4513 vec[0].u2.y = m._24 + m._21;
4514 vec[0].u3.z = m._34 + m._31;
4515 origin_plane[0] = m._44 + m._41;
4517 /* Right plane */
4518 vec[1].u1.x = m._14 - m._11;
4519 vec[1].u2.y = m._24 - m._21;
4520 vec[1].u3.z = m._34 - m._31;
4521 origin_plane[1] = m._44 - m._41;
4523 /* Top plane */
4524 vec[2].u1.x = m._14 - m._12;
4525 vec[2].u2.y = m._24 - m._22;
4526 vec[2].u3.z = m._34 - m._32;
4527 origin_plane[2] = m._44 - m._42;
4529 /* Bottom plane */
4530 vec[3].u1.x = m._14 + m._12;
4531 vec[3].u2.y = m._24 + m._22;
4532 vec[3].u3.z = m._34 + m._32;
4533 origin_plane[3] = m._44 + m._42;
4535 /* Front plane */
4536 vec[4].u1.x = m._13;
4537 vec[4].u2.y = m._23;
4538 vec[4].u3.z = m._33;
4539 origin_plane[4] = m._43;
4541 /* Back plane*/
4542 vec[5].u1.x = m._14 - m._13;
4543 vec[5].u2.y = m._24 - m._23;
4544 vec[5].u3.z = m._34 - m._33;
4545 origin_plane[5] = m._44 - m._43;
4547 for(i=0; i<NumSpheres; i++)
4549 ReturnValues[i] = 0;
4550 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4553 return D3D_OK;
4556 static HRESULT WINAPI
4557 Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4558 D3DVECTOR *Centers,
4559 D3DVALUE *Radii,
4560 DWORD NumSpheres,
4561 DWORD Flags,
4562 DWORD *ReturnValues)
4564 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4565 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4567 return IDirect3DDevice7_ComputeSphereVisibility((IDirect3DDevice7 *)device_from_device3(iface),
4568 Centers, Radii, NumSpheres, Flags, ReturnValues);
4571 /*****************************************************************************
4572 * IDirect3DDevice7::GetTexture
4574 * Returns the texture interface handle assigned to a texture stage.
4575 * The returned texture is AddRefed. This is taken from old ddraw,
4576 * not checked in Windows.
4578 * Version 3 and 7
4580 * Params:
4581 * Stage: Texture stage to read the texture from
4582 * Texture: Address to store the interface pointer at
4584 * Returns:
4585 * D3D_OK on success
4586 * DDERR_INVALIDPARAMS if Texture is NULL
4587 * For details, see IWineD3DDevice::GetTexture
4589 *****************************************************************************/
4590 static HRESULT
4591 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4592 DWORD Stage,
4593 IDirectDrawSurface7 **Texture)
4595 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4596 IWineD3DBaseTexture *Surf;
4597 HRESULT hr;
4599 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4601 if(!Texture)
4603 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4604 return DDERR_INVALIDPARAMS;
4607 EnterCriticalSection(&ddraw_cs);
4608 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, Stage, &Surf);
4609 if( (hr != D3D_OK) || (!Surf) )
4611 *Texture = NULL;
4612 LeaveCriticalSection(&ddraw_cs);
4613 return hr;
4616 *Texture = IWineD3DBaseTexture_GetParent(Surf);
4617 IDirectDrawSurface7_AddRef(*Texture);
4618 LeaveCriticalSection(&ddraw_cs);
4619 return hr;
4622 static HRESULT WINAPI
4623 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4624 DWORD Stage,
4625 IDirectDrawSurface7 **Texture)
4627 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4630 static HRESULT WINAPI
4631 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4632 DWORD Stage,
4633 IDirectDrawSurface7 **Texture)
4635 HRESULT hr;
4636 WORD old_fpucw;
4638 old_fpucw = d3d_fpu_setup();
4639 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4640 set_fpu_control_word(old_fpucw);
4642 return hr;
4645 static HRESULT WINAPI
4646 Thunk_IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface,
4647 DWORD Stage,
4648 IDirect3DTexture2 **Texture2)
4650 HRESULT ret;
4651 IDirectDrawSurface7 *ret_val;
4653 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4655 ret = IDirect3DDevice7_GetTexture((IDirect3DDevice7 *)device_from_device3(iface), Stage, &ret_val);
4657 *Texture2 = ret_val ? (IDirect3DTexture2 *)&((IDirectDrawSurfaceImpl *)ret_val)->IDirect3DTexture2_vtbl : NULL;
4659 TRACE("Returning texture %p.\n", *Texture2);
4661 return ret;
4664 /*****************************************************************************
4665 * IDirect3DDevice7::SetTexture
4667 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4669 * Version 3 and 7
4671 * Params:
4672 * Stage: The stage to assign the texture to
4673 * Texture: Interface pointer to the texture surface
4675 * Returns
4676 * D3D_OK on success
4677 * For details, see IWineD3DDevice::SetTexture
4679 *****************************************************************************/
4680 static HRESULT
4681 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4682 DWORD Stage,
4683 IDirectDrawSurface7 *Texture)
4685 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4686 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
4687 HRESULT hr;
4689 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4691 /* Texture may be NULL here */
4692 EnterCriticalSection(&ddraw_cs);
4693 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
4694 Stage,
4695 surf ? surf->wineD3DTexture : NULL);
4696 LeaveCriticalSection(&ddraw_cs);
4697 return hr;
4700 static HRESULT WINAPI
4701 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4702 DWORD Stage,
4703 IDirectDrawSurface7 *Texture)
4705 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4708 static HRESULT WINAPI
4709 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4710 DWORD Stage,
4711 IDirectDrawSurface7 *Texture)
4713 HRESULT hr;
4714 WORD old_fpucw;
4716 old_fpucw = d3d_fpu_setup();
4717 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4718 set_fpu_control_word(old_fpucw);
4720 return hr;
4723 static HRESULT WINAPI
4724 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4725 DWORD Stage,
4726 IDirect3DTexture2 *Texture2)
4728 IDirect3DDeviceImpl *This = device_from_device3(iface);
4729 IDirectDrawSurfaceImpl *tex = Texture2 ? surface_from_texture2(Texture2) : NULL;
4730 DWORD texmapblend;
4731 HRESULT hr;
4733 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4735 EnterCriticalSection(&ddraw_cs);
4737 if (This->legacyTextureBlending)
4738 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4740 hr = IDirect3DDevice7_SetTexture((IDirect3DDevice7 *)This, Stage, (IDirectDrawSurface7 *)tex);
4742 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4744 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4745 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4746 BOOL tex_alpha = FALSE;
4747 IWineD3DBaseTexture *tex = NULL;
4748 WINED3DSURFACE_DESC desc;
4749 DDPIXELFORMAT ddfmt;
4750 HRESULT result;
4752 result = IWineD3DDevice_GetTexture(This->wineD3DDevice,
4754 &tex);
4756 if(result == WINED3D_OK && tex)
4758 memset(&desc, 0, sizeof(desc));
4759 result = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
4760 if (SUCCEEDED(result))
4762 ddfmt.dwSize = sizeof(ddfmt);
4763 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4764 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4767 IWineD3DBaseTexture_Release(tex);
4770 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4771 if (tex_alpha)
4772 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4773 else
4774 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4777 LeaveCriticalSection(&ddraw_cs);
4779 return hr;
4782 static const struct tss_lookup
4784 BOOL sampler_state;
4785 DWORD state;
4787 tss_lookup[] =
4789 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
4790 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
4791 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
4792 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
4793 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
4794 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
4795 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
4796 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4797 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4798 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4799 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4800 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4801 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
4802 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
4803 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
4804 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
4805 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
4806 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
4807 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
4808 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4809 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4810 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4811 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4812 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4813 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4816 /*****************************************************************************
4817 * IDirect3DDevice7::GetTextureStageState
4819 * Retrieves a state from a texture stage.
4821 * Version 3 and 7
4823 * Params:
4824 * Stage: The stage to retrieve the state from
4825 * TexStageStateType: The state type to retrieve
4826 * State: Address to store the state's value at
4828 * Returns:
4829 * D3D_OK on success
4830 * DDERR_INVALIDPARAMS if State is NULL
4831 * For details, see IWineD3DDevice::GetTextureStageState
4833 *****************************************************************************/
4834 static HRESULT
4835 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4836 DWORD Stage,
4837 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4838 DWORD *State)
4840 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4841 HRESULT hr;
4842 const struct tss_lookup *l;
4844 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4845 iface, Stage, TexStageStateType, State);
4847 if(!State)
4848 return DDERR_INVALIDPARAMS;
4850 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4852 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4853 return DD_OK;
4856 l = &tss_lookup[TexStageStateType];
4858 EnterCriticalSection(&ddraw_cs);
4860 if (l->sampler_state)
4862 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice, Stage, l->state, State);
4864 switch(TexStageStateType)
4866 /* Mipfilter is a sampler state with different values */
4867 case D3DTSS_MIPFILTER:
4869 switch(*State)
4871 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4872 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4873 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4874 default:
4875 ERR("Unexpected mipfilter value %#x\n", *State);
4876 *State = D3DTFP_NONE;
4877 break;
4879 break;
4882 /* Magfilter has slightly different values */
4883 case D3DTSS_MAGFILTER:
4885 switch(*State)
4887 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4888 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4889 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4890 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4891 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4892 default:
4893 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4894 *State = D3DTFG_POINT;
4895 break;
4897 break;
4900 default:
4901 break;
4904 else
4906 hr = IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
4909 LeaveCriticalSection(&ddraw_cs);
4910 return hr;
4913 static HRESULT WINAPI
4914 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4915 DWORD Stage,
4916 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4917 DWORD *State)
4919 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4922 static HRESULT WINAPI
4923 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4924 DWORD Stage,
4925 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4926 DWORD *State)
4928 HRESULT hr;
4929 WORD old_fpucw;
4931 old_fpucw = d3d_fpu_setup();
4932 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4933 set_fpu_control_word(old_fpucw);
4935 return hr;
4938 static HRESULT WINAPI
4939 Thunk_IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4940 DWORD Stage,
4941 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4942 DWORD *State)
4944 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4945 iface, Stage, TexStageStateType, State);
4947 return IDirect3DDevice7_GetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4948 Stage, TexStageStateType, State);
4951 /*****************************************************************************
4952 * IDirect3DDevice7::SetTextureStageState
4954 * Sets a texture stage state. Some stage types need to be handled specially,
4955 * because they do not exist in WineD3D and were moved to another place
4957 * Version 3 and 7
4959 * Params:
4960 * Stage: The stage to modify
4961 * TexStageStateType: The state to change
4962 * State: The new value for the state
4964 * Returns:
4965 * D3D_OK on success
4966 * For details, see IWineD3DDevice::SetTextureStageState
4968 *****************************************************************************/
4969 static HRESULT
4970 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4971 DWORD Stage,
4972 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4973 DWORD State)
4975 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4976 const struct tss_lookup *l;
4977 HRESULT hr;
4979 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4980 iface, Stage, TexStageStateType, State);
4982 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4984 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4985 return DD_OK;
4988 l = &tss_lookup[TexStageStateType];
4990 EnterCriticalSection(&ddraw_cs);
4992 if (l->sampler_state)
4994 switch(TexStageStateType)
4996 /* Mipfilter is a sampler state with different values */
4997 case D3DTSS_MIPFILTER:
4999 switch(State)
5001 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
5002 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
5003 case 0: /* Unchecked */
5004 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
5005 default:
5006 ERR("Unexpected mipfilter value %d\n", State);
5007 State = WINED3DTEXF_NONE;
5008 break;
5010 break;
5013 /* Magfilter has slightly different values */
5014 case D3DTSS_MAGFILTER:
5016 switch(State)
5018 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
5019 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
5020 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
5021 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
5022 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
5023 default:
5024 ERR("Unexpected d3d7 mag filter type %d\n", State);
5025 State = WINED3DTEXF_POINT;
5026 break;
5028 break;
5031 case D3DTSS_ADDRESS:
5032 IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, WINED3DSAMP_ADDRESSV, State);
5033 break;
5035 default:
5036 break;
5039 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, l->state, State);
5041 else
5043 hr = IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
5046 LeaveCriticalSection(&ddraw_cs);
5047 return hr;
5050 static HRESULT WINAPI
5051 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5052 DWORD Stage,
5053 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5054 DWORD State)
5056 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5059 static HRESULT WINAPI
5060 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5061 DWORD Stage,
5062 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5063 DWORD State)
5065 HRESULT hr;
5066 WORD old_fpucw;
5068 old_fpucw = d3d_fpu_setup();
5069 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5070 set_fpu_control_word(old_fpucw);
5072 return hr;
5075 static HRESULT WINAPI
5076 Thunk_IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
5077 DWORD Stage,
5078 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5079 DWORD State)
5081 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5082 iface, Stage, TexStageStateType, State);
5084 return IDirect3DDevice7_SetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
5085 Stage, TexStageStateType, State);
5088 /*****************************************************************************
5089 * IDirect3DDevice7::ValidateDevice
5091 * SDK: "Reports the device's ability to render the currently set
5092 * texture-blending operations in a single pass". Whatever that means
5093 * exactly...
5095 * Version 3 and 7
5097 * Params:
5098 * NumPasses: Address to write the number of necessary passes for the
5099 * desired effect to.
5101 * Returns:
5102 * D3D_OK on success
5103 * See IWineD3DDevice::ValidateDevice for more details
5105 *****************************************************************************/
5106 static HRESULT
5107 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
5108 DWORD *NumPasses)
5110 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5111 HRESULT hr;
5113 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
5115 EnterCriticalSection(&ddraw_cs);
5116 hr = IWineD3DDevice_ValidateDevice(This->wineD3DDevice, NumPasses);
5117 LeaveCriticalSection(&ddraw_cs);
5118 return hr;
5121 static HRESULT WINAPI
5122 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
5123 DWORD *NumPasses)
5125 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5128 static HRESULT WINAPI
5129 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
5130 DWORD *NumPasses)
5132 HRESULT hr;
5133 WORD old_fpucw;
5135 old_fpucw = d3d_fpu_setup();
5136 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5137 set_fpu_control_word(old_fpucw);
5139 return hr;
5142 static HRESULT WINAPI
5143 Thunk_IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface,
5144 DWORD *Passes)
5146 TRACE("iface %p, pass_count %p.\n", iface, Passes);
5148 return IDirect3DDevice7_ValidateDevice((IDirect3DDevice7 *)device_from_device3(iface), Passes);
5151 /*****************************************************************************
5152 * IDirect3DDevice7::Clear
5154 * Fills the render target, the z buffer and the stencil buffer with a
5155 * clear color / value
5157 * Version 7 only
5159 * Params:
5160 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5161 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5162 * Flags: Some flags, as usual
5163 * Color: Clear color for the render target
5164 * Z: Clear value for the Z buffer
5165 * Stencil: Clear value to store in each stencil buffer entry
5167 * Returns:
5168 * D3D_OK on success
5169 * For details, see IWineD3DDevice::Clear
5171 *****************************************************************************/
5172 static HRESULT
5173 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
5174 DWORD Count,
5175 D3DRECT *Rects,
5176 DWORD Flags,
5177 D3DCOLOR Color,
5178 D3DVALUE Z,
5179 DWORD Stencil)
5181 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5182 HRESULT hr;
5184 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5185 iface, Count, Rects, Flags, Color, Z, Stencil);
5187 EnterCriticalSection(&ddraw_cs);
5188 hr = IWineD3DDevice_Clear(This->wineD3DDevice, Count, (RECT *)Rects, Flags, Color, Z, Stencil);
5189 LeaveCriticalSection(&ddraw_cs);
5190 return hr;
5193 static HRESULT WINAPI
5194 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5195 DWORD Count,
5196 D3DRECT *Rects,
5197 DWORD Flags,
5198 D3DCOLOR Color,
5199 D3DVALUE Z,
5200 DWORD Stencil)
5202 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5205 static HRESULT WINAPI
5206 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5207 DWORD Count,
5208 D3DRECT *Rects,
5209 DWORD Flags,
5210 D3DCOLOR Color,
5211 D3DVALUE Z,
5212 DWORD Stencil)
5214 HRESULT hr;
5215 WORD old_fpucw;
5217 old_fpucw = d3d_fpu_setup();
5218 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5219 set_fpu_control_word(old_fpucw);
5221 return hr;
5224 /*****************************************************************************
5225 * IDirect3DDevice7::SetViewport
5227 * Sets the current viewport.
5229 * Version 7 only, but IDirect3DViewport uses this call for older
5230 * versions
5232 * Params:
5233 * Data: The new viewport to set
5235 * Returns:
5236 * D3D_OK on success
5237 * DDERR_INVALIDPARAMS if Data is NULL
5238 * For more details, see IWineDDDevice::SetViewport
5240 *****************************************************************************/
5241 static HRESULT
5242 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5243 D3DVIEWPORT7 *Data)
5245 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5246 HRESULT hr;
5248 TRACE("iface %p, viewport %p.\n", iface, Data);
5250 if(!Data)
5251 return DDERR_INVALIDPARAMS;
5253 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5254 EnterCriticalSection(&ddraw_cs);
5255 hr = IWineD3DDevice_SetViewport(This->wineD3DDevice,
5256 (WINED3DVIEWPORT*) Data);
5257 LeaveCriticalSection(&ddraw_cs);
5258 return hr;
5261 static HRESULT WINAPI
5262 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5263 D3DVIEWPORT7 *Data)
5265 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5268 static HRESULT WINAPI
5269 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5270 D3DVIEWPORT7 *Data)
5272 HRESULT hr;
5273 WORD old_fpucw;
5275 old_fpucw = d3d_fpu_setup();
5276 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5277 set_fpu_control_word(old_fpucw);
5279 return hr;
5282 /*****************************************************************************
5283 * IDirect3DDevice::GetViewport
5285 * Returns the current viewport
5287 * Version 7
5289 * Params:
5290 * Data: D3D7Viewport structure to write the viewport information to
5292 * Returns:
5293 * D3D_OK on success
5294 * DDERR_INVALIDPARAMS if Data is NULL
5295 * For more details, see IWineD3DDevice::GetViewport
5297 *****************************************************************************/
5298 static HRESULT
5299 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5300 D3DVIEWPORT7 *Data)
5302 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5303 HRESULT hr;
5305 TRACE("iface %p, viewport %p.\n", iface, Data);
5307 if(!Data)
5308 return DDERR_INVALIDPARAMS;
5310 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5311 EnterCriticalSection(&ddraw_cs);
5312 hr = IWineD3DDevice_GetViewport(This->wineD3DDevice,
5313 (WINED3DVIEWPORT*) Data);
5315 LeaveCriticalSection(&ddraw_cs);
5316 return hr_ddraw_from_wined3d(hr);
5319 static HRESULT WINAPI
5320 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5321 D3DVIEWPORT7 *Data)
5323 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5326 static HRESULT WINAPI
5327 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5328 D3DVIEWPORT7 *Data)
5330 HRESULT hr;
5331 WORD old_fpucw;
5333 old_fpucw = d3d_fpu_setup();
5334 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5335 set_fpu_control_word(old_fpucw);
5337 return hr;
5340 /*****************************************************************************
5341 * IDirect3DDevice7::SetMaterial
5343 * Sets the Material
5345 * Version 7
5347 * Params:
5348 * Mat: The material to set
5350 * Returns:
5351 * D3D_OK on success
5352 * DDERR_INVALIDPARAMS if Mat is NULL.
5353 * For more details, see IWineD3DDevice::SetMaterial
5355 *****************************************************************************/
5356 static HRESULT
5357 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5358 D3DMATERIAL7 *Mat)
5360 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5361 HRESULT hr;
5363 TRACE("iface %p, material %p.\n", iface, Mat);
5365 if (!Mat) return DDERR_INVALIDPARAMS;
5366 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5367 EnterCriticalSection(&ddraw_cs);
5368 hr = IWineD3DDevice_SetMaterial(This->wineD3DDevice,
5369 (WINED3DMATERIAL*) Mat);
5370 LeaveCriticalSection(&ddraw_cs);
5371 return hr_ddraw_from_wined3d(hr);
5374 static HRESULT WINAPI
5375 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5376 D3DMATERIAL7 *Mat)
5378 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5381 static HRESULT WINAPI
5382 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5383 D3DMATERIAL7 *Mat)
5385 HRESULT hr;
5386 WORD old_fpucw;
5388 old_fpucw = d3d_fpu_setup();
5389 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5390 set_fpu_control_word(old_fpucw);
5392 return hr;
5395 /*****************************************************************************
5396 * IDirect3DDevice7::GetMaterial
5398 * Returns the current material
5400 * Version 7
5402 * Params:
5403 * Mat: D3DMATERIAL7 structure to write the material parameters to
5405 * Returns:
5406 * D3D_OK on success
5407 * DDERR_INVALIDPARAMS if Mat is NULL
5408 * For more details, see IWineD3DDevice::GetMaterial
5410 *****************************************************************************/
5411 static HRESULT
5412 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5413 D3DMATERIAL7 *Mat)
5415 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5416 HRESULT hr;
5418 TRACE("iface %p, material %p.\n", iface, Mat);
5420 EnterCriticalSection(&ddraw_cs);
5421 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5422 hr = IWineD3DDevice_GetMaterial(This->wineD3DDevice,
5423 (WINED3DMATERIAL*) Mat);
5424 LeaveCriticalSection(&ddraw_cs);
5425 return hr_ddraw_from_wined3d(hr);
5428 static HRESULT WINAPI
5429 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5430 D3DMATERIAL7 *Mat)
5432 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5435 static HRESULT WINAPI
5436 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5437 D3DMATERIAL7 *Mat)
5439 HRESULT hr;
5440 WORD old_fpucw;
5442 old_fpucw = d3d_fpu_setup();
5443 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5444 set_fpu_control_word(old_fpucw);
5446 return hr;
5449 /*****************************************************************************
5450 * IDirect3DDevice7::SetLight
5452 * Assigns a light to a light index, but doesn't activate it yet.
5454 * Version 7, IDirect3DLight uses this method for older versions
5456 * Params:
5457 * LightIndex: The index of the new light
5458 * Light: A D3DLIGHT7 structure describing the light
5460 * Returns:
5461 * D3D_OK on success
5462 * For more details, see IWineD3DDevice::SetLight
5464 *****************************************************************************/
5465 static HRESULT
5466 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5467 DWORD LightIndex,
5468 D3DLIGHT7 *Light)
5470 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5471 HRESULT hr;
5473 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5475 EnterCriticalSection(&ddraw_cs);
5476 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5477 hr = IWineD3DDevice_SetLight(This->wineD3DDevice,
5478 LightIndex,
5479 (WINED3DLIGHT*) Light);
5480 LeaveCriticalSection(&ddraw_cs);
5481 return hr_ddraw_from_wined3d(hr);
5484 static HRESULT WINAPI
5485 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5486 DWORD LightIndex,
5487 D3DLIGHT7 *Light)
5489 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5492 static HRESULT WINAPI
5493 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5494 DWORD LightIndex,
5495 D3DLIGHT7 *Light)
5497 HRESULT hr;
5498 WORD old_fpucw;
5500 old_fpucw = d3d_fpu_setup();
5501 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5502 set_fpu_control_word(old_fpucw);
5504 return hr;
5507 /*****************************************************************************
5508 * IDirect3DDevice7::GetLight
5510 * Returns the light assigned to a light index
5512 * Params:
5513 * Light: Structure to write the light information to
5515 * Returns:
5516 * D3D_OK on success
5517 * DDERR_INVALIDPARAMS if Light is NULL
5518 * For details, see IWineD3DDevice::GetLight
5520 *****************************************************************************/
5521 static HRESULT
5522 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5523 DWORD LightIndex,
5524 D3DLIGHT7 *Light)
5526 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5527 HRESULT rc;
5529 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5531 EnterCriticalSection(&ddraw_cs);
5532 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5533 rc = IWineD3DDevice_GetLight(This->wineD3DDevice,
5534 LightIndex,
5535 (WINED3DLIGHT*) Light);
5537 /* Translate the result. WineD3D returns other values than D3D7 */
5538 LeaveCriticalSection(&ddraw_cs);
5539 return hr_ddraw_from_wined3d(rc);
5542 static HRESULT WINAPI
5543 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5544 DWORD LightIndex,
5545 D3DLIGHT7 *Light)
5547 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5550 static HRESULT WINAPI
5551 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5552 DWORD LightIndex,
5553 D3DLIGHT7 *Light)
5555 HRESULT hr;
5556 WORD old_fpucw;
5558 old_fpucw = d3d_fpu_setup();
5559 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5560 set_fpu_control_word(old_fpucw);
5562 return hr;
5565 /*****************************************************************************
5566 * IDirect3DDevice7::BeginStateBlock
5568 * Begins recording to a stateblock
5570 * Version 7
5572 * Returns:
5573 * D3D_OK on success
5574 * For details see IWineD3DDevice::BeginStateBlock
5576 *****************************************************************************/
5577 static HRESULT
5578 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5580 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5581 HRESULT hr;
5583 TRACE("iface %p.\n", iface);
5585 EnterCriticalSection(&ddraw_cs);
5586 hr = IWineD3DDevice_BeginStateBlock(This->wineD3DDevice);
5587 LeaveCriticalSection(&ddraw_cs);
5588 return hr_ddraw_from_wined3d(hr);
5591 static HRESULT WINAPI
5592 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5594 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5597 static HRESULT WINAPI
5598 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5600 HRESULT hr;
5601 WORD old_fpucw;
5603 old_fpucw = d3d_fpu_setup();
5604 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5605 set_fpu_control_word(old_fpucw);
5607 return hr;
5610 /*****************************************************************************
5611 * IDirect3DDevice7::EndStateBlock
5613 * Stops recording to a state block and returns the created stateblock
5614 * handle.
5616 * Version 7
5618 * Params:
5619 * BlockHandle: Address to store the stateblock's handle to
5621 * Returns:
5622 * D3D_OK on success
5623 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5624 * See IWineD3DDevice::EndStateBlock for more details
5626 *****************************************************************************/
5627 static HRESULT
5628 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5629 DWORD *BlockHandle)
5631 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5632 IWineD3DStateBlock *wined3d_sb;
5633 HRESULT hr;
5634 DWORD h;
5636 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5638 if(!BlockHandle)
5640 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5641 return DDERR_INVALIDPARAMS;
5644 EnterCriticalSection(&ddraw_cs);
5646 hr = IWineD3DDevice_EndStateBlock(This->wineD3DDevice, &wined3d_sb);
5647 if (FAILED(hr))
5649 WARN("Failed to end stateblock, hr %#x.\n", hr);
5650 LeaveCriticalSection(&ddraw_cs);
5651 *BlockHandle = 0;
5652 return hr_ddraw_from_wined3d(hr);
5655 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5656 if (h == DDRAW_INVALID_HANDLE)
5658 ERR("Failed to allocate a stateblock handle.\n");
5659 IWineD3DStateBlock_Release(wined3d_sb);
5660 LeaveCriticalSection(&ddraw_cs);
5661 *BlockHandle = 0;
5662 return DDERR_OUTOFMEMORY;
5665 LeaveCriticalSection(&ddraw_cs);
5666 *BlockHandle = h + 1;
5668 return hr_ddraw_from_wined3d(hr);
5671 static HRESULT WINAPI
5672 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5673 DWORD *BlockHandle)
5675 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5678 static HRESULT WINAPI
5679 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5680 DWORD *BlockHandle)
5682 HRESULT hr;
5683 WORD old_fpucw;
5685 old_fpucw = d3d_fpu_setup();
5686 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5687 set_fpu_control_word(old_fpucw);
5689 return hr;
5692 /*****************************************************************************
5693 * IDirect3DDevice7::PreLoad
5695 * Allows the app to signal that a texture will be used soon, to allow
5696 * the Direct3DDevice to load it to the video card in the meantime.
5698 * Version 7
5700 * Params:
5701 * Texture: The texture to preload
5703 * Returns:
5704 * D3D_OK on success
5705 * DDERR_INVALIDPARAMS if Texture is NULL
5706 * See IWineD3DSurface::PreLoad for details
5708 *****************************************************************************/
5709 static HRESULT
5710 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5711 IDirectDrawSurface7 *Texture)
5713 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
5715 TRACE("iface %p, texture %p.\n", iface, Texture);
5717 if(!Texture)
5718 return DDERR_INVALIDPARAMS;
5720 EnterCriticalSection(&ddraw_cs);
5721 IWineD3DSurface_PreLoad(surf->WineD3DSurface);
5722 LeaveCriticalSection(&ddraw_cs);
5723 return D3D_OK;
5726 static HRESULT WINAPI
5727 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5728 IDirectDrawSurface7 *Texture)
5730 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5733 static HRESULT WINAPI
5734 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5735 IDirectDrawSurface7 *Texture)
5737 HRESULT hr;
5738 WORD old_fpucw;
5740 old_fpucw = d3d_fpu_setup();
5741 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5742 set_fpu_control_word(old_fpucw);
5744 return hr;
5747 /*****************************************************************************
5748 * IDirect3DDevice7::ApplyStateBlock
5750 * Activates the state stored in a state block handle.
5752 * Params:
5753 * BlockHandle: The stateblock handle to activate
5755 * Returns:
5756 * D3D_OK on success
5757 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5759 *****************************************************************************/
5760 static HRESULT
5761 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5762 DWORD BlockHandle)
5764 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5765 IWineD3DStateBlock *wined3d_sb;
5766 HRESULT hr;
5768 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5770 EnterCriticalSection(&ddraw_cs);
5772 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5773 if (!wined3d_sb)
5775 WARN("Invalid stateblock handle.\n");
5776 LeaveCriticalSection(&ddraw_cs);
5777 return D3DERR_INVALIDSTATEBLOCK;
5780 hr = IWineD3DStateBlock_Apply(wined3d_sb);
5781 LeaveCriticalSection(&ddraw_cs);
5783 return hr_ddraw_from_wined3d(hr);
5786 static HRESULT WINAPI
5787 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5788 DWORD BlockHandle)
5790 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5793 static HRESULT WINAPI
5794 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5795 DWORD BlockHandle)
5797 HRESULT hr;
5798 WORD old_fpucw;
5800 old_fpucw = d3d_fpu_setup();
5801 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5802 set_fpu_control_word(old_fpucw);
5804 return hr;
5807 /*****************************************************************************
5808 * IDirect3DDevice7::CaptureStateBlock
5810 * Updates a stateblock's values to the values currently set for the device
5812 * Version 7
5814 * Params:
5815 * BlockHandle: Stateblock to update
5817 * Returns:
5818 * D3D_OK on success
5819 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5820 * See IWineD3DDevice::CaptureStateBlock for more details
5822 *****************************************************************************/
5823 static HRESULT
5824 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5825 DWORD BlockHandle)
5827 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5828 IWineD3DStateBlock *wined3d_sb;
5829 HRESULT hr;
5831 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5833 EnterCriticalSection(&ddraw_cs);
5835 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5836 if (!wined3d_sb)
5838 WARN("Invalid stateblock handle.\n");
5839 LeaveCriticalSection(&ddraw_cs);
5840 return D3DERR_INVALIDSTATEBLOCK;
5843 hr = IWineD3DStateBlock_Capture(wined3d_sb);
5844 LeaveCriticalSection(&ddraw_cs);
5845 return hr_ddraw_from_wined3d(hr);
5848 static HRESULT WINAPI
5849 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5850 DWORD BlockHandle)
5852 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5855 static HRESULT WINAPI
5856 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5857 DWORD BlockHandle)
5859 HRESULT hr;
5860 WORD old_fpucw;
5862 old_fpucw = d3d_fpu_setup();
5863 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5864 set_fpu_control_word(old_fpucw);
5866 return hr;
5869 /*****************************************************************************
5870 * IDirect3DDevice7::DeleteStateBlock
5872 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5874 * Version 7
5876 * Params:
5877 * BlockHandle: Stateblock handle to delete
5879 * Returns:
5880 * D3D_OK on success
5881 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5883 *****************************************************************************/
5884 static HRESULT
5885 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5886 DWORD BlockHandle)
5888 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5889 IWineD3DStateBlock *wined3d_sb;
5890 ULONG ref;
5892 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5894 EnterCriticalSection(&ddraw_cs);
5896 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5897 if (!wined3d_sb)
5899 WARN("Invalid stateblock handle.\n");
5900 LeaveCriticalSection(&ddraw_cs);
5901 return D3DERR_INVALIDSTATEBLOCK;
5904 if ((ref = IWineD3DStateBlock_Release(wined3d_sb)))
5906 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5909 LeaveCriticalSection(&ddraw_cs);
5910 return D3D_OK;
5913 static HRESULT WINAPI
5914 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5915 DWORD BlockHandle)
5917 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5920 static HRESULT WINAPI
5921 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5922 DWORD BlockHandle)
5924 HRESULT hr;
5925 WORD old_fpucw;
5927 old_fpucw = d3d_fpu_setup();
5928 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5929 set_fpu_control_word(old_fpucw);
5931 return hr;
5934 /*****************************************************************************
5935 * IDirect3DDevice7::CreateStateBlock
5937 * Creates a new state block handle.
5939 * Version 7
5941 * Params:
5942 * Type: The state block type
5943 * BlockHandle: Address to write the created handle to
5945 * Returns:
5946 * D3D_OK on success
5947 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5949 *****************************************************************************/
5950 static HRESULT
5951 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5952 D3DSTATEBLOCKTYPE Type,
5953 DWORD *BlockHandle)
5955 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5956 IWineD3DStateBlock *wined3d_sb;
5957 HRESULT hr;
5958 DWORD h;
5960 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5962 if(!BlockHandle)
5964 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5965 return DDERR_INVALIDPARAMS;
5967 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5968 Type != D3DSBT_VERTEXSTATE ) {
5969 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5970 return DDERR_INVALIDPARAMS;
5973 EnterCriticalSection(&ddraw_cs);
5975 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5976 hr = IWineD3DDevice_CreateStateBlock(This->wineD3DDevice, Type, &wined3d_sb);
5977 if (FAILED(hr))
5979 WARN("Failed to create stateblock, hr %#x.\n", hr);
5980 LeaveCriticalSection(&ddraw_cs);
5981 return hr_ddraw_from_wined3d(hr);
5984 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5985 if (h == DDRAW_INVALID_HANDLE)
5987 ERR("Failed to allocate stateblock handle.\n");
5988 IWineD3DStateBlock_Release(wined3d_sb);
5989 LeaveCriticalSection(&ddraw_cs);
5990 return DDERR_OUTOFMEMORY;
5993 *BlockHandle = h + 1;
5994 LeaveCriticalSection(&ddraw_cs);
5996 return hr_ddraw_from_wined3d(hr);
5999 static HRESULT WINAPI
6000 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
6001 D3DSTATEBLOCKTYPE Type,
6002 DWORD *BlockHandle)
6004 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6007 static HRESULT WINAPI
6008 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
6009 D3DSTATEBLOCKTYPE Type,
6010 DWORD *BlockHandle)
6012 HRESULT hr;
6013 WORD old_fpucw;
6015 old_fpucw = d3d_fpu_setup();
6016 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6017 set_fpu_control_word(old_fpucw);
6019 return hr;
6022 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6023 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
6024 IDirectDrawSurfaceImpl *src)
6026 IDirectDrawSurfaceImpl *src_level, *dest_level;
6027 IDirectDrawSurface7 *temp;
6028 DDSURFACEDESC2 ddsd;
6029 BOOL levelFound; /* at least one suitable sublevel in dest found */
6031 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
6032 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
6033 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
6035 levelFound = FALSE;
6037 src_level = src;
6038 dest_level = dest;
6040 for (;src_level && dest_level;)
6042 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6043 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6045 levelFound = TRUE;
6047 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6048 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6049 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
6051 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6053 dest_level = (IDirectDrawSurfaceImpl *)temp;
6056 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6057 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6058 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
6060 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6062 src_level = (IDirectDrawSurfaceImpl *)temp;
6065 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6066 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6068 return !dest_level && levelFound;
6071 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6072 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
6073 IDirectDrawSurfaceImpl *dest,
6074 IDirectDrawSurfaceImpl *src,
6075 const POINT *DestPoint,
6076 const RECT *SrcRect)
6078 IDirectDrawSurfaceImpl *src_level, *dest_level;
6079 IDirectDrawSurface7 *temp;
6080 DDSURFACEDESC2 ddsd;
6081 POINT point;
6082 RECT rect;
6083 HRESULT hr;
6084 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
6085 DWORD ckeyflag;
6086 DDCOLORKEY ddckey;
6087 BOOL palette_missing = FALSE;
6089 /* Copy palette, if possible. */
6090 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)src, &pal_src);
6091 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)dest, &pal);
6093 if (pal_src != NULL && pal != NULL)
6095 PALETTEENTRY palent[256];
6097 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
6098 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
6101 if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
6102 DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
6104 palette_missing = TRUE;
6107 if (pal) IDirectDrawPalette_Release(pal);
6108 if (pal_src) IDirectDrawPalette_Release(pal_src);
6110 /* Copy colorkeys, if present. */
6111 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6113 hr = IDirectDrawSurface7_GetColorKey((IDirectDrawSurface7 *)src, ckeyflag, &ddckey);
6115 if (SUCCEEDED(hr))
6117 IDirectDrawSurface7_SetColorKey((IDirectDrawSurface7 *)dest, ckeyflag, &ddckey);
6121 src_level = src;
6122 dest_level = dest;
6124 point = *DestPoint;
6125 rect = *SrcRect;
6127 for (;src_level && dest_level;)
6129 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6130 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6132 /* Try UpdateSurface that may perform a more direct opengl loading. But skip this if destination is paletted texture and has no palette.
6133 * Some games like Sacrifice set palette after Load, and it is a waste of effort to try to load texture without palette and generates
6134 * warnings in wined3d. */
6135 if (!palette_missing)
6136 hr = IWineD3DDevice_UpdateSurface(device->wineD3DDevice, src_level->WineD3DSurface, &rect, dest_level->WineD3DSurface,
6137 &point);
6139 if (palette_missing || FAILED(hr))
6141 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
6142 IWineD3DSurface_BltFast(dest_level->WineD3DSurface,
6143 point.x, point.y,
6144 src_level->WineD3DSurface, &rect, 0);
6147 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6148 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6149 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
6151 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6153 dest_level = (IDirectDrawSurfaceImpl *)temp;
6156 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6157 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6158 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
6160 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6162 src_level = (IDirectDrawSurfaceImpl *)temp;
6164 point.x /= 2;
6165 point.y /= 2;
6167 rect.top /= 2;
6168 rect.left /= 2;
6169 rect.right = (rect.right + 1) / 2;
6170 rect.bottom = (rect.bottom + 1) / 2;
6173 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6174 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6177 /*****************************************************************************
6178 * IDirect3DDevice7::Load
6180 * Loads a rectangular area from the source into the destination texture.
6181 * It can also copy the source to the faces of a cubic environment map
6183 * Version 7
6185 * Params:
6186 * DestTex: Destination texture
6187 * DestPoint: Point in the destination where the source image should be
6188 * written to
6189 * SrcTex: Source texture
6190 * SrcRect: Source rectangle
6191 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6192 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6193 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6195 * Returns:
6196 * D3D_OK on success
6197 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6200 *****************************************************************************/
6202 static HRESULT
6203 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6204 IDirectDrawSurface7 *DestTex,
6205 POINT *DestPoint,
6206 IDirectDrawSurface7 *SrcTex,
6207 RECT *SrcRect,
6208 DWORD Flags)
6210 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6211 IDirectDrawSurfaceImpl *dest = (IDirectDrawSurfaceImpl *)DestTex;
6212 IDirectDrawSurfaceImpl *src = (IDirectDrawSurfaceImpl *)SrcTex;
6213 POINT destpoint;
6214 RECT srcrect;
6216 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6217 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6219 if( (!src) || (!dest) )
6220 return DDERR_INVALIDPARAMS;
6222 EnterCriticalSection(&ddraw_cs);
6224 if (SrcRect) srcrect = *SrcRect;
6225 else
6227 srcrect.left = srcrect.top = 0;
6228 srcrect.right = src->surface_desc.dwWidth;
6229 srcrect.bottom = src->surface_desc.dwHeight;
6232 if (DestPoint) destpoint = *DestPoint;
6233 else
6235 destpoint.x = destpoint.y = 0;
6237 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6238 * destination can be a subset of mip levels, in which case actual coordinates used
6239 * for it may be divided. If any dimension of dest is larger than source, it can't be
6240 * mip level subset, so an error can be returned early.
6242 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6243 srcrect.right > src->surface_desc.dwWidth ||
6244 srcrect.bottom > src->surface_desc.dwHeight ||
6245 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6246 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6247 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6248 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6250 LeaveCriticalSection(&ddraw_cs);
6251 return DDERR_INVALIDPARAMS;
6254 /* Must be top level surfaces. */
6255 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6256 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6258 LeaveCriticalSection(&ddraw_cs);
6259 return DDERR_INVALIDPARAMS;
6262 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6264 DWORD src_face_flag, dest_face_flag;
6265 IDirectDrawSurfaceImpl *src_face, *dest_face;
6266 IDirectDrawSurface7 *temp;
6267 DDSURFACEDESC2 ddsd;
6268 int i;
6270 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6272 LeaveCriticalSection(&ddraw_cs);
6273 return DDERR_INVALIDPARAMS;
6276 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6277 * time it's actual surface loading. */
6278 for (i = 0; i < 2; i++)
6280 dest_face = dest;
6281 src_face = src;
6283 for (;dest_face && src_face;)
6285 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6286 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6288 if (src_face_flag == dest_face_flag)
6290 if (i == 0)
6292 /* Destination mip levels must be subset of source mip levels. */
6293 if (!is_mip_level_subset(dest_face, src_face))
6295 LeaveCriticalSection(&ddraw_cs);
6296 return DDERR_INVALIDPARAMS;
6299 else if (Flags & dest_face_flag)
6301 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6304 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6306 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6307 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6308 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src, &ddsd.ddsCaps, &temp);
6310 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6312 src_face = (IDirectDrawSurfaceImpl *)temp;
6314 else
6316 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6318 src_face = NULL;
6322 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6324 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6325 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6326 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest, &ddsd.ddsCaps, &temp);
6328 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6330 dest_face = (IDirectDrawSurfaceImpl *)temp;
6332 else
6334 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6336 dest_face = NULL;
6340 if (i == 0)
6342 /* Native returns error if src faces are not subset of dest faces. */
6343 if (src_face)
6345 LeaveCriticalSection(&ddraw_cs);
6346 return DDERR_INVALIDPARAMS;
6351 LeaveCriticalSection(&ddraw_cs);
6352 return D3D_OK;
6354 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6356 LeaveCriticalSection(&ddraw_cs);
6357 return DDERR_INVALIDPARAMS;
6360 /* Handle non cube map textures. */
6362 /* Destination mip levels must be subset of source mip levels. */
6363 if (!is_mip_level_subset(dest, src))
6365 LeaveCriticalSection(&ddraw_cs);
6366 return DDERR_INVALIDPARAMS;
6369 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6371 LeaveCriticalSection(&ddraw_cs);
6372 return D3D_OK;
6375 static HRESULT WINAPI
6376 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6377 IDirectDrawSurface7 *DestTex,
6378 POINT *DestPoint,
6379 IDirectDrawSurface7 *SrcTex,
6380 RECT *SrcRect,
6381 DWORD Flags)
6383 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6386 static HRESULT WINAPI
6387 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6388 IDirectDrawSurface7 *DestTex,
6389 POINT *DestPoint,
6390 IDirectDrawSurface7 *SrcTex,
6391 RECT *SrcRect,
6392 DWORD Flags)
6394 HRESULT hr;
6395 WORD old_fpucw;
6397 old_fpucw = d3d_fpu_setup();
6398 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6399 set_fpu_control_word(old_fpucw);
6401 return hr;
6404 /*****************************************************************************
6405 * IDirect3DDevice7::LightEnable
6407 * Enables or disables a light
6409 * Version 7, IDirect3DLight uses this method too.
6411 * Params:
6412 * LightIndex: The index of the light to enable / disable
6413 * Enable: Enable or disable the light
6415 * Returns:
6416 * D3D_OK on success
6417 * For more details, see IWineD3DDevice::SetLightEnable
6419 *****************************************************************************/
6420 static HRESULT
6421 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6422 DWORD LightIndex,
6423 BOOL Enable)
6425 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6426 HRESULT hr;
6428 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6430 EnterCriticalSection(&ddraw_cs);
6431 hr = IWineD3DDevice_SetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6432 LeaveCriticalSection(&ddraw_cs);
6433 return hr_ddraw_from_wined3d(hr);
6436 static HRESULT WINAPI
6437 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6438 DWORD LightIndex,
6439 BOOL Enable)
6441 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6444 static HRESULT WINAPI
6445 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6446 DWORD LightIndex,
6447 BOOL Enable)
6449 HRESULT hr;
6450 WORD old_fpucw;
6452 old_fpucw = d3d_fpu_setup();
6453 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6454 set_fpu_control_word(old_fpucw);
6456 return hr;
6459 /*****************************************************************************
6460 * IDirect3DDevice7::GetLightEnable
6462 * Retrieves if the light with the given index is enabled or not
6464 * Version 7
6466 * Params:
6467 * LightIndex: Index of desired light
6468 * Enable: Pointer to a BOOL which contains the result
6470 * Returns:
6471 * D3D_OK on success
6472 * DDERR_INVALIDPARAMS if Enable is NULL
6473 * See IWineD3DDevice::GetLightEnable for more details
6475 *****************************************************************************/
6476 static HRESULT
6477 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6478 DWORD LightIndex,
6479 BOOL* Enable)
6481 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6482 HRESULT hr;
6484 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6486 if(!Enable)
6487 return DDERR_INVALIDPARAMS;
6489 EnterCriticalSection(&ddraw_cs);
6490 hr = IWineD3DDevice_GetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6491 LeaveCriticalSection(&ddraw_cs);
6492 return hr_ddraw_from_wined3d(hr);
6495 static HRESULT WINAPI
6496 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6497 DWORD LightIndex,
6498 BOOL* Enable)
6500 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6503 static HRESULT WINAPI
6504 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6505 DWORD LightIndex,
6506 BOOL* Enable)
6508 HRESULT hr;
6509 WORD old_fpucw;
6511 old_fpucw = d3d_fpu_setup();
6512 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6513 set_fpu_control_word(old_fpucw);
6515 return hr;
6518 /*****************************************************************************
6519 * IDirect3DDevice7::SetClipPlane
6521 * Sets custom clipping plane
6523 * Version 7
6525 * Params:
6526 * Index: The index of the clipping plane
6527 * PlaneEquation: An equation defining the clipping plane
6529 * Returns:
6530 * D3D_OK on success
6531 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6532 * See IWineD3DDevice::SetClipPlane for more details
6534 *****************************************************************************/
6535 static HRESULT
6536 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6537 DWORD Index,
6538 D3DVALUE* PlaneEquation)
6540 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6541 HRESULT hr;
6543 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6545 if(!PlaneEquation)
6546 return DDERR_INVALIDPARAMS;
6548 EnterCriticalSection(&ddraw_cs);
6549 hr = IWineD3DDevice_SetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6550 LeaveCriticalSection(&ddraw_cs);
6551 return hr;
6554 static HRESULT WINAPI
6555 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6556 DWORD Index,
6557 D3DVALUE* PlaneEquation)
6559 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6562 static HRESULT WINAPI
6563 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6564 DWORD Index,
6565 D3DVALUE* PlaneEquation)
6567 HRESULT hr;
6568 WORD old_fpucw;
6570 old_fpucw = d3d_fpu_setup();
6571 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6572 set_fpu_control_word(old_fpucw);
6574 return hr;
6577 /*****************************************************************************
6578 * IDirect3DDevice7::GetClipPlane
6580 * Returns the clipping plane with a specific index
6582 * Params:
6583 * Index: The index of the desired plane
6584 * PlaneEquation: Address to store the plane equation to
6586 * Returns:
6587 * D3D_OK on success
6588 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6589 * See IWineD3DDevice::GetClipPlane for more details
6591 *****************************************************************************/
6592 static HRESULT
6593 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6594 DWORD Index,
6595 D3DVALUE* PlaneEquation)
6597 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6598 HRESULT hr;
6600 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6602 if(!PlaneEquation)
6603 return DDERR_INVALIDPARAMS;
6605 EnterCriticalSection(&ddraw_cs);
6606 hr = IWineD3DDevice_GetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6607 LeaveCriticalSection(&ddraw_cs);
6608 return hr;
6611 static HRESULT WINAPI
6612 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6613 DWORD Index,
6614 D3DVALUE* PlaneEquation)
6616 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6619 static HRESULT WINAPI
6620 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6621 DWORD Index,
6622 D3DVALUE* PlaneEquation)
6624 HRESULT hr;
6625 WORD old_fpucw;
6627 old_fpucw = d3d_fpu_setup();
6628 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6629 set_fpu_control_word(old_fpucw);
6631 return hr;
6634 /*****************************************************************************
6635 * IDirect3DDevice7::GetInfo
6637 * Retrieves some information about the device. The DirectX sdk says that
6638 * this version returns S_FALSE for all retail builds of DirectX, that's what
6639 * this implementation does.
6641 * Params:
6642 * DevInfoID: Information type requested
6643 * DevInfoStruct: Pointer to a structure to store the info to
6644 * Size: Size of the structure
6646 * Returns:
6647 * S_FALSE, because it's a non-debug driver
6649 *****************************************************************************/
6650 static HRESULT WINAPI
6651 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6652 DWORD DevInfoID,
6653 void *DevInfoStruct,
6654 DWORD Size)
6656 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6657 iface, DevInfoID, DevInfoStruct, Size);
6659 if (TRACE_ON(ddraw))
6661 TRACE(" info requested : ");
6662 switch (DevInfoID)
6664 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6665 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6666 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6667 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6671 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6674 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6675 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6676 * are not duplicated.
6678 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6679 * has already been setup for optimal d3d operation.
6681 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6682 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6683 * by Sacrifice (game). */
6684 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6686 /*** IUnknown Methods ***/
6687 IDirect3DDeviceImpl_7_QueryInterface,
6688 IDirect3DDeviceImpl_7_AddRef,
6689 IDirect3DDeviceImpl_7_Release,
6690 /*** IDirect3DDevice7 ***/
6691 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6692 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6693 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6694 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6695 IDirect3DDeviceImpl_7_GetDirect3D,
6696 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6697 IDirect3DDeviceImpl_7_GetRenderTarget,
6698 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6699 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6700 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6701 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6702 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6703 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6704 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6705 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6706 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6707 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6708 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6709 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6710 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6711 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6712 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6713 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6714 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6715 IDirect3DDeviceImpl_7_SetClipStatus,
6716 IDirect3DDeviceImpl_7_GetClipStatus,
6717 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6718 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6719 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6720 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6721 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6722 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6723 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6724 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6725 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6726 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6727 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6728 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6729 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6730 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6731 IDirect3DDeviceImpl_7_Load_FPUSetup,
6732 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6733 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6734 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6735 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6736 IDirect3DDeviceImpl_7_GetInfo
6739 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6741 /*** IUnknown Methods ***/
6742 IDirect3DDeviceImpl_7_QueryInterface,
6743 IDirect3DDeviceImpl_7_AddRef,
6744 IDirect3DDeviceImpl_7_Release,
6745 /*** IDirect3DDevice7 ***/
6746 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6747 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6748 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6749 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6750 IDirect3DDeviceImpl_7_GetDirect3D,
6751 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6752 IDirect3DDeviceImpl_7_GetRenderTarget,
6753 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6754 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6755 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6756 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6757 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6758 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6759 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6760 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6761 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6762 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6763 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6764 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6765 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6766 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6767 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6768 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6769 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6770 IDirect3DDeviceImpl_7_SetClipStatus,
6771 IDirect3DDeviceImpl_7_GetClipStatus,
6772 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6773 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6774 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6775 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6776 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6777 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6778 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6779 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6780 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6781 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6782 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6783 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6784 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6785 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6786 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6787 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6788 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6789 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6790 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6791 IDirect3DDeviceImpl_7_GetInfo
6794 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6796 /*** IUnknown Methods ***/
6797 Thunk_IDirect3DDeviceImpl_3_QueryInterface,
6798 Thunk_IDirect3DDeviceImpl_3_AddRef,
6799 Thunk_IDirect3DDeviceImpl_3_Release,
6800 /*** IDirect3DDevice3 ***/
6801 IDirect3DDeviceImpl_3_GetCaps,
6802 IDirect3DDeviceImpl_3_GetStats,
6803 IDirect3DDeviceImpl_3_AddViewport,
6804 IDirect3DDeviceImpl_3_DeleteViewport,
6805 IDirect3DDeviceImpl_3_NextViewport,
6806 Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
6807 Thunk_IDirect3DDeviceImpl_3_BeginScene,
6808 Thunk_IDirect3DDeviceImpl_3_EndScene,
6809 Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
6810 IDirect3DDeviceImpl_3_SetCurrentViewport,
6811 IDirect3DDeviceImpl_3_GetCurrentViewport,
6812 Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
6813 Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
6814 IDirect3DDeviceImpl_3_Begin,
6815 IDirect3DDeviceImpl_3_BeginIndexed,
6816 IDirect3DDeviceImpl_3_Vertex,
6817 IDirect3DDeviceImpl_3_Index,
6818 IDirect3DDeviceImpl_3_End,
6819 IDirect3DDeviceImpl_3_GetRenderState,
6820 IDirect3DDeviceImpl_3_SetRenderState,
6821 IDirect3DDeviceImpl_3_GetLightState,
6822 IDirect3DDeviceImpl_3_SetLightState,
6823 Thunk_IDirect3DDeviceImpl_3_SetTransform,
6824 Thunk_IDirect3DDeviceImpl_3_GetTransform,
6825 Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
6826 Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
6827 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6828 Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
6829 Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
6830 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6831 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6832 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6833 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6834 Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6835 Thunk_IDirect3DDeviceImpl_3_GetTexture,
6836 IDirect3DDeviceImpl_3_SetTexture,
6837 Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
6838 Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
6839 Thunk_IDirect3DDeviceImpl_3_ValidateDevice
6842 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6844 /*** IUnknown Methods ***/
6845 Thunk_IDirect3DDeviceImpl_2_QueryInterface,
6846 Thunk_IDirect3DDeviceImpl_2_AddRef,
6847 Thunk_IDirect3DDeviceImpl_2_Release,
6848 /*** IDirect3DDevice2 ***/
6849 Thunk_IDirect3DDeviceImpl_2_GetCaps,
6850 IDirect3DDeviceImpl_2_SwapTextureHandles,
6851 Thunk_IDirect3DDeviceImpl_2_GetStats,
6852 Thunk_IDirect3DDeviceImpl_2_AddViewport,
6853 Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
6854 Thunk_IDirect3DDeviceImpl_2_NextViewport,
6855 IDirect3DDeviceImpl_2_EnumTextureFormats,
6856 Thunk_IDirect3DDeviceImpl_2_BeginScene,
6857 Thunk_IDirect3DDeviceImpl_2_EndScene,
6858 Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
6859 Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
6860 Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
6861 Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
6862 Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
6863 Thunk_IDirect3DDeviceImpl_2_Begin,
6864 Thunk_IDirect3DDeviceImpl_2_BeginIndexed,
6865 Thunk_IDirect3DDeviceImpl_2_Vertex,
6866 Thunk_IDirect3DDeviceImpl_2_Index,
6867 Thunk_IDirect3DDeviceImpl_2_End,
6868 Thunk_IDirect3DDeviceImpl_2_GetRenderState,
6869 Thunk_IDirect3DDeviceImpl_2_SetRenderState,
6870 Thunk_IDirect3DDeviceImpl_2_GetLightState,
6871 Thunk_IDirect3DDeviceImpl_2_SetLightState,
6872 Thunk_IDirect3DDeviceImpl_2_SetTransform,
6873 Thunk_IDirect3DDeviceImpl_2_GetTransform,
6874 Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
6875 Thunk_IDirect3DDeviceImpl_2_DrawPrimitive,
6876 Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6877 Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
6878 Thunk_IDirect3DDeviceImpl_2_GetClipStatus
6881 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6883 /*** IUnknown Methods ***/
6884 Thunk_IDirect3DDeviceImpl_1_QueryInterface,
6885 Thunk_IDirect3DDeviceImpl_1_AddRef,
6886 Thunk_IDirect3DDeviceImpl_1_Release,
6887 /*** IDirect3DDevice1 ***/
6888 IDirect3DDeviceImpl_1_Initialize,
6889 Thunk_IDirect3DDeviceImpl_1_GetCaps,
6890 Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
6891 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6892 Thunk_IDirect3DDeviceImpl_1_GetStats,
6893 IDirect3DDeviceImpl_1_Execute,
6894 Thunk_IDirect3DDeviceImpl_1_AddViewport,
6895 Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
6896 Thunk_IDirect3DDeviceImpl_1_NextViewport,
6897 IDirect3DDeviceImpl_1_Pick,
6898 IDirect3DDeviceImpl_1_GetPickRecords,
6899 Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
6900 IDirect3DDeviceImpl_1_CreateMatrix,
6901 IDirect3DDeviceImpl_1_SetMatrix,
6902 IDirect3DDeviceImpl_1_GetMatrix,
6903 IDirect3DDeviceImpl_1_DeleteMatrix,
6904 Thunk_IDirect3DDeviceImpl_1_BeginScene,
6905 Thunk_IDirect3DDeviceImpl_1_EndScene,
6906 Thunk_IDirect3DDeviceImpl_1_GetDirect3D
6909 /*****************************************************************************
6910 * IDirect3DDeviceImpl_UpdateDepthStencil
6912 * Checks the current render target for attached depth stencils and sets the
6913 * WineD3D depth stencil accordingly.
6915 * Returns:
6916 * The depth stencil state to set if creating the device
6918 *****************************************************************************/
6919 WINED3DZBUFFERTYPE
6920 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6922 IDirectDrawSurface7 *depthStencil = NULL;
6923 IDirectDrawSurfaceImpl *dsi;
6924 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6926 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)This->target, &depthcaps, &depthStencil);
6927 if(!depthStencil)
6929 TRACE("Setting wined3d depth stencil to NULL\n");
6930 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6931 NULL);
6932 return WINED3DZB_FALSE;
6935 dsi = (IDirectDrawSurfaceImpl *)depthStencil;
6936 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->WineD3DSurface);
6937 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6938 dsi->WineD3DSurface);
6940 IDirectDrawSurface7_Release(depthStencil);
6941 return WINED3DZB_TRUE;
6944 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
6946 IParentImpl *index_buffer_parent;
6947 HRESULT hr;
6949 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6950 device->lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6951 else
6952 device->lpVtbl = &d3d_device7_fpu_setup_vtbl;
6954 device->IDirect3DDevice3_vtbl = &d3d_device3_vtbl;
6955 device->IDirect3DDevice2_vtbl = &d3d_device2_vtbl;
6956 device->IDirect3DDevice_vtbl = &d3d_device1_vtbl;
6957 device->ref = 1;
6958 device->ddraw = ddraw;
6959 device->target = target;
6961 if (!ddraw_handle_table_init(&device->handle_table, 64))
6963 ERR("Failed to initialize handle table.\n");
6964 return DDERR_OUTOFMEMORY;
6967 device->legacyTextureBlending = FALSE;
6969 /* Create an index buffer, it's needed for indexed drawing */
6970 index_buffer_parent = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*index_buffer_parent));
6971 if (!index_buffer_parent)
6973 ERR("Failed to allocate index buffer parent memory.\n");
6974 ddraw_handle_table_destroy(&device->handle_table);
6975 return DDERR_OUTOFMEMORY;
6978 ddraw_parent_init(index_buffer_parent);
6980 hr = IWineD3DDevice_CreateIndexBuffer(ddraw->wineD3DDevice, 0x40000 /* Length. Don't know how long it should be */,
6981 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, index_buffer_parent,
6982 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
6983 if (FAILED(hr))
6985 ERR("Failed to create an index buffer, hr %#x.\n", hr);
6986 HeapFree(GetProcessHeap(), 0, index_buffer_parent);
6987 ddraw_handle_table_destroy(&device->handle_table);
6988 return hr;
6990 index_buffer_parent->child = (IUnknown *)device->indexbuffer;
6992 /* This is for convenience. */
6993 device->wineD3DDevice = ddraw->wineD3DDevice;
6994 IWineD3DDevice_AddRef(ddraw->wineD3DDevice);
6996 /* Render to the back buffer */
6997 hr = IWineD3DDevice_SetRenderTarget(ddraw->wineD3DDevice, 0, target->WineD3DSurface, TRUE);
6998 if (FAILED(hr))
7000 ERR("Failed to set render target, hr %#x.\n", hr);
7001 IParent_Release((IParent *)index_buffer_parent);
7002 ddraw_handle_table_destroy(&device->handle_table);
7003 return hr;
7006 /* FIXME: This is broken. The target AddRef() makes some sense, because
7007 * we store a pointer during initialization, but then that's also where
7008 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
7009 /* AddRef the render target. Also AddRef the render target from ddraw,
7010 * because if it is released before the app releases the D3D device, the
7011 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
7013 * In most cases, those surfaces are the same anyway, but this will simply
7014 * add another ref which is released when the device is destroyed. */
7015 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)target);
7016 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)ddraw->d3d_target);
7018 ddraw->d3ddevice = device;
7020 IWineD3DDevice_SetRenderState(ddraw->wineD3DDevice, WINED3DRS_ZENABLE,
7021 IDirect3DDeviceImpl_UpdateDepthStencil(device));
7023 return D3D_OK;