cmd: Use boolean types for boolean variables.
[wine/multimedia.git] / dlls / ddraw / device.c
blobe9e7744babd8824ad9a0fdf1cb0c66f5afac1536
1 /*
2 * Copyright (c) 1998-2004 Lionel Ulmer
3 * Copyright (c) 2002-2005 Christian Costa
4 * Copyright (c) 2006 Stefan Dösinger
5 * Copyright (c) 2008 Alexander Dorofeyev
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * IDirect3DDevice implementation, version 1, 2, 3 and 7. Rendering is relayed
22 * to WineD3D, some minimal DirectDraw specific management is handled here.
23 * The Direct3DDevice is NOT the parent of the WineD3DDevice, because d3d
24 * is initialized when DirectDraw creates the primary surface.
25 * Some type management is necessary, because some D3D types changed between
26 * D3D7 and D3D9.
30 #include "config.h"
31 #include "wine/port.h"
33 #include "ddraw_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
37 /* The device ID */
38 const GUID IID_D3DDEVICE_WineD3D = {
39 0xaef72d43,
40 0xb09a,
41 0x4b7b,
42 { 0xb7,0x98,0xc6,0x8a,0x77,0x2d,0x72,0x2a }
45 static inline void set_fpu_control_word(WORD fpucw)
47 #if defined(__i386__) && defined(__GNUC__)
48 __asm__ volatile ("fldcw %0" : : "m" (fpucw));
49 #elif defined(__i386__) && defined(_MSC_VER)
50 __asm fldcw fpucw;
51 #endif
54 static inline WORD d3d_fpu_setup(void)
56 WORD oldcw;
58 #if defined(__i386__) && defined(__GNUC__)
59 __asm__ volatile ("fnstcw %0" : "=m" (oldcw));
60 #elif defined(__i386__) && defined(_MSC_VER)
61 __asm fnstcw oldcw;
62 #else
63 static BOOL warned = FALSE;
64 if(!warned)
66 FIXME("FPUPRESERVE not implemented for this platform / compiler\n");
67 warned = TRUE;
69 return 0;
70 #endif
72 set_fpu_control_word(0x37f);
74 return oldcw;
77 /*****************************************************************************
78 * IUnknown Methods. Common for Version 1, 2, 3 and 7
79 *****************************************************************************/
81 /*****************************************************************************
82 * IDirect3DDevice7::QueryInterface
84 * Used to query other interfaces from a Direct3DDevice interface.
85 * It can return interface pointers to all Direct3DDevice versions as well
86 * as IDirectDraw and IDirect3D. For a link to QueryInterface
87 * rules see ddraw.c, IDirectDraw7::QueryInterface
89 * Exists in Version 1, 2, 3 and 7
91 * Params:
92 * refiid: Interface ID queried for
93 * obj: Used to return the interface pointer
95 * Returns:
96 * D3D_OK or E_NOINTERFACE
98 *****************************************************************************/
99 static HRESULT WINAPI
100 IDirect3DDeviceImpl_7_QueryInterface(IDirect3DDevice7 *iface,
101 REFIID refiid,
102 void **obj)
104 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
106 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(refiid), obj);
108 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
109 *obj = NULL;
111 if(!refiid)
112 return DDERR_INVALIDPARAMS;
114 if ( IsEqualGUID( &IID_IUnknown, refiid ) )
116 *obj = iface;
119 /* Check DirectDraw Interfaces. */
120 else if( IsEqualGUID( &IID_IDirectDraw7, refiid ) )
122 *obj = &This->ddraw->IDirectDraw7_iface;
123 TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
125 else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
127 *obj = &This->ddraw->IDirectDraw4_iface;
128 TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
130 else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
132 *obj = &This->ddraw->IDirectDraw2_iface;
133 TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
135 else if( IsEqualGUID( &IID_IDirectDraw, refiid ) )
137 *obj = &This->ddraw->IDirectDraw_iface;
138 TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
141 /* Direct3D */
142 else if ( IsEqualGUID( &IID_IDirect3D , refiid ) )
144 *obj = &This->ddraw->IDirect3D_iface;
145 TRACE("(%p) Returning IDirect3D interface at %p\n", This, *obj);
147 else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) )
149 *obj = &This->ddraw->IDirect3D2_iface;
150 TRACE("(%p) Returning IDirect3D2 interface at %p\n", This, *obj);
152 else if ( IsEqualGUID( &IID_IDirect3D3 , refiid ) )
154 *obj = &This->ddraw->IDirect3D3_iface;
155 TRACE("(%p) Returning IDirect3D3 interface at %p\n", This, *obj);
157 else if ( IsEqualGUID( &IID_IDirect3D7 , refiid ) )
159 *obj = &This->ddraw->IDirect3D7_iface;
160 TRACE("(%p) Returning IDirect3D7 interface at %p\n", This, *obj);
163 /* Direct3DDevice */
164 else if ( IsEqualGUID( &IID_IDirect3DDevice , refiid ) )
166 *obj = &This->IDirect3DDevice_iface;
167 TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
169 else if ( IsEqualGUID( &IID_IDirect3DDevice2 , refiid ) ) {
170 *obj = &This->IDirect3DDevice2_iface;
171 TRACE("(%p) Returning IDirect3DDevice2 interface at %p\n", This, *obj);
173 else if ( IsEqualGUID( &IID_IDirect3DDevice3 , refiid ) ) {
174 *obj = &This->IDirect3DDevice3_iface;
175 TRACE("(%p) Returning IDirect3DDevice3 interface at %p\n", This, *obj);
177 else if ( IsEqualGUID( &IID_IDirect3DDevice7 , refiid ) ) {
178 *obj = This;
179 TRACE("(%p) Returning IDirect3DDevice7 interface at %p\n", This, *obj);
182 /* Unknown interface */
183 else
185 ERR("(%p)->(%s, %p): No interface found\n", This, debugstr_guid(refiid), obj);
186 return E_NOINTERFACE;
189 /* AddRef the returned interface */
190 IUnknown_AddRef( (IUnknown *) *obj);
191 return D3D_OK;
194 static HRESULT WINAPI IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface, REFIID riid,
195 void **obj)
197 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
198 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
200 return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obj);
203 static HRESULT WINAPI IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface, REFIID riid,
204 void **obj)
206 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
207 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
209 return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obj);
212 static HRESULT WINAPI IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface, REFIID riid,
213 void **obp)
215 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
216 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
218 return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obp);
221 /*****************************************************************************
222 * IDirect3DDevice7::AddRef
224 * Increases the refcount....
225 * The most exciting Method, definitely
227 * Exists in Version 1, 2, 3 and 7
229 * Returns:
230 * The new refcount
232 *****************************************************************************/
233 static ULONG WINAPI
234 IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
236 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
237 ULONG ref = InterlockedIncrement(&This->ref);
239 TRACE("%p increasing refcount to %u.\n", This, ref);
241 return ref;
244 static ULONG WINAPI IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
246 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
247 TRACE("iface %p.\n", iface);
249 return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
252 static ULONG WINAPI IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
254 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
255 TRACE("iface %p.\n", iface);
257 return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
260 static ULONG WINAPI IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
262 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
263 TRACE("iface %p.\n", iface);
265 return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
268 /*****************************************************************************
269 * IDirect3DDevice7::Release
271 * Decreases the refcount of the interface
272 * When the refcount is reduced to 0, the object is destroyed.
274 * Exists in Version 1, 2, 3 and 7
276 * Returns:d
277 * The new refcount
279 *****************************************************************************/
280 static ULONG WINAPI
281 IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
283 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
284 ULONG ref = InterlockedDecrement(&This->ref);
286 TRACE("%p decreasing refcount to %u.\n", This, ref);
288 /* This method doesn't destroy the WineD3DDevice, because it's still in use for
289 * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
290 * when the render target is released
292 if (ref == 0)
294 DWORD i;
296 wined3d_mutex_lock();
298 /* There is no need to unset any resources here, wined3d will take
299 * care of that on Uninit3D(). */
301 /* Free the index buffer. */
302 wined3d_buffer_decref(This->indexbuffer);
304 /* Set the device up to render to the front buffer since the back
305 * buffer will vanish soon. */
306 wined3d_device_set_render_target(This->wined3d_device, 0,
307 This->ddraw->wined3d_frontbuffer, TRUE);
309 /* Release the WineD3DDevice. This won't destroy it. */
310 if (!wined3d_device_decref(This->wined3d_device))
311 ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This->wined3d_device);
313 /* The texture handles should be unset by now, but there might be some bits
314 * missing in our reference counting(needs test). Do a sanity check. */
315 for (i = 0; i < This->handle_table.entry_count; ++i)
317 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
319 switch (entry->type)
321 case DDRAW_HANDLE_FREE:
322 break;
324 case DDRAW_HANDLE_MATERIAL:
326 IDirect3DMaterialImpl *m = entry->object;
327 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
328 m->Handle = 0;
329 break;
332 case DDRAW_HANDLE_MATRIX:
334 /* No FIXME here because this might happen because of sloppy applications. */
335 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
336 IDirect3DDevice_DeleteMatrix(&This->IDirect3DDevice_iface, i + 1);
337 break;
340 case DDRAW_HANDLE_STATEBLOCK:
342 /* No FIXME here because this might happen because of sloppy applications. */
343 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
344 IDirect3DDevice7_DeleteStateBlock(iface, i + 1);
345 break;
348 case DDRAW_HANDLE_SURFACE:
350 IDirectDrawSurfaceImpl *surf = entry->object;
351 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
352 surf->Handle = 0;
353 break;
356 default:
357 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
358 break;
362 ddraw_handle_table_destroy(&This->handle_table);
364 TRACE("Releasing target %p.\n", This->target);
365 /* Release the render target and the WineD3D render target
366 * (See IDirect3D7::CreateDevice for more comments on this)
368 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
369 TRACE("Target release done\n");
371 This->ddraw->d3ddevice = NULL;
373 /* Now free the structure */
374 HeapFree(GetProcessHeap(), 0, This);
375 wined3d_mutex_unlock();
378 TRACE("Done\n");
379 return ref;
382 static ULONG WINAPI IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
384 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
385 TRACE("iface %p.\n", iface);
387 return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
390 static ULONG WINAPI IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
392 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
393 TRACE("iface %p.\n", iface);
395 return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
398 static ULONG WINAPI IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
400 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
401 TRACE("iface %p.\n", iface);
403 return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
406 /*****************************************************************************
407 * IDirect3DDevice Methods
408 *****************************************************************************/
410 /*****************************************************************************
411 * IDirect3DDevice::Initialize
413 * Initializes a Direct3DDevice. This implementation is a no-op, as all
414 * initialization is done at create time.
416 * Exists in Version 1
418 * Parameters:
419 * No idea what they mean, as the MSDN page is gone
421 * Returns: DD_OK
423 *****************************************************************************/
424 static HRESULT WINAPI
425 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
426 IDirect3D *Direct3D, GUID *guid,
427 D3DDEVICEDESC *Desc)
429 /* It shouldn't be crucial, but print a FIXME, I'm interested if
430 * any game calls it and when. */
431 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
432 iface, Direct3D, debugstr_guid(guid), Desc);
434 return D3D_OK;
437 /*****************************************************************************
438 * IDirect3DDevice7::GetCaps
440 * Retrieves the device's capabilities
442 * This implementation is used for Version 7 only, the older versions have
443 * their own implementation.
445 * Parameters:
446 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
448 * Returns:
449 * D3D_OK on success
450 * D3DERR_* if a problem occurs. See WineD3D
452 *****************************************************************************/
453 static HRESULT
454 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
455 D3DDEVICEDESC7 *Desc)
457 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
458 D3DDEVICEDESC OldDesc;
460 TRACE("iface %p, device_desc %p.\n", iface, Desc);
462 /* Call the same function used by IDirect3D, this saves code */
463 return IDirect3DImpl_GetCaps(This->ddraw->wined3d, &OldDesc, Desc);
466 static HRESULT WINAPI
467 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
468 D3DDEVICEDESC7 *Desc)
470 return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
473 static HRESULT WINAPI
474 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
475 D3DDEVICEDESC7 *Desc)
477 HRESULT hr;
478 WORD old_fpucw;
480 old_fpucw = d3d_fpu_setup();
481 hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
482 set_fpu_control_word(old_fpucw);
484 return hr;
486 /*****************************************************************************
487 * IDirect3DDevice3::GetCaps
489 * Retrieves the capabilities of the hardware device and the emulation
490 * device. For Wine, hardware and emulation are the same (it's all HW).
492 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
494 * Parameters:
495 * HWDesc: Structure to fill with the HW caps
496 * HelDesc: Structure to fill with the hardware emulation caps
498 * Returns:
499 * D3D_OK on success
500 * D3DERR_* if a problem occurs. See WineD3D
502 *****************************************************************************/
503 static HRESULT WINAPI
504 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
505 D3DDEVICEDESC *HWDesc,
506 D3DDEVICEDESC *HelDesc)
508 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
509 D3DDEVICEDESC7 newDesc;
510 HRESULT hr;
512 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
514 hr = IDirect3DImpl_GetCaps(This->ddraw->wined3d, HWDesc, &newDesc);
515 if(hr != D3D_OK) return hr;
517 *HelDesc = *HWDesc;
518 return D3D_OK;
521 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
522 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
524 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
525 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
526 return IDirect3DDevice3_GetCaps(&This->IDirect3DDevice3_iface, D3DHWDevDesc, D3DHELDevDesc);
529 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
530 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
532 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
533 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
534 return IDirect3DDevice3_GetCaps(&This->IDirect3DDevice3_iface, D3DHWDevDesc, D3DHELDevDesc);
537 /*****************************************************************************
538 * IDirect3DDevice2::SwapTextureHandles
540 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
542 * Parameters:
543 * Tex1, Tex2: The 2 Textures to swap
545 * Returns:
546 * D3D_OK
548 *****************************************************************************/
549 static HRESULT WINAPI
550 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
551 IDirect3DTexture2 *Tex1,
552 IDirect3DTexture2 *Tex2)
554 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
555 IDirectDrawSurfaceImpl *surf1 = unsafe_impl_from_IDirect3DTexture2(Tex1);
556 IDirectDrawSurfaceImpl *surf2 = unsafe_impl_from_IDirect3DTexture2(Tex2);
557 DWORD h1, h2;
559 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, Tex1, Tex2);
561 wined3d_mutex_lock();
563 h1 = surf1->Handle - 1;
564 h2 = surf2->Handle - 1;
565 This->handle_table.entries[h1].object = surf2;
566 This->handle_table.entries[h2].object = surf1;
567 surf2->Handle = h1 + 1;
568 surf1->Handle = h2 + 1;
570 wined3d_mutex_unlock();
572 return D3D_OK;
575 static HRESULT WINAPI IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
576 IDirect3DTexture *D3DTex1, IDirect3DTexture *D3DTex2)
578 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
579 IDirectDrawSurfaceImpl *surf1 = unsafe_impl_from_IDirect3DTexture(D3DTex1);
580 IDirectDrawSurfaceImpl *surf2 = unsafe_impl_from_IDirect3DTexture(D3DTex2);
581 IDirect3DTexture2 *t1 = surf1 ? &surf1->IDirect3DTexture2_iface : NULL;
582 IDirect3DTexture2 *t2 = surf2 ? &surf2->IDirect3DTexture2_iface : NULL;
584 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, D3DTex1, D3DTex2);
586 return IDirect3DDevice2_SwapTextureHandles(&This->IDirect3DDevice2_iface, t1, t2);
589 /*****************************************************************************
590 * IDirect3DDevice3::GetStats
592 * This method seems to retrieve some stats from the device.
593 * The MSDN documentation doesn't exist any more, but the D3DSTATS
594 * structure suggests that the amount of drawn primitives and processed
595 * vertices is returned.
597 * Exists in Version 1, 2 and 3
599 * Parameters:
600 * Stats: Pointer to a D3DSTATS structure to be filled
602 * Returns:
603 * D3D_OK on success
604 * DDERR_INVALIDPARAMS if Stats == NULL
606 *****************************************************************************/
607 static HRESULT WINAPI
608 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
609 D3DSTATS *Stats)
611 FIXME("iface %p, stats %p stub!\n", iface, Stats);
613 if(!Stats)
614 return DDERR_INVALIDPARAMS;
616 /* Fill the Stats with 0 */
617 Stats->dwTrianglesDrawn = 0;
618 Stats->dwLinesDrawn = 0;
619 Stats->dwPointsDrawn = 0;
620 Stats->dwSpansDrawn = 0;
621 Stats->dwVerticesProcessed = 0;
623 return D3D_OK;
626 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *Stats)
628 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
630 TRACE("iface %p, stats %p.\n", iface, Stats);
632 return IDirect3DDevice3_GetStats(&This->IDirect3DDevice3_iface, Stats);
635 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface, D3DSTATS *Stats)
637 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
639 TRACE("iface %p, stats %p.\n", iface, Stats);
641 return IDirect3DDevice3_GetStats(&This->IDirect3DDevice3_iface, Stats);
644 /*****************************************************************************
645 * IDirect3DDevice::CreateExecuteBuffer
647 * Creates an IDirect3DExecuteBuffer, used for rendering with a
648 * Direct3DDevice.
650 * Version 1 only.
652 * Params:
653 * Desc: Buffer description
654 * ExecuteBuffer: Address to return the Interface pointer at
655 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
656 * support
658 * Returns:
659 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
660 * DDERR_OUTOFMEMORY if we ran out of memory
661 * D3D_OK on success
663 *****************************************************************************/
664 static HRESULT WINAPI
665 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
666 D3DEXECUTEBUFFERDESC *Desc,
667 IDirect3DExecuteBuffer **ExecuteBuffer,
668 IUnknown *UnkOuter)
670 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
671 IDirect3DExecuteBufferImpl* object;
672 HRESULT hr;
674 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
675 iface, Desc, ExecuteBuffer, UnkOuter);
677 if(UnkOuter)
678 return CLASS_E_NOAGGREGATION;
680 /* Allocate the new Execute Buffer */
681 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
682 if(!object)
684 ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
685 return DDERR_OUTOFMEMORY;
688 hr = d3d_execute_buffer_init(object, This, Desc);
689 if (FAILED(hr))
691 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
692 HeapFree(GetProcessHeap(), 0, object);
693 return hr;
696 *ExecuteBuffer = &object->IDirect3DExecuteBuffer_iface;
698 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
700 return D3D_OK;
703 /*****************************************************************************
704 * IDirect3DDevice::Execute
706 * Executes all the stuff in an execute buffer.
708 * Params:
709 * ExecuteBuffer: The buffer to execute
710 * Viewport: The viewport used for rendering
711 * Flags: Some flags
713 * Returns:
714 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
715 * D3D_OK on success
717 *****************************************************************************/
718 static HRESULT WINAPI IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
719 IDirect3DExecuteBuffer *ExecuteBuffer, IDirect3DViewport *Viewport, DWORD Flags)
721 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
722 IDirect3DExecuteBufferImpl *buffer = unsafe_impl_from_IDirect3DExecuteBuffer(ExecuteBuffer);
723 IDirect3DViewportImpl *Direct3DViewportImpl = unsafe_impl_from_IDirect3DViewport(Viewport);
724 HRESULT hr;
726 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, Viewport, Flags);
728 if(!buffer)
729 return DDERR_INVALIDPARAMS;
731 /* Execute... */
732 wined3d_mutex_lock();
733 hr = d3d_execute_buffer_execute(buffer, This, Direct3DViewportImpl);
734 wined3d_mutex_unlock();
736 return hr;
739 /*****************************************************************************
740 * IDirect3DDevice3::AddViewport
742 * Add a Direct3DViewport to the device's viewport list. These viewports
743 * are wrapped to IDirect3DDevice7 viewports in viewport.c
745 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
746 * are the same interfaces.
748 * Params:
749 * Viewport: The viewport to add
751 * Returns:
752 * DDERR_INVALIDPARAMS if Viewport == NULL
753 * D3D_OK on success
755 *****************************************************************************/
756 static HRESULT WINAPI
757 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
758 IDirect3DViewport3 *Viewport)
760 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
761 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(Viewport);
763 TRACE("iface %p, viewport %p.\n", iface, Viewport);
765 /* Sanity check */
766 if(!vp)
767 return DDERR_INVALIDPARAMS;
769 wined3d_mutex_lock();
770 list_add_head(&This->viewport_list, &vp->entry);
771 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
772 so set active_device here. */
773 wined3d_mutex_unlock();
775 return D3D_OK;
778 static HRESULT WINAPI IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
779 IDirect3DViewport2 *Direct3DViewport2)
781 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
782 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
784 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
786 return IDirect3DDevice3_AddViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
789 static HRESULT WINAPI IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
790 IDirect3DViewport *Direct3DViewport)
792 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
793 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport(Direct3DViewport);
795 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
797 return IDirect3DDevice3_AddViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
800 /*****************************************************************************
801 * IDirect3DDevice3::DeleteViewport
803 * Deletes a Direct3DViewport from the device's viewport list.
805 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
806 * are equal.
808 * Params:
809 * Viewport: The viewport to delete
811 * Returns:
812 * D3D_OK on success
813 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
815 *****************************************************************************/
816 static HRESULT WINAPI IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
818 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
819 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
821 TRACE("iface %p, viewport %p.\n", iface, viewport);
823 wined3d_mutex_lock();
825 if (vp->active_device != This)
827 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
828 wined3d_mutex_unlock();
829 return DDERR_INVALIDPARAMS;
832 vp->active_device = NULL;
833 list_remove(&vp->entry);
835 wined3d_mutex_unlock();
837 return D3D_OK;
840 static HRESULT WINAPI IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
841 IDirect3DViewport2 *Direct3DViewport2)
843 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
844 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
846 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
848 return IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
851 static HRESULT WINAPI IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
852 IDirect3DViewport *Direct3DViewport)
854 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
855 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport(Direct3DViewport);
857 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
859 return IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
862 /*****************************************************************************
863 * IDirect3DDevice3::NextViewport
865 * Returns a viewport from the viewport list, depending on the
866 * passed viewport and the flags.
868 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
869 * are equal.
871 * Params:
872 * Viewport: Viewport to use for beginning the search
873 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
875 * Returns:
876 * D3D_OK on success
877 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
879 *****************************************************************************/
880 static HRESULT WINAPI
881 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
882 IDirect3DViewport3 *Viewport3,
883 IDirect3DViewport3 **lplpDirect3DViewport3,
884 DWORD Flags)
886 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
887 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(Viewport3);
888 IDirect3DViewportImpl *next;
889 struct list *entry;
891 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
892 iface, Viewport3, lplpDirect3DViewport3, Flags);
894 if(!vp)
896 *lplpDirect3DViewport3 = NULL;
897 return DDERR_INVALIDPARAMS;
901 wined3d_mutex_lock();
902 switch (Flags)
904 case D3DNEXT_NEXT:
905 entry = list_next(&This->viewport_list, &vp->entry);
906 break;
908 case D3DNEXT_HEAD:
909 entry = list_head(&This->viewport_list);
910 break;
912 case D3DNEXT_TAIL:
913 entry = list_tail(&This->viewport_list);
914 break;
916 default:
917 WARN("Invalid flags %#x.\n", Flags);
918 *lplpDirect3DViewport3 = NULL;
919 wined3d_mutex_unlock();
920 return DDERR_INVALIDPARAMS;
923 if (entry)
925 next = LIST_ENTRY(entry, IDirect3DViewportImpl, entry);
926 *lplpDirect3DViewport3 = &next->IDirect3DViewport3_iface;
928 else
929 *lplpDirect3DViewport3 = NULL;
931 wined3d_mutex_unlock();
933 return D3D_OK;
936 static HRESULT WINAPI IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
937 IDirect3DViewport2 *Viewport2, IDirect3DViewport2 **lplpDirect3DViewport2, DWORD Flags)
939 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
940 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Viewport2);
941 IDirect3DViewport3 *res;
942 HRESULT hr;
944 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
945 iface, Viewport2, lplpDirect3DViewport2, Flags);
947 hr = IDirect3DDevice3_NextViewport(&This->IDirect3DDevice3_iface,
948 &vp->IDirect3DViewport3_iface, &res, Flags);
949 *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
950 return hr;
953 static HRESULT WINAPI IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
954 IDirect3DViewport *Viewport, IDirect3DViewport **lplpDirect3DViewport, DWORD Flags)
956 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
957 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport(Viewport);
958 IDirect3DViewport3 *res;
959 HRESULT hr;
961 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
962 iface, Viewport, lplpDirect3DViewport, Flags);
964 hr = IDirect3DDevice3_NextViewport(&This->IDirect3DDevice3_iface,
965 &vp->IDirect3DViewport3_iface, &res, Flags);
966 *lplpDirect3DViewport = (IDirect3DViewport *)res;
967 return hr;
970 /*****************************************************************************
971 * IDirect3DDevice::Pick
973 * Executes an execute buffer without performing rendering. Instead, a
974 * list of primitives that intersect with (x1,y1) of the passed rectangle
975 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
976 * this list.
978 * Version 1 only
980 * Params:
981 * ExecuteBuffer: Buffer to execute
982 * Viewport: Viewport to use for execution
983 * Flags: None are defined, according to the SDK
984 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
985 * x2 and y2 are ignored.
987 * Returns:
988 * D3D_OK because it's a stub
990 *****************************************************************************/
991 static HRESULT WINAPI
992 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
993 IDirect3DExecuteBuffer *ExecuteBuffer,
994 IDirect3DViewport *Viewport,
995 DWORD Flags,
996 D3DRECT *Rect)
998 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
999 iface, ExecuteBuffer, Viewport, Flags, wine_dbgstr_rect((RECT *)Rect));
1001 return D3D_OK;
1004 /*****************************************************************************
1005 * IDirect3DDevice::GetPickRecords
1007 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1009 * Version 1 only
1011 * Params:
1012 * Count: Pointer to a DWORD containing the numbers of pick records to
1013 * retrieve
1014 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1016 * Returns:
1017 * D3D_OK, because it's a stub
1019 *****************************************************************************/
1020 static HRESULT WINAPI
1021 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1022 DWORD *Count,
1023 D3DPICKRECORD *D3DPickRec)
1025 FIXME("iface %p, count %p, records %p stub!\n", iface, Count, D3DPickRec);
1027 return D3D_OK;
1030 /*****************************************************************************
1031 * IDirect3DDevice7::EnumTextureformats
1033 * Enumerates the supported texture formats. It has a list of all possible
1034 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1035 * WineD3D supports it. If so, then it is passed to the app.
1037 * This is for Version 7 and 3, older versions have a different
1038 * callback function and their own implementation
1040 * Params:
1041 * Callback: Callback to call for each enumerated format
1042 * Arg: Argument to pass to the callback
1044 * Returns:
1045 * D3D_OK on success
1046 * DDERR_INVALIDPARAMS if Callback == NULL
1048 *****************************************************************************/
1049 static HRESULT
1050 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1051 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1052 void *Arg)
1054 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1055 struct wined3d_display_mode mode;
1056 HRESULT hr;
1057 unsigned int i;
1059 static const enum wined3d_format_id FormatList[] =
1061 /* 16 bit */
1062 WINED3DFMT_B5G5R5X1_UNORM,
1063 WINED3DFMT_B5G5R5A1_UNORM,
1064 WINED3DFMT_B4G4R4A4_UNORM,
1065 WINED3DFMT_B5G6R5_UNORM,
1066 /* 32 bit */
1067 WINED3DFMT_B8G8R8X8_UNORM,
1068 WINED3DFMT_B8G8R8A8_UNORM,
1069 /* 8 bit */
1070 WINED3DFMT_B2G3R3_UNORM,
1071 WINED3DFMT_P8_UINT,
1072 /* FOURCC codes */
1073 WINED3DFMT_DXT1,
1074 WINED3DFMT_DXT3,
1075 WINED3DFMT_DXT5,
1078 static const enum wined3d_format_id BumpFormatList[] =
1080 WINED3DFMT_R8G8_SNORM,
1081 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1082 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1083 WINED3DFMT_R16G16_SNORM,
1084 WINED3DFMT_R10G11B11_SNORM,
1085 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1088 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1090 if(!Callback)
1091 return DDERR_INVALIDPARAMS;
1093 wined3d_mutex_lock();
1095 memset(&mode, 0, sizeof(mode));
1096 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1097 if (FAILED(hr))
1099 wined3d_mutex_unlock();
1100 WARN("Cannot get the current adapter format\n");
1101 return hr;
1104 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1106 hr = wined3d_check_device_format(This->ddraw->wined3d, WINED3DADAPTER_DEFAULT, WINED3DDEVTYPE_HAL,
1107 mode.format_id, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1108 if (hr == D3D_OK)
1110 DDPIXELFORMAT pformat;
1112 memset(&pformat, 0, sizeof(pformat));
1113 pformat.dwSize = sizeof(pformat);
1114 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1116 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1117 hr = Callback(&pformat, Arg);
1118 if(hr != DDENUMRET_OK)
1120 TRACE("Format enumeration cancelled by application\n");
1121 wined3d_mutex_unlock();
1122 return D3D_OK;
1127 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1129 hr = wined3d_check_device_format(This->ddraw->wined3d, WINED3DADAPTER_DEFAULT,
1130 WINED3DDEVTYPE_HAL, mode.format_id, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1131 WINED3DRTYPE_TEXTURE, BumpFormatList[i], SURFACE_OPENGL);
1132 if (hr == D3D_OK)
1134 DDPIXELFORMAT pformat;
1136 memset(&pformat, 0, sizeof(pformat));
1137 pformat.dwSize = sizeof(pformat);
1138 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1140 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1141 hr = Callback(&pformat, Arg);
1142 if(hr != DDENUMRET_OK)
1144 TRACE("Format enumeration cancelled by application\n");
1145 wined3d_mutex_unlock();
1146 return D3D_OK;
1150 TRACE("End of enumeration\n");
1151 wined3d_mutex_unlock();
1153 return D3D_OK;
1156 static HRESULT WINAPI
1157 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1158 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1159 void *Arg)
1161 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1164 static HRESULT WINAPI
1165 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1166 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1167 void *Arg)
1169 HRESULT hr;
1170 WORD old_fpucw;
1172 old_fpucw = d3d_fpu_setup();
1173 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1174 set_fpu_control_word(old_fpucw);
1176 return hr;
1179 static HRESULT WINAPI IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1180 LPD3DENUMPIXELFORMATSCALLBACK Callback, void *Arg)
1182 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1184 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1186 return IDirect3DDevice7_EnumTextureFormats(&This->IDirect3DDevice7_iface, Callback, Arg);
1189 /*****************************************************************************
1190 * IDirect3DDevice2::EnumTextureformats
1192 * EnumTextureFormats for Version 1 and 2, see
1193 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1195 * This version has a different callback and does not enumerate FourCC
1196 * formats
1198 *****************************************************************************/
1199 static HRESULT WINAPI
1200 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1201 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1202 void *Arg)
1204 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1205 struct wined3d_display_mode mode;
1206 HRESULT hr;
1207 unsigned int i;
1209 static const enum wined3d_format_id FormatList[] =
1211 /* 16 bit */
1212 WINED3DFMT_B5G5R5X1_UNORM,
1213 WINED3DFMT_B5G5R5A1_UNORM,
1214 WINED3DFMT_B4G4R4A4_UNORM,
1215 WINED3DFMT_B5G6R5_UNORM,
1216 /* 32 bit */
1217 WINED3DFMT_B8G8R8X8_UNORM,
1218 WINED3DFMT_B8G8R8A8_UNORM,
1219 /* 8 bit */
1220 WINED3DFMT_B2G3R3_UNORM,
1221 WINED3DFMT_P8_UINT,
1222 /* FOURCC codes - Not in this version*/
1225 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1227 if(!Callback)
1228 return DDERR_INVALIDPARAMS;
1230 wined3d_mutex_lock();
1232 memset(&mode, 0, sizeof(mode));
1233 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1234 if (FAILED(hr))
1236 wined3d_mutex_unlock();
1237 WARN("Cannot get the current adapter format\n");
1238 return hr;
1241 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1243 hr = wined3d_check_device_format(This->ddraw->wined3d, 0, WINED3DDEVTYPE_HAL,
1244 mode.format_id, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1245 if (hr == D3D_OK)
1247 DDSURFACEDESC sdesc;
1249 memset(&sdesc, 0, sizeof(sdesc));
1250 sdesc.dwSize = sizeof(sdesc);
1251 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1252 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1253 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1254 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1256 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1257 hr = Callback(&sdesc, Arg);
1258 if(hr != DDENUMRET_OK)
1260 TRACE("Format enumeration cancelled by application\n");
1261 wined3d_mutex_unlock();
1262 return D3D_OK;
1266 TRACE("End of enumeration\n");
1267 wined3d_mutex_unlock();
1269 return D3D_OK;
1272 static HRESULT WINAPI IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1273 LPD3DENUMTEXTUREFORMATSCALLBACK Callback, void *Arg)
1275 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1277 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1279 return IDirect3DDevice2_EnumTextureFormats(&This->IDirect3DDevice2_iface, Callback, Arg);
1282 /*****************************************************************************
1283 * IDirect3DDevice::CreateMatrix
1285 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1286 * allocated for the handle.
1288 * Version 1 only
1290 * Params
1291 * D3DMatHandle: Address to return the handle at
1293 * Returns:
1294 * D3D_OK on success
1295 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1297 *****************************************************************************/
1298 static HRESULT WINAPI
1299 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1301 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1302 D3DMATRIX *Matrix;
1303 DWORD h;
1305 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1307 if(!D3DMatHandle)
1308 return DDERR_INVALIDPARAMS;
1310 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1311 if(!Matrix)
1313 ERR("Out of memory when allocating a D3DMATRIX\n");
1314 return DDERR_OUTOFMEMORY;
1317 wined3d_mutex_lock();
1319 h = ddraw_allocate_handle(&This->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1320 if (h == DDRAW_INVALID_HANDLE)
1322 ERR("Failed to allocate a matrix handle.\n");
1323 HeapFree(GetProcessHeap(), 0, Matrix);
1324 wined3d_mutex_unlock();
1325 return DDERR_OUTOFMEMORY;
1328 *D3DMatHandle = h + 1;
1330 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1332 wined3d_mutex_unlock();
1334 return D3D_OK;
1337 /*****************************************************************************
1338 * IDirect3DDevice::SetMatrix
1340 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1341 * allocated for the handle
1343 * Version 1 only
1345 * Params:
1346 * D3DMatHandle: Handle to set the matrix to
1347 * D3DMatrix: Matrix to set
1349 * Returns:
1350 * D3D_OK on success
1351 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1352 * to set is NULL
1354 *****************************************************************************/
1355 static HRESULT WINAPI
1356 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1357 D3DMATRIXHANDLE D3DMatHandle,
1358 D3DMATRIX *D3DMatrix)
1360 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1361 D3DMATRIX *m;
1363 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1365 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1367 wined3d_mutex_lock();
1369 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1370 if (!m)
1372 WARN("Invalid matrix handle.\n");
1373 wined3d_mutex_unlock();
1374 return DDERR_INVALIDPARAMS;
1377 if (TRACE_ON(ddraw))
1378 dump_D3DMATRIX(D3DMatrix);
1380 *m = *D3DMatrix;
1382 if (D3DMatHandle == This->world)
1383 wined3d_device_set_transform(This->wined3d_device,
1384 WINED3DTS_WORLDMATRIX(0), (struct wined3d_matrix *)D3DMatrix);
1386 if (D3DMatHandle == This->view)
1387 wined3d_device_set_transform(This->wined3d_device,
1388 WINED3DTS_VIEW, (struct wined3d_matrix *)D3DMatrix);
1390 if (D3DMatHandle == This->proj)
1391 wined3d_device_set_transform(This->wined3d_device,
1392 WINED3DTS_PROJECTION, (struct wined3d_matrix *)D3DMatrix);
1394 wined3d_mutex_unlock();
1396 return D3D_OK;
1399 /*****************************************************************************
1400 * IDirect3DDevice::GetMatrix
1402 * Returns the content of a D3DMATRIX handle
1404 * Version 1 only
1406 * Params:
1407 * D3DMatHandle: Matrix handle to read the content from
1408 * D3DMatrix: Address to store the content at
1410 * Returns:
1411 * D3D_OK on success
1412 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1414 *****************************************************************************/
1415 static HRESULT WINAPI
1416 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1417 D3DMATRIXHANDLE D3DMatHandle,
1418 D3DMATRIX *D3DMatrix)
1420 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1421 D3DMATRIX *m;
1423 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1425 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1427 wined3d_mutex_lock();
1429 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1430 if (!m)
1432 WARN("Invalid matrix handle.\n");
1433 wined3d_mutex_unlock();
1434 return DDERR_INVALIDPARAMS;
1437 *D3DMatrix = *m;
1439 wined3d_mutex_unlock();
1441 return D3D_OK;
1444 /*****************************************************************************
1445 * IDirect3DDevice::DeleteMatrix
1447 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1449 * Version 1 only
1451 * Params:
1452 * D3DMatHandle: Handle to destroy
1454 * Returns:
1455 * D3D_OK on success
1456 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1458 *****************************************************************************/
1459 static HRESULT WINAPI
1460 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1461 D3DMATRIXHANDLE D3DMatHandle)
1463 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1464 D3DMATRIX *m;
1466 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1468 wined3d_mutex_lock();
1470 m = ddraw_free_handle(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1471 if (!m)
1473 WARN("Invalid matrix handle.\n");
1474 wined3d_mutex_unlock();
1475 return DDERR_INVALIDPARAMS;
1478 wined3d_mutex_unlock();
1480 HeapFree(GetProcessHeap(), 0, m);
1482 return D3D_OK;
1485 /*****************************************************************************
1486 * IDirect3DDevice7::BeginScene
1488 * This method must be called before any rendering is performed.
1489 * IDirect3DDevice::EndScene has to be called after the scene is complete
1491 * Version 1, 2, 3 and 7
1493 * Returns:
1494 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1495 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1496 * started scene).
1498 *****************************************************************************/
1499 static HRESULT
1500 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1502 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1503 HRESULT hr;
1505 TRACE("iface %p.\n", iface);
1507 wined3d_mutex_lock();
1508 hr = wined3d_device_begin_scene(This->wined3d_device);
1509 wined3d_mutex_unlock();
1511 if(hr == WINED3D_OK) return D3D_OK;
1512 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1515 static HRESULT WINAPI
1516 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1518 return IDirect3DDeviceImpl_7_BeginScene(iface);
1521 static HRESULT WINAPI
1522 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1524 HRESULT hr;
1525 WORD old_fpucw;
1527 old_fpucw = d3d_fpu_setup();
1528 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1529 set_fpu_control_word(old_fpucw);
1531 return hr;
1534 static HRESULT WINAPI IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1536 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1537 TRACE("iface %p.\n", iface);
1539 return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
1542 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1544 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1545 TRACE("iface %p.\n", iface);
1547 return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
1550 static HRESULT WINAPI IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1552 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1553 TRACE("iface %p.\n", iface);
1555 return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
1558 /*****************************************************************************
1559 * IDirect3DDevice7::EndScene
1561 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1562 * This method must be called after rendering is finished.
1564 * Version 1, 2, 3 and 7
1566 * Returns:
1567 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1568 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1569 * that only if the scene was already ended.
1571 *****************************************************************************/
1572 static HRESULT
1573 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1575 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1576 HRESULT hr;
1578 TRACE("iface %p.\n", iface);
1580 wined3d_mutex_lock();
1581 hr = wined3d_device_end_scene(This->wined3d_device);
1582 wined3d_mutex_unlock();
1584 if(hr == WINED3D_OK) return D3D_OK;
1585 else return D3DERR_SCENE_NOT_IN_SCENE;
1588 static HRESULT WINAPI DECLSPEC_HOTPATCH
1589 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1591 return IDirect3DDeviceImpl_7_EndScene(iface);
1594 static HRESULT WINAPI DECLSPEC_HOTPATCH
1595 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1597 HRESULT hr;
1598 WORD old_fpucw;
1600 old_fpucw = d3d_fpu_setup();
1601 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1602 set_fpu_control_word(old_fpucw);
1604 return hr;
1607 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1609 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1610 TRACE("iface %p.\n", iface);
1612 return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
1615 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1617 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1618 TRACE("iface %p.\n", iface);
1620 return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
1623 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1625 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1626 TRACE("iface %p.\n", iface);
1628 return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
1631 /*****************************************************************************
1632 * IDirect3DDevice7::GetDirect3D
1634 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1635 * this device.
1637 * Params:
1638 * Direct3D7: Address to store the interface pointer at
1640 * Returns:
1641 * D3D_OK on success
1642 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1644 *****************************************************************************/
1645 static HRESULT WINAPI
1646 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1647 IDirect3D7 **Direct3D7)
1649 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1651 TRACE("iface %p, d3d %p.\n", iface, Direct3D7);
1653 if(!Direct3D7)
1654 return DDERR_INVALIDPARAMS;
1656 *Direct3D7 = &This->ddraw->IDirect3D7_iface;
1657 IDirect3D7_AddRef(*Direct3D7);
1659 TRACE(" returning interface %p\n", *Direct3D7);
1660 return D3D_OK;
1663 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1664 IDirect3D3 **Direct3D3)
1666 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1668 TRACE("iface %p, d3d %p.\n", iface, Direct3D3);
1670 if(!Direct3D3)
1671 return DDERR_INVALIDPARAMS;
1673 IDirect3D3_AddRef(&This->ddraw->IDirect3D3_iface);
1674 *Direct3D3 = &This->ddraw->IDirect3D3_iface;
1675 TRACE(" returning interface %p\n", *Direct3D3);
1676 return D3D_OK;
1679 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1680 IDirect3D2 **Direct3D2)
1682 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1684 TRACE("iface %p, d3d %p.\n", iface, Direct3D2);
1686 if(!Direct3D2)
1687 return DDERR_INVALIDPARAMS;
1689 IDirect3D2_AddRef(&This->ddraw->IDirect3D2_iface);
1690 *Direct3D2 = &This->ddraw->IDirect3D2_iface;
1691 TRACE(" returning interface %p\n", *Direct3D2);
1692 return D3D_OK;
1695 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1696 IDirect3D **Direct3D)
1698 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1700 TRACE("iface %p, d3d %p.\n", iface, Direct3D);
1702 if(!Direct3D)
1703 return DDERR_INVALIDPARAMS;
1705 IDirect3D_AddRef(&This->ddraw->IDirect3D_iface);
1706 *Direct3D = &This->ddraw->IDirect3D_iface;
1707 TRACE(" returning interface %p\n", *Direct3D);
1708 return D3D_OK;
1711 /*****************************************************************************
1712 * IDirect3DDevice3::SetCurrentViewport
1714 * Sets a Direct3DViewport as the current viewport.
1715 * For the thunks note that all viewport interface versions are equal
1717 * Params:
1718 * Direct3DViewport3: The viewport to set
1720 * Version 2 and 3
1722 * Returns:
1723 * D3D_OK on success
1724 * (Is a NULL viewport valid?)
1726 *****************************************************************************/
1727 static HRESULT WINAPI
1728 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1729 IDirect3DViewport3 *Direct3DViewport3)
1731 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1732 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(Direct3DViewport3);
1734 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1736 wined3d_mutex_lock();
1737 /* Do nothing if the specified viewport is the same as the current one */
1738 if (This->current_viewport == vp )
1740 wined3d_mutex_unlock();
1741 return D3D_OK;
1744 if (vp->active_device != This)
1746 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1747 wined3d_mutex_unlock();
1748 return DDERR_INVALIDPARAMS;
1751 /* Release previous viewport and AddRef the new one */
1752 if (This->current_viewport)
1754 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1755 &This->current_viewport->IDirect3DViewport3_iface);
1756 IDirect3DViewport3_Release(&This->current_viewport->IDirect3DViewport3_iface);
1758 IDirect3DViewport3_AddRef(Direct3DViewport3);
1760 /* Set this viewport as the current viewport */
1761 This->current_viewport = vp;
1763 /* Activate this viewport */
1764 viewport_activate(This->current_viewport, FALSE);
1766 wined3d_mutex_unlock();
1768 return D3D_OK;
1771 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1772 IDirect3DViewport2 *Direct3DViewport2)
1774 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1775 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
1777 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1779 return IDirect3DDevice3_SetCurrentViewport(&This->IDirect3DDevice3_iface,
1780 &vp->IDirect3DViewport3_iface);
1783 /*****************************************************************************
1784 * IDirect3DDevice3::GetCurrentViewport
1786 * Returns the currently active viewport.
1788 * Version 2 and 3
1790 * Params:
1791 * Direct3DViewport3: Address to return the interface pointer at
1793 * Returns:
1794 * D3D_OK on success
1795 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1797 *****************************************************************************/
1798 static HRESULT WINAPI
1799 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1800 IDirect3DViewport3 **Direct3DViewport3)
1802 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1804 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1806 if(!Direct3DViewport3)
1807 return DDERR_INVALIDPARAMS;
1809 wined3d_mutex_lock();
1810 *Direct3DViewport3 = &This->current_viewport->IDirect3DViewport3_iface;
1812 /* AddRef the returned viewport */
1813 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1815 TRACE(" returning interface %p\n", *Direct3DViewport3);
1817 wined3d_mutex_unlock();
1819 return D3D_OK;
1822 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1823 IDirect3DViewport2 **Direct3DViewport2)
1825 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1826 HRESULT hr;
1828 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1830 hr = IDirect3DDevice3_GetCurrentViewport(&This->IDirect3DDevice3_iface,
1831 (IDirect3DViewport3 **)Direct3DViewport2);
1832 if(hr != D3D_OK) return hr;
1833 return D3D_OK;
1836 /*****************************************************************************
1837 * IDirect3DDevice7::SetRenderTarget
1839 * Sets the render target for the Direct3DDevice.
1840 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1841 * IDirectDrawSurface3 == IDirectDrawSurface
1843 * Version 2, 3 and 7
1845 * Params:
1846 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1847 * render target
1848 * Flags: Some flags
1850 * Returns:
1851 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1853 *****************************************************************************/
1854 static HRESULT d3d_device_set_render_target(IDirect3DDeviceImpl *This, IDirectDrawSurfaceImpl *Target)
1856 HRESULT hr;
1858 wined3d_mutex_lock();
1860 if(This->target == Target)
1862 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1863 wined3d_mutex_unlock();
1864 return D3D_OK;
1866 This->target = Target;
1867 hr = wined3d_device_set_render_target(This->wined3d_device, 0,
1868 Target ? Target->wined3d_surface : NULL, FALSE);
1869 if(hr != D3D_OK)
1871 wined3d_mutex_unlock();
1872 return hr;
1874 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1876 wined3d_mutex_unlock();
1878 return D3D_OK;
1881 static HRESULT
1882 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1883 IDirectDrawSurface7 *NewTarget,
1884 DWORD Flags)
1886 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1887 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface7(NewTarget);
1889 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, Flags);
1890 /* Flags: Not used */
1892 IDirectDrawSurface7_AddRef(NewTarget);
1893 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
1894 return d3d_device_set_render_target(This, Target);
1897 static HRESULT WINAPI
1898 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1899 IDirectDrawSurface7 *NewTarget,
1900 DWORD Flags)
1902 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1905 static HRESULT WINAPI
1906 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1907 IDirectDrawSurface7 *NewTarget,
1908 DWORD Flags)
1910 HRESULT hr;
1911 WORD old_fpucw;
1913 old_fpucw = d3d_fpu_setup();
1914 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1915 set_fpu_control_word(old_fpucw);
1917 return hr;
1920 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
1921 IDirectDrawSurface4 *NewRenderTarget, DWORD Flags)
1923 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1924 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface4(NewRenderTarget);
1926 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1928 IDirectDrawSurface4_AddRef(NewRenderTarget);
1929 IDirectDrawSurface4_Release(&This->target->IDirectDrawSurface4_iface);
1930 return d3d_device_set_render_target(This, Target);
1933 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
1934 IDirectDrawSurface *NewRenderTarget, DWORD Flags)
1936 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1937 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface(NewRenderTarget);
1939 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1941 IDirectDrawSurface_AddRef(NewRenderTarget);
1942 IDirectDrawSurface_Release(&This->target->IDirectDrawSurface_iface);
1943 return d3d_device_set_render_target(This, Target);
1946 /*****************************************************************************
1947 * IDirect3DDevice7::GetRenderTarget
1949 * Returns the current render target.
1950 * This is handled locally, because the WineD3D render target's parent
1951 * is an IParent
1953 * Version 2, 3 and 7
1955 * Params:
1956 * RenderTarget: Address to store the surface interface pointer
1958 * Returns:
1959 * D3D_OK on success
1960 * DDERR_INVALIDPARAMS if RenderTarget == NULL
1962 *****************************************************************************/
1963 static HRESULT WINAPI
1964 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
1965 IDirectDrawSurface7 **RenderTarget)
1967 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1969 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1971 if(!RenderTarget)
1972 return DDERR_INVALIDPARAMS;
1974 wined3d_mutex_lock();
1975 *RenderTarget = &This->target->IDirectDrawSurface7_iface;
1976 IDirectDrawSurface7_AddRef(*RenderTarget);
1977 wined3d_mutex_unlock();
1979 return D3D_OK;
1982 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
1983 IDirectDrawSurface4 **RenderTarget)
1985 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1986 IDirectDrawSurface7 *RenderTarget7;
1987 IDirectDrawSurfaceImpl *RenderTargetImpl;
1988 HRESULT hr;
1990 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1992 if(!RenderTarget)
1993 return DDERR_INVALIDPARAMS;
1995 hr = IDirect3DDevice7_GetRenderTarget(&This->IDirect3DDevice7_iface, &RenderTarget7);
1996 if(hr != D3D_OK) return hr;
1997 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
1998 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface;
1999 IDirectDrawSurface4_AddRef(*RenderTarget);
2000 IDirectDrawSurface7_Release(RenderTarget7);
2001 return D3D_OK;
2004 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
2005 IDirectDrawSurface **RenderTarget)
2007 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2008 IDirectDrawSurface7 *RenderTarget7;
2009 IDirectDrawSurfaceImpl *RenderTargetImpl;
2010 HRESULT hr;
2012 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2014 if(!RenderTarget)
2015 return DDERR_INVALIDPARAMS;
2017 hr = IDirect3DDevice7_GetRenderTarget(&This->IDirect3DDevice7_iface, &RenderTarget7);
2018 if(hr != D3D_OK) return hr;
2019 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2020 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
2021 IDirectDrawSurface_AddRef(*RenderTarget);
2022 IDirectDrawSurface7_Release(RenderTarget7);
2023 return D3D_OK;
2026 /*****************************************************************************
2027 * IDirect3DDevice3::Begin
2029 * Begins a description block of vertices. This is similar to glBegin()
2030 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2031 * described with IDirect3DDevice::Vertex are drawn.
2033 * Version 2 and 3
2035 * Params:
2036 * PrimitiveType: The type of primitives to draw
2037 * VertexTypeDesc: A flexible vertex format description of the vertices
2038 * Flags: Some flags..
2040 * Returns:
2041 * D3D_OK on success
2043 *****************************************************************************/
2044 static HRESULT WINAPI
2045 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2046 D3DPRIMITIVETYPE PrimitiveType,
2047 DWORD VertexTypeDesc,
2048 DWORD Flags)
2050 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2052 TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
2053 iface, PrimitiveType, VertexTypeDesc, Flags);
2055 wined3d_mutex_lock();
2056 This->primitive_type = PrimitiveType;
2057 This->vertex_type = VertexTypeDesc;
2058 This->render_flags = Flags;
2059 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2060 This->nb_vertices = 0;
2061 wined3d_mutex_unlock();
2063 return D3D_OK;
2066 static HRESULT WINAPI IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface, D3DPRIMITIVETYPE d3dpt,
2067 D3DVERTEXTYPE dwVertexTypeDesc, DWORD dwFlags)
2069 DWORD FVF;
2070 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2072 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2073 iface, d3dpt, dwVertexTypeDesc, dwFlags);
2075 switch(dwVertexTypeDesc)
2077 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2078 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2079 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2080 default:
2081 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2082 return DDERR_INVALIDPARAMS; /* Should never happen */
2085 return IDirect3DDevice3_Begin(&This->IDirect3DDevice3_iface, d3dpt, FVF, dwFlags);
2088 /*****************************************************************************
2089 * IDirect3DDevice3::BeginIndexed
2091 * Draws primitives based on vertices in a vertex array which are specified
2092 * by indices.
2094 * Version 2 and 3
2096 * Params:
2097 * PrimitiveType: Primitive type to draw
2098 * VertexType: A FVF description of the vertex format
2099 * Vertices: pointer to an array containing the vertices
2100 * NumVertices: The number of vertices in the vertex array
2101 * Flags: Some flags ...
2103 * Returns:
2104 * D3D_OK, because it's a stub
2106 *****************************************************************************/
2107 static HRESULT WINAPI
2108 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2109 D3DPRIMITIVETYPE PrimitiveType,
2110 DWORD VertexType,
2111 void *Vertices,
2112 DWORD NumVertices,
2113 DWORD Flags)
2115 FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2116 iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2118 return D3D_OK;
2122 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2123 D3DPRIMITIVETYPE d3dptPrimitiveType, D3DVERTEXTYPE d3dvtVertexType,
2124 void *lpvVertices, DWORD dwNumVertices, DWORD dwFlags)
2126 DWORD FVF;
2127 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2129 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2130 iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2132 switch(d3dvtVertexType)
2134 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2135 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2136 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2137 default:
2138 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2139 return DDERR_INVALIDPARAMS; /* Should never happen */
2142 return IDirect3DDevice3_BeginIndexed(&This->IDirect3DDevice3_iface,
2143 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2146 /*****************************************************************************
2147 * IDirect3DDevice3::Vertex
2149 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2150 * drawn vertices in a vertex buffer. If the buffer is too small, its
2151 * size is increased.
2153 * Version 2 and 3
2155 * Params:
2156 * Vertex: Pointer to the vertex
2158 * Returns:
2159 * D3D_OK, on success
2160 * DDERR_INVALIDPARAMS if Vertex is NULL
2162 *****************************************************************************/
2163 static HRESULT WINAPI
2164 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2165 void *Vertex)
2167 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2169 TRACE("iface %p, vertex %p.\n", iface, Vertex);
2171 if(!Vertex)
2172 return DDERR_INVALIDPARAMS;
2174 wined3d_mutex_lock();
2175 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2177 BYTE *old_buffer;
2178 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2179 old_buffer = This->vertex_buffer;
2180 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2181 if (old_buffer)
2183 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2184 HeapFree(GetProcessHeap(), 0, old_buffer);
2188 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2189 wined3d_mutex_unlock();
2191 return D3D_OK;
2194 static HRESULT WINAPI IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface, void *lpVertexType)
2196 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2198 TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
2200 return IDirect3DDevice3_Vertex(&This->IDirect3DDevice3_iface, lpVertexType);
2203 /*****************************************************************************
2204 * IDirect3DDevice3::Index
2206 * Specifies an index to a vertex to be drawn. The vertex array has to
2207 * be specified with BeginIndexed first.
2209 * Parameters:
2210 * VertexIndex: The index of the vertex to draw
2212 * Returns:
2213 * D3D_OK because it's a stub
2215 *****************************************************************************/
2216 static HRESULT WINAPI
2217 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2218 WORD VertexIndex)
2220 FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
2222 return D3D_OK;
2225 static HRESULT WINAPI IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface, WORD wVertexIndex)
2227 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2229 TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
2231 return IDirect3DDevice3_Index(&This->IDirect3DDevice3_iface, wVertexIndex);
2234 /*****************************************************************************
2235 * IDirect3DDevice3::End
2237 * Ends a draw begun with IDirect3DDevice3::Begin or
2238 * IDirect3DDevice::BeginIndexed. The vertices specified with
2239 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2240 * the IDirect3DDevice7::DrawPrimitive method. So far only
2241 * non-indexed mode is supported
2243 * Version 2 and 3
2245 * Params:
2246 * Flags: Some flags, as usual. Don't know which are defined
2248 * Returns:
2249 * The return value of IDirect3DDevice7::DrawPrimitive
2251 *****************************************************************************/
2252 static HRESULT WINAPI
2253 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2254 DWORD Flags)
2256 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2258 TRACE("iface %p, flags %#x.\n", iface, Flags);
2260 return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface, This->primitive_type,
2261 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2264 static HRESULT WINAPI IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface, DWORD dwFlags)
2266 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2268 TRACE("iface %p, flags %#x.\n", iface, dwFlags);
2270 return IDirect3DDevice3_End(&This->IDirect3DDevice3_iface, dwFlags);
2273 /*****************************************************************************
2274 * IDirect3DDevice7::GetRenderState
2276 * Returns the value of a render state. The possible render states are
2277 * defined in include/d3dtypes.h
2279 * Version 2, 3 and 7
2281 * Params:
2282 * RenderStateType: Render state to return the current setting of
2283 * Value: Address to store the value at
2285 * Returns:
2286 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2287 * DDERR_INVALIDPARAMS if Value == NULL
2289 *****************************************************************************/
2290 static HRESULT IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2291 D3DRENDERSTATETYPE RenderStateType, DWORD *Value)
2293 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
2294 HRESULT hr;
2296 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2298 if(!Value)
2299 return DDERR_INVALIDPARAMS;
2301 wined3d_mutex_lock();
2302 switch(RenderStateType)
2304 case D3DRENDERSTATE_TEXTUREMAG:
2306 WINED3DTEXTUREFILTERTYPE tex_mag;
2308 hr = wined3d_device_get_sampler_state(This->wined3d_device, 0, WINED3DSAMP_MAGFILTER, &tex_mag);
2310 switch (tex_mag)
2312 case WINED3DTEXF_POINT:
2313 *Value = D3DFILTER_NEAREST;
2314 break;
2315 case WINED3DTEXF_LINEAR:
2316 *Value = D3DFILTER_LINEAR;
2317 break;
2318 default:
2319 ERR("Unhandled texture mag %d !\n",tex_mag);
2320 *Value = 0;
2322 break;
2325 case D3DRENDERSTATE_TEXTUREMIN:
2327 WINED3DTEXTUREFILTERTYPE tex_min;
2328 WINED3DTEXTUREFILTERTYPE tex_mip;
2330 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2331 0, WINED3DSAMP_MINFILTER, &tex_min);
2332 if (FAILED(hr))
2334 wined3d_mutex_unlock();
2335 return hr;
2337 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2338 0, WINED3DSAMP_MIPFILTER, &tex_mip);
2340 switch (tex_min)
2342 case WINED3DTEXF_POINT:
2343 switch (tex_mip)
2345 case WINED3DTEXF_NONE:
2346 *Value = D3DFILTER_NEAREST;
2347 break;
2348 case WINED3DTEXF_POINT:
2349 *Value = D3DFILTER_MIPNEAREST;
2350 break;
2351 case WINED3DTEXF_LINEAR:
2352 *Value = D3DFILTER_LINEARMIPNEAREST;
2353 break;
2354 default:
2355 ERR("Unhandled mip filter %#x.\n", tex_mip);
2356 *Value = D3DFILTER_NEAREST;
2357 break;
2359 break;
2360 case WINED3DTEXF_LINEAR:
2361 switch (tex_mip)
2363 case WINED3DTEXF_NONE:
2364 *Value = D3DFILTER_LINEAR;
2365 break;
2366 case WINED3DTEXF_POINT:
2367 *Value = D3DFILTER_MIPLINEAR;
2368 break;
2369 case WINED3DTEXF_LINEAR:
2370 *Value = D3DFILTER_LINEARMIPLINEAR;
2371 break;
2372 default:
2373 ERR("Unhandled mip filter %#x.\n", tex_mip);
2374 *Value = D3DFILTER_LINEAR;
2375 break;
2377 break;
2378 default:
2379 ERR("Unhandled texture min filter %#x.\n",tex_min);
2380 *Value = D3DFILTER_NEAREST;
2381 break;
2383 break;
2386 case D3DRENDERSTATE_TEXTUREADDRESS:
2387 case D3DRENDERSTATE_TEXTUREADDRESSU:
2388 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2389 0, WINED3DSAMP_ADDRESSU, Value);
2390 break;
2391 case D3DRENDERSTATE_TEXTUREADDRESSV:
2392 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2393 0, WINED3DSAMP_ADDRESSV, Value);
2394 break;
2396 case D3DRENDERSTATE_BORDERCOLOR:
2397 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2398 hr = E_NOTIMPL;
2399 break;
2401 case D3DRENDERSTATE_TEXTUREHANDLE:
2402 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2403 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2404 hr = DDERR_INVALIDPARAMS;
2405 break;
2407 case D3DRENDERSTATE_ZBIAS:
2408 hr = wined3d_device_get_render_state(This->wined3d_device, WINED3DRS_DEPTHBIAS, Value);
2409 break;
2411 default:
2412 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2413 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2415 FIXME("Unhandled stipple pattern render state (%#x).\n",
2416 RenderStateType);
2417 hr = E_NOTIMPL;
2418 break;
2420 hr = wined3d_device_get_render_state(This->wined3d_device, RenderStateType, Value);
2422 wined3d_mutex_unlock();
2424 return hr;
2427 static HRESULT WINAPI
2428 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2429 D3DRENDERSTATETYPE RenderStateType,
2430 DWORD *Value)
2432 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2435 static HRESULT WINAPI
2436 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2437 D3DRENDERSTATETYPE RenderStateType,
2438 DWORD *Value)
2440 HRESULT hr;
2441 WORD old_fpucw;
2443 old_fpucw = d3d_fpu_setup();
2444 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2445 set_fpu_control_word(old_fpucw);
2447 return hr;
2450 static HRESULT WINAPI
2451 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2452 D3DRENDERSTATETYPE dwRenderStateType,
2453 DWORD *lpdwRenderState)
2455 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2456 HRESULT hr;
2458 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2460 switch(dwRenderStateType)
2462 case D3DRENDERSTATE_TEXTUREHANDLE:
2464 /* This state is wrapped to SetTexture in SetRenderState, so
2465 * it has to be wrapped to GetTexture here. */
2466 struct wined3d_texture *tex = NULL;
2467 *lpdwRenderState = 0;
2469 wined3d_mutex_lock();
2470 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2471 if (SUCCEEDED(hr) && tex)
2473 /* The parent of the texture is the IDirectDrawSurface7
2474 * interface of the ddraw surface. */
2475 IDirectDrawSurfaceImpl *parent = wined3d_texture_get_parent(tex);
2476 if (parent) *lpdwRenderState = parent->Handle;
2477 wined3d_texture_decref(tex);
2479 wined3d_mutex_unlock();
2481 return hr;
2484 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2486 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2487 the mapping to get the value. */
2488 DWORD colorop, colorarg1, colorarg2;
2489 DWORD alphaop, alphaarg1, alphaarg2;
2491 wined3d_mutex_lock();
2493 This->legacyTextureBlending = TRUE;
2495 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLOROP, &colorop);
2496 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLORARG1, &colorarg1);
2497 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLORARG2, &colorarg2);
2498 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, &alphaop);
2499 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2500 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2502 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2503 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2505 *lpdwRenderState = D3DTBLEND_DECAL;
2507 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2508 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2510 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2512 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2513 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2515 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2517 else
2519 struct wined3d_texture *tex = NULL;
2520 HRESULT hr;
2521 BOOL tex_alpha = FALSE;
2522 DDPIXELFORMAT ddfmt;
2524 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2526 if(hr == WINED3D_OK && tex)
2528 struct wined3d_resource *sub_resource;
2530 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2532 struct wined3d_resource_desc desc;
2534 wined3d_resource_get_desc(sub_resource, &desc);
2535 ddfmt.dwSize = sizeof(ddfmt);
2536 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2537 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2540 wined3d_texture_decref(tex);
2543 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2544 alphaop == (tex_alpha ? WINED3DTOP_SELECTARG1 : WINED3DTOP_SELECTARG2) &&
2545 alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2547 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2550 *lpdwRenderState = D3DTBLEND_MODULATE;
2553 wined3d_mutex_unlock();
2555 return D3D_OK;
2558 default:
2559 return IDirect3DDevice7_GetRenderState(&This->IDirect3DDevice7_iface, dwRenderStateType, lpdwRenderState);
2563 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2564 D3DRENDERSTATETYPE dwRenderStateType, DWORD *lpdwRenderState)
2566 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2568 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2570 return IDirect3DDevice3_GetRenderState(&This->IDirect3DDevice3_iface,
2571 dwRenderStateType, lpdwRenderState);
2574 /*****************************************************************************
2575 * IDirect3DDevice7::SetRenderState
2577 * Sets a render state. The possible render states are defined in
2578 * include/d3dtypes.h
2580 * Version 2, 3 and 7
2582 * Params:
2583 * RenderStateType: State to set
2584 * Value: Value to assign to that state
2586 * Returns:
2587 * D3D_OK on success,
2588 * for details see IWineD3DDevice::SetRenderState
2590 *****************************************************************************/
2591 static HRESULT
2592 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2593 D3DRENDERSTATETYPE RenderStateType,
2594 DWORD Value)
2596 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
2597 HRESULT hr;
2599 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2601 wined3d_mutex_lock();
2602 /* Some render states need special care */
2603 switch(RenderStateType)
2606 * The ddraw texture filter mapping works like this:
2607 * D3DFILTER_NEAREST Point min/mag, no mip
2608 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2609 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2611 * D3DFILTER_LINEAR Linear min/mag, no mip
2612 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2613 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2615 * This is the opposite of the GL naming convention,
2616 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2618 case D3DRENDERSTATE_TEXTUREMAG:
2620 WINED3DTEXTUREFILTERTYPE tex_mag;
2622 switch (Value)
2624 case D3DFILTER_NEAREST:
2625 case D3DFILTER_MIPNEAREST:
2626 case D3DFILTER_LINEARMIPNEAREST:
2627 tex_mag = WINED3DTEXF_POINT;
2628 break;
2629 case D3DFILTER_LINEAR:
2630 case D3DFILTER_MIPLINEAR:
2631 case D3DFILTER_LINEARMIPLINEAR:
2632 tex_mag = WINED3DTEXF_LINEAR;
2633 break;
2634 default:
2635 tex_mag = WINED3DTEXF_POINT;
2636 ERR("Unhandled texture mag %d !\n",Value);
2637 break;
2640 hr = wined3d_device_set_sampler_state(This->wined3d_device, 0, WINED3DSAMP_MAGFILTER, tex_mag);
2641 break;
2644 case D3DRENDERSTATE_TEXTUREMIN:
2646 WINED3DTEXTUREFILTERTYPE tex_min;
2647 WINED3DTEXTUREFILTERTYPE tex_mip;
2649 switch ((D3DTEXTUREFILTER) Value)
2651 case D3DFILTER_NEAREST:
2652 tex_min = WINED3DTEXF_POINT;
2653 tex_mip = WINED3DTEXF_NONE;
2654 break;
2655 case D3DFILTER_LINEAR:
2656 tex_min = WINED3DTEXF_LINEAR;
2657 tex_mip = WINED3DTEXF_NONE;
2658 break;
2659 case D3DFILTER_MIPNEAREST:
2660 tex_min = WINED3DTEXF_POINT;
2661 tex_mip = WINED3DTEXF_POINT;
2662 break;
2663 case D3DFILTER_MIPLINEAR:
2664 tex_min = WINED3DTEXF_LINEAR;
2665 tex_mip = WINED3DTEXF_POINT;
2666 break;
2667 case D3DFILTER_LINEARMIPNEAREST:
2668 tex_min = WINED3DTEXF_POINT;
2669 tex_mip = WINED3DTEXF_LINEAR;
2670 break;
2671 case D3DFILTER_LINEARMIPLINEAR:
2672 tex_min = WINED3DTEXF_LINEAR;
2673 tex_mip = WINED3DTEXF_LINEAR;
2674 break;
2676 default:
2677 ERR("Unhandled texture min %d !\n",Value);
2678 tex_min = WINED3DTEXF_POINT;
2679 tex_mip = WINED3DTEXF_NONE;
2680 break;
2683 wined3d_device_set_sampler_state(This->wined3d_device,
2684 0, WINED3DSAMP_MIPFILTER, tex_mip);
2685 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2686 0, WINED3DSAMP_MINFILTER, tex_min);
2687 break;
2690 case D3DRENDERSTATE_TEXTUREADDRESS:
2691 wined3d_device_set_sampler_state(This->wined3d_device,
2692 0, WINED3DSAMP_ADDRESSV, Value);
2693 /* Drop through */
2694 case D3DRENDERSTATE_TEXTUREADDRESSU:
2695 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2696 0, WINED3DSAMP_ADDRESSU, Value);
2697 break;
2698 case D3DRENDERSTATE_TEXTUREADDRESSV:
2699 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2700 0, WINED3DSAMP_ADDRESSV, Value);
2701 break;
2703 case D3DRENDERSTATE_BORDERCOLOR:
2704 /* This should probably just forward to the corresponding sampler
2705 * state. Needs tests. */
2706 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2707 hr = E_NOTIMPL;
2708 break;
2710 case D3DRENDERSTATE_TEXTUREHANDLE:
2711 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2712 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2713 hr = DDERR_INVALIDPARAMS;
2714 break;
2716 case D3DRENDERSTATE_ZBIAS:
2717 hr = wined3d_device_set_render_state(This->wined3d_device, WINED3DRS_DEPTHBIAS, Value);
2718 break;
2720 default:
2721 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2722 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2724 FIXME("Unhandled stipple pattern render state (%#x).\n",
2725 RenderStateType);
2726 hr = E_NOTIMPL;
2727 break;
2730 hr = wined3d_device_set_render_state(This->wined3d_device, RenderStateType, Value);
2731 break;
2733 wined3d_mutex_unlock();
2735 return hr;
2738 static HRESULT WINAPI
2739 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2740 D3DRENDERSTATETYPE RenderStateType,
2741 DWORD Value)
2743 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2746 static HRESULT WINAPI
2747 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2748 D3DRENDERSTATETYPE RenderStateType,
2749 DWORD Value)
2751 HRESULT hr;
2752 WORD old_fpucw;
2754 old_fpucw = d3d_fpu_setup();
2755 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2756 set_fpu_control_word(old_fpucw);
2758 return hr;
2761 static HRESULT WINAPI
2762 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2763 D3DRENDERSTATETYPE RenderStateType,
2764 DWORD Value)
2766 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2767 for this state can be directly mapped to texture stage colorop and alphaop, but
2768 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2769 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2770 alphaarg when needed.
2772 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2774 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2775 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2776 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2777 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2778 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2779 in device - TRUE if the app is using TEXTUREMAPBLEND.
2781 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2782 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2783 unless some broken game will be found that cares. */
2785 HRESULT hr;
2786 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2788 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2790 wined3d_mutex_lock();
2792 switch(RenderStateType)
2794 case D3DRENDERSTATE_TEXTUREHANDLE:
2796 IDirectDrawSurfaceImpl *surf;
2798 if(Value == 0)
2800 hr = wined3d_device_set_texture(This->wined3d_device, 0, NULL);
2801 break;
2804 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2805 if (!surf)
2807 WARN("Invalid texture handle.\n");
2808 hr = DDERR_INVALIDPARAMS;
2809 break;
2812 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2813 break;
2816 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2818 This->legacyTextureBlending = TRUE;
2820 switch ( (D3DTEXTUREBLEND) Value)
2822 case D3DTBLEND_MODULATE:
2824 struct wined3d_texture *tex = NULL;
2825 BOOL tex_alpha = FALSE;
2826 DDPIXELFORMAT ddfmt;
2828 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2830 if(hr == WINED3D_OK && tex)
2832 struct wined3d_resource *sub_resource;
2834 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2836 struct wined3d_resource_desc desc;
2838 wined3d_resource_get_desc(sub_resource, &desc);
2839 ddfmt.dwSize = sizeof(ddfmt);
2840 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2841 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2844 wined3d_texture_decref(tex);
2847 if (tex_alpha)
2848 wined3d_device_set_texture_stage_state(This->wined3d_device,
2849 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2850 else
2851 wined3d_device_set_texture_stage_state(This->wined3d_device,
2852 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2853 wined3d_device_set_texture_stage_state(This->wined3d_device,
2854 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2855 wined3d_device_set_texture_stage_state(This->wined3d_device,
2856 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2857 wined3d_device_set_texture_stage_state(This->wined3d_device,
2858 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2859 wined3d_device_set_texture_stage_state(This->wined3d_device,
2860 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2861 wined3d_device_set_texture_stage_state(This->wined3d_device,
2862 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2863 break;
2866 case D3DTBLEND_ADD:
2867 wined3d_device_set_texture_stage_state(This->wined3d_device,
2868 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2869 wined3d_device_set_texture_stage_state(This->wined3d_device,
2870 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2871 wined3d_device_set_texture_stage_state(This->wined3d_device,
2872 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2873 wined3d_device_set_texture_stage_state(This->wined3d_device,
2874 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2875 wined3d_device_set_texture_stage_state(This->wined3d_device,
2876 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2877 break;
2879 case D3DTBLEND_MODULATEALPHA:
2880 wined3d_device_set_texture_stage_state(This->wined3d_device,
2881 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2882 wined3d_device_set_texture_stage_state(This->wined3d_device,
2883 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2884 wined3d_device_set_texture_stage_state(This->wined3d_device,
2885 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2886 wined3d_device_set_texture_stage_state(This->wined3d_device,
2887 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2888 wined3d_device_set_texture_stage_state(This->wined3d_device,
2889 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2890 wined3d_device_set_texture_stage_state(This->wined3d_device,
2891 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2892 break;
2894 case D3DTBLEND_COPY:
2895 case D3DTBLEND_DECAL:
2896 wined3d_device_set_texture_stage_state(This->wined3d_device,
2897 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2898 wined3d_device_set_texture_stage_state(This->wined3d_device,
2899 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2900 wined3d_device_set_texture_stage_state(This->wined3d_device,
2901 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2902 wined3d_device_set_texture_stage_state(This->wined3d_device,
2903 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2904 break;
2906 case D3DTBLEND_DECALALPHA:
2907 wined3d_device_set_texture_stage_state(This->wined3d_device,
2908 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2909 wined3d_device_set_texture_stage_state(This->wined3d_device,
2910 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2911 wined3d_device_set_texture_stage_state(This->wined3d_device,
2912 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2913 wined3d_device_set_texture_stage_state(This->wined3d_device,
2914 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2915 wined3d_device_set_texture_stage_state(This->wined3d_device,
2916 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2917 break;
2919 default:
2920 ERR("Unhandled texture environment %d !\n",Value);
2923 hr = D3D_OK;
2924 break;
2927 default:
2928 hr = IDirect3DDevice7_SetRenderState(&This->IDirect3DDevice7_iface, RenderStateType, Value);
2929 break;
2931 wined3d_mutex_unlock();
2933 return hr;
2936 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2937 D3DRENDERSTATETYPE RenderStateType, DWORD Value)
2939 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2941 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2943 return IDirect3DDevice3_SetRenderState(&This->IDirect3DDevice3_iface, RenderStateType, Value);
2946 /*****************************************************************************
2947 * Direct3DDevice3::SetLightState
2949 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2950 * light states are forwarded to Direct3DDevice7 render states
2952 * Version 2 and 3
2954 * Params:
2955 * LightStateType: The light state to change
2956 * Value: The value to assign to that light state
2958 * Returns:
2959 * D3D_OK on success
2960 * DDERR_INVALIDPARAMS if the parameters were incorrect
2961 * Also check IDirect3DDevice7::SetRenderState
2963 *****************************************************************************/
2964 static HRESULT WINAPI
2965 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
2966 D3DLIGHTSTATETYPE LightStateType,
2967 DWORD Value)
2969 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2970 HRESULT hr;
2972 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
2974 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2976 TRACE("Unexpected Light State Type\n");
2977 return DDERR_INVALIDPARAMS;
2980 wined3d_mutex_lock();
2981 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
2983 IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
2984 if (!m)
2986 WARN("Invalid material handle.\n");
2987 wined3d_mutex_unlock();
2988 return DDERR_INVALIDPARAMS;
2991 TRACE(" activating material %p.\n", m);
2992 material_activate(m);
2994 This->material = Value;
2996 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
2998 switch (Value)
3000 case D3DCOLOR_MONO:
3001 ERR("DDCOLOR_MONO should not happen!\n");
3002 break;
3003 case D3DCOLOR_RGB:
3004 /* We are already in this mode */
3005 TRACE("Setting color model to RGB (no-op).\n");
3006 break;
3007 default:
3008 ERR("Unknown color model!\n");
3009 wined3d_mutex_unlock();
3010 return DDERR_INVALIDPARAMS;
3013 else
3015 D3DRENDERSTATETYPE rs;
3016 switch (LightStateType)
3018 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3019 rs = D3DRENDERSTATE_AMBIENT;
3020 break;
3021 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3022 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3023 break;
3024 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3025 rs = D3DRENDERSTATE_FOGSTART;
3026 break;
3027 case D3DLIGHTSTATE_FOGEND: /* 6 */
3028 rs = D3DRENDERSTATE_FOGEND;
3029 break;
3030 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3031 rs = D3DRENDERSTATE_FOGDENSITY;
3032 break;
3033 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3034 rs = D3DRENDERSTATE_COLORVERTEX;
3035 break;
3036 default:
3037 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3038 wined3d_mutex_unlock();
3039 return DDERR_INVALIDPARAMS;
3042 hr = IDirect3DDevice7_SetRenderState(&This->IDirect3DDevice7_iface, rs, Value);
3043 wined3d_mutex_unlock();
3044 return hr;
3046 wined3d_mutex_unlock();
3048 return D3D_OK;
3051 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3052 D3DLIGHTSTATETYPE LightStateType, DWORD Value)
3054 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3056 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3058 return IDirect3DDevice3_SetLightState(&This->IDirect3DDevice3_iface, LightStateType, Value);
3061 /*****************************************************************************
3062 * IDirect3DDevice3::GetLightState
3064 * Returns the current setting of a light state. The state is read from
3065 * the Direct3DDevice7 render state.
3067 * Version 2 and 3
3069 * Params:
3070 * LightStateType: The light state to return
3071 * Value: The address to store the light state setting at
3073 * Returns:
3074 * D3D_OK on success
3075 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3076 * Also see IDirect3DDevice7::GetRenderState
3078 *****************************************************************************/
3079 static HRESULT WINAPI
3080 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3081 D3DLIGHTSTATETYPE LightStateType,
3082 DWORD *Value)
3084 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3085 HRESULT hr;
3087 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3089 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3091 TRACE("Unexpected Light State Type\n");
3092 return DDERR_INVALIDPARAMS;
3095 if(!Value)
3096 return DDERR_INVALIDPARAMS;
3098 wined3d_mutex_lock();
3099 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3101 *Value = This->material;
3103 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3105 *Value = D3DCOLOR_RGB;
3107 else
3109 D3DRENDERSTATETYPE rs;
3110 switch (LightStateType)
3112 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3113 rs = D3DRENDERSTATE_AMBIENT;
3114 break;
3115 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3116 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3117 break;
3118 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3119 rs = D3DRENDERSTATE_FOGSTART;
3120 break;
3121 case D3DLIGHTSTATE_FOGEND: /* 6 */
3122 rs = D3DRENDERSTATE_FOGEND;
3123 break;
3124 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3125 rs = D3DRENDERSTATE_FOGDENSITY;
3126 break;
3127 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3128 rs = D3DRENDERSTATE_COLORVERTEX;
3129 break;
3130 default:
3131 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3132 wined3d_mutex_unlock();
3133 return DDERR_INVALIDPARAMS;
3136 hr = IDirect3DDevice7_GetRenderState(&This->IDirect3DDevice7_iface, rs, Value);
3137 wined3d_mutex_unlock();
3138 return hr;
3140 wined3d_mutex_unlock();
3142 return D3D_OK;
3145 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3146 D3DLIGHTSTATETYPE LightStateType, DWORD *Value)
3148 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3150 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3152 return IDirect3DDevice3_GetLightState(&This->IDirect3DDevice3_iface, LightStateType, Value);
3155 /*****************************************************************************
3156 * IDirect3DDevice7::SetTransform
3158 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3159 * in include/d3dtypes.h.
3160 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3161 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3162 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3164 * Version 2, 3 and 7
3166 * Params:
3167 * TransformStateType: transform state to set
3168 * Matrix: Matrix to assign to the state
3170 * Returns:
3171 * D3D_OK on success
3172 * DDERR_INVALIDPARAMS if Matrix == NULL
3173 * For details see IWineD3DDevice::SetTransform
3175 *****************************************************************************/
3176 static HRESULT
3177 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3178 D3DTRANSFORMSTATETYPE TransformStateType,
3179 D3DMATRIX *Matrix)
3181 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3182 D3DTRANSFORMSTATETYPE type;
3183 HRESULT hr;
3185 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3187 switch(TransformStateType)
3189 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3190 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3191 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3192 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3193 default: type = TransformStateType;
3196 if (!Matrix)
3197 return DDERR_INVALIDPARAMS;
3199 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3200 wined3d_mutex_lock();
3201 hr = wined3d_device_set_transform(This->wined3d_device, type, (struct wined3d_matrix *)Matrix);
3202 wined3d_mutex_unlock();
3204 return hr;
3207 static HRESULT WINAPI
3208 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3209 D3DTRANSFORMSTATETYPE TransformStateType,
3210 D3DMATRIX *Matrix)
3212 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3215 static HRESULT WINAPI
3216 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3217 D3DTRANSFORMSTATETYPE TransformStateType,
3218 D3DMATRIX *Matrix)
3220 HRESULT hr;
3221 WORD old_fpucw;
3223 old_fpucw = d3d_fpu_setup();
3224 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3225 set_fpu_control_word(old_fpucw);
3227 return hr;
3230 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3231 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3233 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3235 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3237 return IDirect3DDevice7_SetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3240 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3241 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3243 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3245 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3247 return IDirect3DDevice7_SetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3250 /*****************************************************************************
3251 * IDirect3DDevice7::GetTransform
3253 * Returns the matrix assigned to a transform state
3254 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3255 * SetTransform
3257 * Params:
3258 * TransformStateType: State to read the matrix from
3259 * Matrix: Address to store the matrix at
3261 * Returns:
3262 * D3D_OK on success
3263 * DDERR_INVALIDPARAMS if Matrix == NULL
3264 * For details, see IWineD3DDevice::GetTransform
3266 *****************************************************************************/
3267 static HRESULT
3268 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3269 D3DTRANSFORMSTATETYPE TransformStateType,
3270 D3DMATRIX *Matrix)
3272 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3273 D3DTRANSFORMSTATETYPE type;
3274 HRESULT hr;
3276 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3278 switch(TransformStateType)
3280 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3281 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3282 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3283 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3284 default: type = TransformStateType;
3287 if(!Matrix)
3288 return DDERR_INVALIDPARAMS;
3290 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3291 wined3d_mutex_lock();
3292 hr = wined3d_device_get_transform(This->wined3d_device, type, (struct wined3d_matrix *)Matrix);
3293 wined3d_mutex_unlock();
3295 return hr;
3298 static HRESULT WINAPI
3299 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3300 D3DTRANSFORMSTATETYPE TransformStateType,
3301 D3DMATRIX *Matrix)
3303 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3306 static HRESULT WINAPI
3307 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3308 D3DTRANSFORMSTATETYPE TransformStateType,
3309 D3DMATRIX *Matrix)
3311 HRESULT hr;
3312 WORD old_fpucw;
3314 old_fpucw = d3d_fpu_setup();
3315 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3316 set_fpu_control_word(old_fpucw);
3318 return hr;
3321 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3322 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3324 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3326 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3328 return IDirect3DDevice7_GetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3331 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3332 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3334 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3336 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3338 return IDirect3DDevice7_GetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3341 /*****************************************************************************
3342 * IDirect3DDevice7::MultiplyTransform
3344 * Multiplies the already-set transform matrix of a transform state
3345 * with another matrix. For the world matrix, see SetTransform
3347 * Version 2, 3 and 7
3349 * Params:
3350 * TransformStateType: Transform state to multiply
3351 * D3DMatrix Matrix to multiply with.
3353 * Returns
3354 * D3D_OK on success
3355 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3356 * For details, see IWineD3DDevice::MultiplyTransform
3358 *****************************************************************************/
3359 static HRESULT
3360 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3361 D3DTRANSFORMSTATETYPE TransformStateType,
3362 D3DMATRIX *D3DMatrix)
3364 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3365 HRESULT hr;
3366 D3DTRANSFORMSTATETYPE type;
3368 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3370 switch(TransformStateType)
3372 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3373 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3374 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3375 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3376 default: type = TransformStateType;
3379 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3380 wined3d_mutex_lock();
3381 hr = wined3d_device_multiply_transform(This->wined3d_device,
3382 type, (struct wined3d_matrix *)D3DMatrix);
3383 wined3d_mutex_unlock();
3385 return hr;
3388 static HRESULT WINAPI
3389 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3390 D3DTRANSFORMSTATETYPE TransformStateType,
3391 D3DMATRIX *D3DMatrix)
3393 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3396 static HRESULT WINAPI
3397 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3398 D3DTRANSFORMSTATETYPE TransformStateType,
3399 D3DMATRIX *D3DMatrix)
3401 HRESULT hr;
3402 WORD old_fpucw;
3404 old_fpucw = d3d_fpu_setup();
3405 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3406 set_fpu_control_word(old_fpucw);
3408 return hr;
3411 static HRESULT WINAPI IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3412 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3414 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3416 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3418 return IDirect3DDevice7_MultiplyTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3421 static HRESULT WINAPI IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3422 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3424 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3426 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3428 return IDirect3DDevice7_MultiplyTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3431 /*****************************************************************************
3432 * IDirect3DDevice7::DrawPrimitive
3434 * Draws primitives based on vertices in an application-provided pointer
3436 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3437 * an FVF format for D3D7
3439 * Params:
3440 * PrimitiveType: The type of the primitives to draw
3441 * Vertex type: Flexible vertex format vertex description
3442 * Vertices: Pointer to the vertex array
3443 * VertexCount: The number of vertices to draw
3444 * Flags: As usual a few flags
3446 * Returns:
3447 * D3D_OK on success
3448 * DDERR_INVALIDPARAMS if Vertices is NULL
3449 * For details, see IWineD3DDevice::DrawPrimitiveUP
3451 *****************************************************************************/
3452 static HRESULT
3453 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3454 D3DPRIMITIVETYPE PrimitiveType,
3455 DWORD VertexType,
3456 void *Vertices,
3457 DWORD VertexCount,
3458 DWORD Flags)
3460 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3461 UINT stride;
3462 HRESULT hr;
3464 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3465 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3467 if(!Vertices)
3468 return DDERR_INVALIDPARAMS;
3470 /* Get the stride */
3471 stride = get_flexible_vertex_size(VertexType);
3473 /* Set the FVF */
3474 wined3d_mutex_lock();
3475 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3476 if(hr != D3D_OK)
3478 wined3d_mutex_unlock();
3479 return hr;
3482 /* This method translates to the user pointer draw of WineD3D */
3483 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3484 hr = wined3d_device_draw_primitive_up(This->wined3d_device, VertexCount, Vertices, stride);
3485 wined3d_mutex_unlock();
3487 return hr;
3490 static HRESULT WINAPI
3491 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3492 D3DPRIMITIVETYPE PrimitiveType,
3493 DWORD VertexType,
3494 void *Vertices,
3495 DWORD VertexCount,
3496 DWORD Flags)
3498 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3501 static HRESULT WINAPI
3502 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3503 D3DPRIMITIVETYPE PrimitiveType,
3504 DWORD VertexType,
3505 void *Vertices,
3506 DWORD VertexCount,
3507 DWORD Flags)
3509 HRESULT hr;
3510 WORD old_fpucw;
3512 old_fpucw = d3d_fpu_setup();
3513 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3514 set_fpu_control_word(old_fpucw);
3516 return hr;
3519 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3520 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3521 DWORD Flags)
3523 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3524 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3525 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3527 return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface,
3528 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3531 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3532 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3533 DWORD VertexCount, DWORD Flags)
3535 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3536 DWORD FVF;
3538 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3539 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3541 switch(VertexType)
3543 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3544 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3545 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3546 default:
3547 ERR("Unexpected vertex type %d\n", VertexType);
3548 return DDERR_INVALIDPARAMS; /* Should never happen */
3551 return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface,
3552 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3555 /*****************************************************************************
3556 * IDirect3DDevice7::DrawIndexedPrimitive
3558 * Draws vertices from an application-provided pointer, based on the index
3559 * numbers in a WORD array.
3561 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3562 * an FVF format for D3D7
3564 * Params:
3565 * PrimitiveType: The primitive type to draw
3566 * VertexType: The FVF vertex description
3567 * Vertices: Pointer to the vertex array
3568 * VertexCount: ?
3569 * Indices: Pointer to the index array
3570 * IndexCount: Number of indices = Number of vertices to draw
3571 * Flags: As usual, some flags
3573 * Returns:
3574 * D3D_OK on success
3575 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3576 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3578 *****************************************************************************/
3579 static HRESULT
3580 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3581 D3DPRIMITIVETYPE PrimitiveType,
3582 DWORD VertexType,
3583 void *Vertices,
3584 DWORD VertexCount,
3585 WORD *Indices,
3586 DWORD IndexCount,
3587 DWORD Flags)
3589 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3590 HRESULT hr;
3592 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3593 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3595 /* Set the D3DDevice's FVF */
3596 wined3d_mutex_lock();
3597 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3598 if(FAILED(hr))
3600 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3601 wined3d_mutex_unlock();
3602 return hr;
3605 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3606 hr = wined3d_device_draw_indexed_primitive_up(This->wined3d_device, IndexCount, Indices,
3607 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3608 wined3d_mutex_unlock();
3610 return hr;
3613 static HRESULT WINAPI
3614 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3615 D3DPRIMITIVETYPE PrimitiveType,
3616 DWORD VertexType,
3617 void *Vertices,
3618 DWORD VertexCount,
3619 WORD *Indices,
3620 DWORD IndexCount,
3621 DWORD Flags)
3623 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3626 static HRESULT WINAPI
3627 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3628 D3DPRIMITIVETYPE PrimitiveType,
3629 DWORD VertexType,
3630 void *Vertices,
3631 DWORD VertexCount,
3632 WORD *Indices,
3633 DWORD IndexCount,
3634 DWORD Flags)
3636 HRESULT hr;
3637 WORD old_fpucw;
3639 old_fpucw = d3d_fpu_setup();
3640 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3641 set_fpu_control_word(old_fpucw);
3643 return hr;
3646 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3647 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3648 WORD *Indices, DWORD IndexCount, DWORD Flags)
3650 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3651 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3652 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3654 return IDirect3DDevice7_DrawIndexedPrimitive(&This->IDirect3DDevice7_iface,
3655 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3658 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3659 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3660 DWORD VertexCount, WORD *Indices, DWORD IndexCount, DWORD Flags)
3662 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3663 DWORD FVF;
3665 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3666 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3668 switch(VertexType)
3670 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3671 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3672 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3673 default:
3674 ERR("Unexpected vertex type %d\n", VertexType);
3675 return DDERR_INVALIDPARAMS; /* Should never happen */
3678 return IDirect3DDevice7_DrawIndexedPrimitive(&This->IDirect3DDevice7_iface,
3679 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3682 /*****************************************************************************
3683 * IDirect3DDevice7::SetClipStatus
3685 * Sets the clip status. This defines things as clipping conditions and
3686 * the extents of the clipping region.
3688 * Version 2, 3 and 7
3690 * Params:
3691 * ClipStatus:
3693 * Returns:
3694 * D3D_OK because it's a stub
3695 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3697 *****************************************************************************/
3698 static HRESULT WINAPI
3699 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3700 D3DCLIPSTATUS *ClipStatus)
3702 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3704 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3705 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3707 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3708 return D3D_OK;
3711 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3712 D3DCLIPSTATUS *ClipStatus)
3714 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3715 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3717 return IDirect3DDevice7_SetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3720 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3721 D3DCLIPSTATUS *ClipStatus)
3723 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3724 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3726 return IDirect3DDevice7_SetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3729 /*****************************************************************************
3730 * IDirect3DDevice7::GetClipStatus
3732 * Returns the clip status
3734 * Params:
3735 * ClipStatus: Address to write the clip status to
3737 * Returns:
3738 * D3D_OK because it's a stub
3740 *****************************************************************************/
3741 static HRESULT WINAPI
3742 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3743 D3DCLIPSTATUS *ClipStatus)
3745 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3747 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3748 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3749 return D3D_OK;
3752 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3753 D3DCLIPSTATUS *ClipStatus)
3755 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3756 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3758 return IDirect3DDevice7_GetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3761 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3762 D3DCLIPSTATUS *ClipStatus)
3764 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3765 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3767 return IDirect3DDevice7_GetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3770 /*****************************************************************************
3771 * IDirect3DDevice::DrawPrimitiveStrided
3773 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3775 * Version 3 and 7
3777 * Params:
3778 * PrimitiveType: The primitive type to draw
3779 * VertexType: The FVF description of the vertices to draw (for the stride??)
3780 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3781 * the vertex data locations
3782 * VertexCount: The number of vertices to draw
3783 * Flags: Some flags
3785 * Returns:
3786 * D3D_OK, because it's a stub
3787 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3788 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3790 *****************************************************************************/
3791 static HRESULT
3792 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3793 D3DPRIMITIVETYPE PrimitiveType,
3794 DWORD VertexType,
3795 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3796 DWORD VertexCount,
3797 DWORD Flags)
3799 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3800 WineDirect3DVertexStridedData WineD3DStrided;
3801 DWORD i;
3802 HRESULT hr;
3804 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3805 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3807 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3808 /* Get the strided data right. the wined3d structure is a bit bigger
3809 * Watch out: The contents of the strided data are determined by the fvf,
3810 * not by the members set in D3DDrawPrimStrideData. So it's valid
3811 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3812 * not set in the fvf.
3814 if(VertexType & D3DFVF_POSITION_MASK)
3816 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3817 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3818 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3819 if (VertexType & D3DFVF_XYZRHW)
3821 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3822 WineD3DStrided.position_transformed = TRUE;
3823 } else
3824 WineD3DStrided.position_transformed = FALSE;
3827 if(VertexType & D3DFVF_NORMAL)
3829 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3830 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3831 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3834 if(VertexType & D3DFVF_DIFFUSE)
3836 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3837 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3838 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3841 if(VertexType & D3DFVF_SPECULAR)
3843 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3844 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3845 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3848 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3850 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3852 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3853 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3854 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3855 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3856 default: ERR("Unexpected texture coordinate size %d\n",
3857 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3859 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3860 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3863 /* WineD3D doesn't need the FVF here */
3864 wined3d_mutex_lock();
3865 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3866 hr = wined3d_device_draw_primitive_strided(This->wined3d_device, VertexCount, &WineD3DStrided);
3867 wined3d_mutex_unlock();
3869 return hr;
3872 static HRESULT WINAPI
3873 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3874 D3DPRIMITIVETYPE PrimitiveType,
3875 DWORD VertexType,
3876 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3877 DWORD VertexCount,
3878 DWORD Flags)
3880 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3883 static HRESULT WINAPI
3884 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3885 D3DPRIMITIVETYPE PrimitiveType,
3886 DWORD VertexType,
3887 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3888 DWORD VertexCount,
3889 DWORD Flags)
3891 HRESULT hr;
3892 WORD old_fpucw;
3894 old_fpucw = d3d_fpu_setup();
3895 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3896 set_fpu_control_word(old_fpucw);
3898 return hr;
3901 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3902 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3903 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3905 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3907 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3908 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3910 return IDirect3DDevice7_DrawPrimitiveStrided(&This->IDirect3DDevice7_iface,
3911 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3914 /*****************************************************************************
3915 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3917 * Draws primitives specified by strided data locations based on indices
3919 * Version 3 and 7
3921 * Params:
3922 * PrimitiveType:
3924 * Returns:
3925 * D3D_OK, because it's a stub
3926 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3927 * (DDERR_INVALIDPARAMS if Indices is NULL)
3928 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3930 *****************************************************************************/
3931 static HRESULT
3932 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3933 D3DPRIMITIVETYPE PrimitiveType,
3934 DWORD VertexType,
3935 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3936 DWORD VertexCount,
3937 WORD *Indices,
3938 DWORD IndexCount,
3939 DWORD Flags)
3941 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3942 WineDirect3DVertexStridedData WineD3DStrided;
3943 DWORD i;
3944 HRESULT hr;
3946 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3947 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3949 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3950 /* Get the strided data right. the wined3d structure is a bit bigger
3951 * Watch out: The contents of the strided data are determined by the fvf,
3952 * not by the members set in D3DDrawPrimStrideData. So it's valid
3953 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3954 * not set in the fvf.
3956 if(VertexType & D3DFVF_POSITION_MASK)
3958 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3959 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3960 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3961 if (VertexType & D3DFVF_XYZRHW)
3963 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3964 WineD3DStrided.position_transformed = TRUE;
3965 } else
3966 WineD3DStrided.position_transformed = FALSE;
3969 if(VertexType & D3DFVF_NORMAL)
3971 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3972 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3973 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3976 if(VertexType & D3DFVF_DIFFUSE)
3978 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3979 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3980 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3983 if(VertexType & D3DFVF_SPECULAR)
3985 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3986 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3987 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3990 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3992 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3994 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3995 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3996 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3997 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3998 default: ERR("Unexpected texture coordinate size %d\n",
3999 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4001 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4002 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4005 /* WineD3D doesn't need the FVF here */
4006 wined3d_mutex_lock();
4007 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4008 hr = wined3d_device_draw_indexed_primitive_strided(This->wined3d_device,
4009 IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
4010 wined3d_mutex_unlock();
4012 return hr;
4015 static HRESULT WINAPI
4016 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4017 D3DPRIMITIVETYPE PrimitiveType,
4018 DWORD VertexType,
4019 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4020 DWORD VertexCount,
4021 WORD *Indices,
4022 DWORD IndexCount,
4023 DWORD Flags)
4025 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4028 static HRESULT WINAPI
4029 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4030 D3DPRIMITIVETYPE PrimitiveType,
4031 DWORD VertexType,
4032 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4033 DWORD VertexCount,
4034 WORD *Indices,
4035 DWORD IndexCount,
4036 DWORD Flags)
4038 HRESULT hr;
4039 WORD old_fpucw;
4041 old_fpucw = d3d_fpu_setup();
4042 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4043 set_fpu_control_word(old_fpucw);
4045 return hr;
4048 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4049 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4050 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4051 DWORD IndexCount, DWORD Flags)
4053 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4055 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4056 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4058 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&This->IDirect3DDevice7_iface,
4059 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4062 /*****************************************************************************
4063 * IDirect3DDevice7::DrawPrimitiveVB
4065 * Draws primitives from a vertex buffer to the screen.
4067 * Version 3 and 7
4069 * Params:
4070 * PrimitiveType: Type of primitive to be rendered.
4071 * D3DVertexBuf: Source Vertex Buffer
4072 * StartVertex: Index of the first vertex from the buffer to be rendered
4073 * NumVertices: Number of vertices to be rendered
4074 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4076 * Return values
4077 * D3D_OK on success
4078 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4080 *****************************************************************************/
4081 static HRESULT
4082 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4083 D3DPRIMITIVETYPE PrimitiveType,
4084 IDirect3DVertexBuffer7 *D3DVertexBuf,
4085 DWORD StartVertex,
4086 DWORD NumVertices,
4087 DWORD Flags)
4089 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4090 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4091 HRESULT hr;
4092 DWORD stride;
4094 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4095 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4097 /* Sanity checks */
4098 if(!vb)
4100 ERR("(%p) No Vertex buffer specified\n", This);
4101 return DDERR_INVALIDPARAMS;
4103 stride = get_flexible_vertex_size(vb->fvf);
4105 wined3d_mutex_lock();
4106 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4107 if (FAILED(hr))
4109 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4110 wined3d_mutex_unlock();
4111 return hr;
4114 /* Set the vertex stream source */
4115 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4116 if(hr != D3D_OK)
4118 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4119 wined3d_mutex_unlock();
4120 return hr;
4123 /* Now draw the primitives */
4124 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4125 hr = wined3d_device_draw_primitive(This->wined3d_device, StartVertex, NumVertices);
4126 wined3d_mutex_unlock();
4128 return hr;
4131 static HRESULT WINAPI
4132 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4133 D3DPRIMITIVETYPE PrimitiveType,
4134 IDirect3DVertexBuffer7 *D3DVertexBuf,
4135 DWORD StartVertex,
4136 DWORD NumVertices,
4137 DWORD Flags)
4139 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4142 static HRESULT WINAPI
4143 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4144 D3DPRIMITIVETYPE PrimitiveType,
4145 IDirect3DVertexBuffer7 *D3DVertexBuf,
4146 DWORD StartVertex,
4147 DWORD NumVertices,
4148 DWORD Flags)
4150 HRESULT hr;
4151 WORD old_fpucw;
4153 old_fpucw = d3d_fpu_setup();
4154 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4155 set_fpu_control_word(old_fpucw);
4157 return hr;
4160 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4161 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex,
4162 DWORD NumVertices, DWORD Flags)
4164 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4165 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4167 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4168 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4170 return IDirect3DDevice7_DrawPrimitiveVB(&This->IDirect3DDevice7_iface,
4171 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4175 /*****************************************************************************
4176 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4178 * Draws primitives from a vertex buffer to the screen
4180 * Params:
4181 * PrimitiveType: Type of primitive to be rendered.
4182 * D3DVertexBuf: Source Vertex Buffer
4183 * StartVertex: Index of the first vertex from the buffer to be rendered
4184 * NumVertices: Number of vertices to be rendered
4185 * Indices: Array of DWORDs used to index into the Vertices
4186 * IndexCount: Number of indices in Indices
4187 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4189 * Return values
4191 *****************************************************************************/
4192 static HRESULT
4193 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4194 D3DPRIMITIVETYPE PrimitiveType,
4195 IDirect3DVertexBuffer7 *D3DVertexBuf,
4196 DWORD StartVertex,
4197 DWORD NumVertices,
4198 WORD *Indices,
4199 DWORD IndexCount,
4200 DWORD Flags)
4202 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4203 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4204 DWORD stride = get_flexible_vertex_size(vb->fvf);
4205 struct wined3d_resource *wined3d_resource;
4206 struct wined3d_resource_desc desc;
4207 WORD *LockedIndices;
4208 HRESULT hr;
4210 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4211 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4213 /* Steps:
4214 * 1) Upload the Indices to the index buffer
4215 * 2) Set the index source
4216 * 3) Set the Vertex Buffer as the Stream source
4217 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4220 wined3d_mutex_lock();
4222 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4223 if (FAILED(hr))
4225 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4226 wined3d_mutex_unlock();
4227 return hr;
4230 /* check that the buffer is large enough to hold the indices,
4231 * reallocate if necessary. */
4232 wined3d_resource = wined3d_buffer_get_resource(This->indexbuffer);
4233 wined3d_resource_get_desc(wined3d_resource, &desc);
4234 if (desc.size < IndexCount * sizeof(WORD))
4236 UINT size = max(desc.size * 2, IndexCount * sizeof(WORD));
4237 struct wined3d_buffer *buffer;
4239 TRACE("Growing index buffer to %u bytes\n", size);
4241 hr = wined3d_buffer_create_ib(This->wined3d_device, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4242 WINED3DPOOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
4243 if (FAILED(hr))
4245 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4246 wined3d_mutex_unlock();
4247 return hr;
4250 wined3d_buffer_decref(This->indexbuffer);
4251 This->indexbuffer = buffer;
4254 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4255 * method could be created which takes an user pointer containing the
4256 * indices or a SetData-Method for the index buffer, which overrides the
4257 * index buffer data with our pointer. */
4258 hr = wined3d_buffer_map(This->indexbuffer, 0, IndexCount * sizeof(WORD),
4259 (BYTE **)&LockedIndices, 0);
4260 if (FAILED(hr))
4262 ERR("Failed to map buffer, hr %#x.\n", hr);
4263 wined3d_mutex_unlock();
4264 return hr;
4266 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4267 wined3d_buffer_unmap(This->indexbuffer);
4269 /* Set the index stream */
4270 wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4271 hr = wined3d_device_set_index_buffer(This->wined3d_device, This->indexbuffer, WINED3DFMT_R16_UINT);
4273 /* Set the vertex stream source */
4274 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4275 if (FAILED(hr))
4277 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4278 wined3d_mutex_unlock();
4279 return hr;
4283 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4284 hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, 0, IndexCount);
4286 wined3d_mutex_unlock();
4288 return hr;
4291 static HRESULT WINAPI
4292 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4293 D3DPRIMITIVETYPE PrimitiveType,
4294 IDirect3DVertexBuffer7 *D3DVertexBuf,
4295 DWORD StartVertex,
4296 DWORD NumVertices,
4297 WORD *Indices,
4298 DWORD IndexCount,
4299 DWORD Flags)
4301 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4304 static HRESULT WINAPI
4305 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4306 D3DPRIMITIVETYPE PrimitiveType,
4307 IDirect3DVertexBuffer7 *D3DVertexBuf,
4308 DWORD StartVertex,
4309 DWORD NumVertices,
4310 WORD *Indices,
4311 DWORD IndexCount,
4312 DWORD Flags)
4314 HRESULT hr;
4315 WORD old_fpucw;
4317 old_fpucw = d3d_fpu_setup();
4318 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4319 set_fpu_control_word(old_fpucw);
4321 return hr;
4324 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4325 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4326 DWORD IndexCount, DWORD Flags)
4328 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4329 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4331 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4332 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4334 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&This->IDirect3DDevice7_iface,
4335 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount,
4336 Flags);
4339 /*****************************************************************************
4340 * IDirect3DDevice7::ComputeSphereVisibility
4342 * Calculates the visibility of spheres in the current viewport. The spheres
4343 * are passed in the Centers and Radii arrays, the results are passed back
4344 * in the ReturnValues array. Return values are either completely visible,
4345 * partially visible or completely invisible.
4346 * The return value consist of a combination of D3DCLIP_* flags, or it's
4347 * 0 if the sphere is completely visible(according to the SDK, not checked)
4349 * Version 3 and 7
4351 * Params:
4352 * Centers: Array containing the sphere centers
4353 * Radii: Array containing the sphere radii
4354 * NumSpheres: The number of centers and radii in the arrays
4355 * Flags: Some flags
4356 * ReturnValues: Array to write the results to
4358 * Returns:
4359 * D3D_OK
4360 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4361 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4362 * is singular)
4364 *****************************************************************************/
4366 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4368 float distance, norm;
4370 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4371 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4373 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4374 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4375 return 0;
4378 static HRESULT WINAPI
4379 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4380 D3DVECTOR *Centers,
4381 D3DVALUE *Radii,
4382 DWORD NumSpheres,
4383 DWORD Flags,
4384 DWORD *ReturnValues)
4386 D3DMATRIX m, temp;
4387 D3DVALUE origin_plane[6];
4388 D3DVECTOR vec[6];
4389 HRESULT hr;
4390 UINT i, j;
4392 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4393 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4395 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4396 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4397 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4398 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4399 multiply_matrix(&m, &temp, &m);
4401 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4402 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4403 multiply_matrix(&m, &temp, &m);
4405 /* Left plane */
4406 vec[0].u1.x = m._14 + m._11;
4407 vec[0].u2.y = m._24 + m._21;
4408 vec[0].u3.z = m._34 + m._31;
4409 origin_plane[0] = m._44 + m._41;
4411 /* Right plane */
4412 vec[1].u1.x = m._14 - m._11;
4413 vec[1].u2.y = m._24 - m._21;
4414 vec[1].u3.z = m._34 - m._31;
4415 origin_plane[1] = m._44 - m._41;
4417 /* Top plane */
4418 vec[2].u1.x = m._14 - m._12;
4419 vec[2].u2.y = m._24 - m._22;
4420 vec[2].u3.z = m._34 - m._32;
4421 origin_plane[2] = m._44 - m._42;
4423 /* Bottom plane */
4424 vec[3].u1.x = m._14 + m._12;
4425 vec[3].u2.y = m._24 + m._22;
4426 vec[3].u3.z = m._34 + m._32;
4427 origin_plane[3] = m._44 + m._42;
4429 /* Front plane */
4430 vec[4].u1.x = m._13;
4431 vec[4].u2.y = m._23;
4432 vec[4].u3.z = m._33;
4433 origin_plane[4] = m._43;
4435 /* Back plane*/
4436 vec[5].u1.x = m._14 - m._13;
4437 vec[5].u2.y = m._24 - m._23;
4438 vec[5].u3.z = m._34 - m._33;
4439 origin_plane[5] = m._44 - m._43;
4441 for(i=0; i<NumSpheres; i++)
4443 ReturnValues[i] = 0;
4444 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4447 return D3D_OK;
4450 static HRESULT WINAPI IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4451 D3DVECTOR *Centers, D3DVALUE *Radii, DWORD NumSpheres, DWORD Flags, DWORD *ReturnValues)
4453 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4455 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4456 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4458 return IDirect3DDevice7_ComputeSphereVisibility(&This->IDirect3DDevice7_iface,
4459 Centers, Radii, NumSpheres, Flags, ReturnValues);
4462 /*****************************************************************************
4463 * IDirect3DDevice7::GetTexture
4465 * Returns the texture interface handle assigned to a texture stage.
4466 * The returned texture is AddRefed. This is taken from old ddraw,
4467 * not checked in Windows.
4469 * Version 3 and 7
4471 * Params:
4472 * Stage: Texture stage to read the texture from
4473 * Texture: Address to store the interface pointer at
4475 * Returns:
4476 * D3D_OK on success
4477 * DDERR_INVALIDPARAMS if Texture is NULL
4478 * For details, see IWineD3DDevice::GetTexture
4480 *****************************************************************************/
4481 static HRESULT
4482 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4483 DWORD Stage,
4484 IDirectDrawSurface7 **Texture)
4486 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4487 struct wined3d_texture *wined3d_texture;
4488 HRESULT hr;
4490 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4492 if(!Texture)
4494 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4495 return DDERR_INVALIDPARAMS;
4498 wined3d_mutex_lock();
4499 hr = wined3d_device_get_texture(This->wined3d_device, Stage, &wined3d_texture);
4500 if (FAILED(hr) || !wined3d_texture)
4502 *Texture = NULL;
4503 wined3d_mutex_unlock();
4504 return hr;
4507 *Texture = wined3d_texture_get_parent(wined3d_texture);
4508 IDirectDrawSurface7_AddRef(*Texture);
4509 wined3d_texture_decref(wined3d_texture);
4510 wined3d_mutex_unlock();
4512 return hr;
4515 static HRESULT WINAPI
4516 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4517 DWORD Stage,
4518 IDirectDrawSurface7 **Texture)
4520 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4523 static HRESULT WINAPI
4524 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4525 DWORD Stage,
4526 IDirectDrawSurface7 **Texture)
4528 HRESULT hr;
4529 WORD old_fpucw;
4531 old_fpucw = d3d_fpu_setup();
4532 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4533 set_fpu_control_word(old_fpucw);
4535 return hr;
4538 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface, DWORD Stage,
4539 IDirect3DTexture2 **Texture2)
4541 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4542 HRESULT ret;
4543 IDirectDrawSurface7 *ret_val;
4544 IDirectDrawSurfaceImpl *ret_val_impl;
4546 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4548 ret = IDirect3DDevice7_GetTexture(&This->IDirect3DDevice7_iface, Stage, &ret_val);
4550 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4551 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4553 TRACE("Returning texture %p.\n", *Texture2);
4555 return ret;
4558 /*****************************************************************************
4559 * IDirect3DDevice7::SetTexture
4561 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4563 * Version 3 and 7
4565 * Params:
4566 * Stage: The stage to assign the texture to
4567 * Texture: Interface pointer to the texture surface
4569 * Returns
4570 * D3D_OK on success
4571 * For details, see IWineD3DDevice::SetTexture
4573 *****************************************************************************/
4574 static HRESULT
4575 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4576 DWORD Stage,
4577 IDirectDrawSurface7 *Texture)
4579 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4580 IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
4581 HRESULT hr;
4583 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4585 /* Texture may be NULL here */
4586 wined3d_mutex_lock();
4587 hr = wined3d_device_set_texture(This->wined3d_device,
4588 Stage, surf ? surf->wined3d_texture : NULL);
4589 wined3d_mutex_unlock();
4591 return hr;
4594 static HRESULT WINAPI
4595 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4596 DWORD Stage,
4597 IDirectDrawSurface7 *Texture)
4599 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4602 static HRESULT WINAPI
4603 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4604 DWORD Stage,
4605 IDirectDrawSurface7 *Texture)
4607 HRESULT hr;
4608 WORD old_fpucw;
4610 old_fpucw = d3d_fpu_setup();
4611 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4612 set_fpu_control_word(old_fpucw);
4614 return hr;
4617 static HRESULT WINAPI
4618 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4619 DWORD Stage,
4620 IDirect3DTexture2 *Texture2)
4622 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4623 IDirectDrawSurfaceImpl *tex = unsafe_impl_from_IDirect3DTexture2(Texture2);
4624 DWORD texmapblend;
4625 HRESULT hr;
4627 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4629 wined3d_mutex_lock();
4631 if (This->legacyTextureBlending)
4632 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4634 hr = IDirect3DDevice7_SetTexture(&This->IDirect3DDevice7_iface, Stage, &tex->IDirectDrawSurface7_iface);
4636 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4638 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4639 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4640 struct wined3d_texture *tex = NULL;
4641 BOOL tex_alpha = FALSE;
4642 DDPIXELFORMAT ddfmt;
4643 HRESULT result;
4645 result = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
4646 if (result == WINED3D_OK && tex)
4648 struct wined3d_resource *sub_resource;
4650 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4652 struct wined3d_resource_desc desc;
4654 wined3d_resource_get_desc(sub_resource, &desc);
4655 ddfmt.dwSize = sizeof(ddfmt);
4656 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4657 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4660 wined3d_texture_decref(tex);
4663 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4664 if (tex_alpha)
4665 wined3d_device_set_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4666 else
4667 wined3d_device_set_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4670 wined3d_mutex_unlock();
4672 return hr;
4675 static const struct tss_lookup
4677 BOOL sampler_state;
4678 DWORD state;
4680 tss_lookup[] =
4682 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
4683 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
4684 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
4685 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
4686 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
4687 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
4688 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
4689 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4690 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4691 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4692 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4693 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4694 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
4695 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
4696 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
4697 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
4698 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
4699 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
4700 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
4701 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4702 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4703 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4704 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4705 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4706 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4709 /*****************************************************************************
4710 * IDirect3DDevice7::GetTextureStageState
4712 * Retrieves a state from a texture stage.
4714 * Version 3 and 7
4716 * Params:
4717 * Stage: The stage to retrieve the state from
4718 * TexStageStateType: The state type to retrieve
4719 * State: Address to store the state's value at
4721 * Returns:
4722 * D3D_OK on success
4723 * DDERR_INVALIDPARAMS if State is NULL
4724 * For details, see IWineD3DDevice::GetTextureStageState
4726 *****************************************************************************/
4727 static HRESULT
4728 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4729 DWORD Stage,
4730 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4731 DWORD *State)
4733 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4734 HRESULT hr;
4735 const struct tss_lookup *l;
4737 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4738 iface, Stage, TexStageStateType, State);
4740 if(!State)
4741 return DDERR_INVALIDPARAMS;
4743 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4745 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4746 return DD_OK;
4749 l = &tss_lookup[TexStageStateType];
4751 wined3d_mutex_lock();
4753 if (l->sampler_state)
4755 hr = wined3d_device_get_sampler_state(This->wined3d_device, Stage, l->state, State);
4757 switch(TexStageStateType)
4759 /* Mipfilter is a sampler state with different values */
4760 case D3DTSS_MIPFILTER:
4762 switch(*State)
4764 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4765 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4766 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4767 default:
4768 ERR("Unexpected mipfilter value %#x\n", *State);
4769 *State = D3DTFP_NONE;
4770 break;
4772 break;
4775 /* Magfilter has slightly different values */
4776 case D3DTSS_MAGFILTER:
4778 switch(*State)
4780 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4781 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4782 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4783 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4784 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4785 default:
4786 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4787 *State = D3DTFG_POINT;
4788 break;
4790 break;
4793 default:
4794 break;
4797 else
4799 hr = wined3d_device_get_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4802 wined3d_mutex_unlock();
4804 return hr;
4807 static HRESULT WINAPI
4808 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4809 DWORD Stage,
4810 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4811 DWORD *State)
4813 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4816 static HRESULT WINAPI
4817 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4818 DWORD Stage,
4819 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4820 DWORD *State)
4822 HRESULT hr;
4823 WORD old_fpucw;
4825 old_fpucw = d3d_fpu_setup();
4826 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4827 set_fpu_control_word(old_fpucw);
4829 return hr;
4832 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4833 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD *State)
4835 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4837 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4838 iface, Stage, TexStageStateType, State);
4840 return IDirect3DDevice7_GetTextureStageState(&This->IDirect3DDevice7_iface,
4841 Stage, TexStageStateType, State);
4844 /*****************************************************************************
4845 * IDirect3DDevice7::SetTextureStageState
4847 * Sets a texture stage state. Some stage types need to be handled specially,
4848 * because they do not exist in WineD3D and were moved to another place
4850 * Version 3 and 7
4852 * Params:
4853 * Stage: The stage to modify
4854 * TexStageStateType: The state to change
4855 * State: The new value for the state
4857 * Returns:
4858 * D3D_OK on success
4859 * For details, see IWineD3DDevice::SetTextureStageState
4861 *****************************************************************************/
4862 static HRESULT
4863 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4864 DWORD Stage,
4865 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4866 DWORD State)
4868 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4869 const struct tss_lookup *l;
4870 HRESULT hr;
4872 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4873 iface, Stage, TexStageStateType, State);
4875 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4877 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4878 return DD_OK;
4881 l = &tss_lookup[TexStageStateType];
4883 wined3d_mutex_lock();
4885 if (l->sampler_state)
4887 switch(TexStageStateType)
4889 /* Mipfilter is a sampler state with different values */
4890 case D3DTSS_MIPFILTER:
4892 switch(State)
4894 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
4895 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
4896 case 0: /* Unchecked */
4897 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
4898 default:
4899 ERR("Unexpected mipfilter value %d\n", State);
4900 State = WINED3DTEXF_NONE;
4901 break;
4903 break;
4906 /* Magfilter has slightly different values */
4907 case D3DTSS_MAGFILTER:
4909 switch(State)
4911 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
4912 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
4913 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
4914 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
4915 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
4916 default:
4917 ERR("Unexpected d3d7 mag filter type %d\n", State);
4918 State = WINED3DTEXF_POINT;
4919 break;
4921 break;
4924 case D3DTSS_ADDRESS:
4925 wined3d_device_set_sampler_state(This->wined3d_device, Stage, WINED3DSAMP_ADDRESSV, State);
4926 break;
4928 default:
4929 break;
4932 hr = wined3d_device_set_sampler_state(This->wined3d_device, Stage, l->state, State);
4934 else
4936 hr = wined3d_device_set_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4939 wined3d_mutex_unlock();
4941 return hr;
4944 static HRESULT WINAPI
4945 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4946 DWORD Stage,
4947 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4948 DWORD State)
4950 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4953 static HRESULT WINAPI
4954 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4955 DWORD Stage,
4956 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4957 DWORD State)
4959 HRESULT hr;
4960 WORD old_fpucw;
4962 old_fpucw = d3d_fpu_setup();
4963 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4964 set_fpu_control_word(old_fpucw);
4966 return hr;
4969 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
4970 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD State)
4972 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4974 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4975 iface, Stage, TexStageStateType, State);
4977 return IDirect3DDevice7_SetTextureStageState(&This->IDirect3DDevice7_iface,
4978 Stage, TexStageStateType, State);
4981 /*****************************************************************************
4982 * IDirect3DDevice7::ValidateDevice
4984 * SDK: "Reports the device's ability to render the currently set
4985 * texture-blending operations in a single pass". Whatever that means
4986 * exactly...
4988 * Version 3 and 7
4990 * Params:
4991 * NumPasses: Address to write the number of necessary passes for the
4992 * desired effect to.
4994 * Returns:
4995 * D3D_OK on success
4996 * See IWineD3DDevice::ValidateDevice for more details
4998 *****************************************************************************/
4999 static HRESULT
5000 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
5001 DWORD *NumPasses)
5003 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5004 HRESULT hr;
5006 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
5008 wined3d_mutex_lock();
5009 hr = wined3d_device_validate_device(This->wined3d_device, NumPasses);
5010 wined3d_mutex_unlock();
5012 return hr;
5015 static HRESULT WINAPI
5016 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
5017 DWORD *NumPasses)
5019 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5022 static HRESULT WINAPI
5023 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
5024 DWORD *NumPasses)
5026 HRESULT hr;
5027 WORD old_fpucw;
5029 old_fpucw = d3d_fpu_setup();
5030 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5031 set_fpu_control_word(old_fpucw);
5033 return hr;
5036 static HRESULT WINAPI IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *Passes)
5038 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
5040 TRACE("iface %p, pass_count %p.\n", iface, Passes);
5042 return IDirect3DDevice7_ValidateDevice(&This->IDirect3DDevice7_iface, Passes);
5045 /*****************************************************************************
5046 * IDirect3DDevice7::Clear
5048 * Fills the render target, the z buffer and the stencil buffer with a
5049 * clear color / value
5051 * Version 7 only
5053 * Params:
5054 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5055 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5056 * Flags: Some flags, as usual
5057 * Color: Clear color for the render target
5058 * Z: Clear value for the Z buffer
5059 * Stencil: Clear value to store in each stencil buffer entry
5061 * Returns:
5062 * D3D_OK on success
5063 * For details, see IWineD3DDevice::Clear
5065 *****************************************************************************/
5066 static HRESULT IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface, DWORD count,
5067 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5069 const struct wined3d_color c =
5071 ((color >> 16) & 0xff) / 255.0f,
5072 ((color >> 8) & 0xff) / 255.0f,
5073 (color & 0xff) / 255.0f,
5074 ((color >> 24) & 0xff) / 255.0f,
5076 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5077 HRESULT hr;
5079 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5080 iface, count, rects, flags, color, z, stencil);
5082 wined3d_mutex_lock();
5083 hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
5084 wined3d_mutex_unlock();
5086 return hr;
5089 static HRESULT WINAPI
5090 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5091 DWORD Count,
5092 D3DRECT *Rects,
5093 DWORD Flags,
5094 D3DCOLOR Color,
5095 D3DVALUE Z,
5096 DWORD Stencil)
5098 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5101 static HRESULT WINAPI
5102 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5103 DWORD Count,
5104 D3DRECT *Rects,
5105 DWORD Flags,
5106 D3DCOLOR Color,
5107 D3DVALUE Z,
5108 DWORD Stencil)
5110 HRESULT hr;
5111 WORD old_fpucw;
5113 old_fpucw = d3d_fpu_setup();
5114 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5115 set_fpu_control_word(old_fpucw);
5117 return hr;
5120 /*****************************************************************************
5121 * IDirect3DDevice7::SetViewport
5123 * Sets the current viewport.
5125 * Version 7 only, but IDirect3DViewport uses this call for older
5126 * versions
5128 * Params:
5129 * Data: The new viewport to set
5131 * Returns:
5132 * D3D_OK on success
5133 * DDERR_INVALIDPARAMS if Data is NULL
5134 * For more details, see IWineDDDevice::SetViewport
5136 *****************************************************************************/
5137 static HRESULT
5138 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5139 D3DVIEWPORT7 *Data)
5141 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5142 HRESULT hr;
5144 TRACE("iface %p, viewport %p.\n", iface, Data);
5146 if(!Data)
5147 return DDERR_INVALIDPARAMS;
5149 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5150 wined3d_mutex_lock();
5151 hr = wined3d_device_set_viewport(This->wined3d_device, (struct wined3d_viewport *)Data);
5152 wined3d_mutex_unlock();
5154 return hr;
5157 static HRESULT WINAPI
5158 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5159 D3DVIEWPORT7 *Data)
5161 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5164 static HRESULT WINAPI
5165 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5166 D3DVIEWPORT7 *Data)
5168 HRESULT hr;
5169 WORD old_fpucw;
5171 old_fpucw = d3d_fpu_setup();
5172 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5173 set_fpu_control_word(old_fpucw);
5175 return hr;
5178 /*****************************************************************************
5179 * IDirect3DDevice::GetViewport
5181 * Returns the current viewport
5183 * Version 7
5185 * Params:
5186 * Data: D3D7Viewport structure to write the viewport information to
5188 * Returns:
5189 * D3D_OK on success
5190 * DDERR_INVALIDPARAMS if Data is NULL
5191 * For more details, see IWineD3DDevice::GetViewport
5193 *****************************************************************************/
5194 static HRESULT
5195 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5196 D3DVIEWPORT7 *Data)
5198 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5199 HRESULT hr;
5201 TRACE("iface %p, viewport %p.\n", iface, Data);
5203 if(!Data)
5204 return DDERR_INVALIDPARAMS;
5206 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5207 wined3d_mutex_lock();
5208 hr = wined3d_device_get_viewport(This->wined3d_device, (struct wined3d_viewport *)Data);
5209 wined3d_mutex_unlock();
5211 return hr_ddraw_from_wined3d(hr);
5214 static HRESULT WINAPI
5215 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5216 D3DVIEWPORT7 *Data)
5218 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5221 static HRESULT WINAPI
5222 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5223 D3DVIEWPORT7 *Data)
5225 HRESULT hr;
5226 WORD old_fpucw;
5228 old_fpucw = d3d_fpu_setup();
5229 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5230 set_fpu_control_word(old_fpucw);
5232 return hr;
5235 /*****************************************************************************
5236 * IDirect3DDevice7::SetMaterial
5238 * Sets the Material
5240 * Version 7
5242 * Params:
5243 * Mat: The material to set
5245 * Returns:
5246 * D3D_OK on success
5247 * DDERR_INVALIDPARAMS if Mat is NULL.
5248 * For more details, see IWineD3DDevice::SetMaterial
5250 *****************************************************************************/
5251 static HRESULT
5252 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5253 D3DMATERIAL7 *Mat)
5255 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5256 HRESULT hr;
5258 TRACE("iface %p, material %p.\n", iface, Mat);
5260 if (!Mat) return DDERR_INVALIDPARAMS;
5262 wined3d_mutex_lock();
5263 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5264 hr = wined3d_device_set_material(This->wined3d_device, (struct wined3d_material *)Mat);
5265 wined3d_mutex_unlock();
5267 return hr_ddraw_from_wined3d(hr);
5270 static HRESULT WINAPI
5271 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5272 D3DMATERIAL7 *Mat)
5274 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5277 static HRESULT WINAPI
5278 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5279 D3DMATERIAL7 *Mat)
5281 HRESULT hr;
5282 WORD old_fpucw;
5284 old_fpucw = d3d_fpu_setup();
5285 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5286 set_fpu_control_word(old_fpucw);
5288 return hr;
5291 /*****************************************************************************
5292 * IDirect3DDevice7::GetMaterial
5294 * Returns the current material
5296 * Version 7
5298 * Params:
5299 * Mat: D3DMATERIAL7 structure to write the material parameters to
5301 * Returns:
5302 * D3D_OK on success
5303 * DDERR_INVALIDPARAMS if Mat is NULL
5304 * For more details, see IWineD3DDevice::GetMaterial
5306 *****************************************************************************/
5307 static HRESULT
5308 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5309 D3DMATERIAL7 *Mat)
5311 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5312 HRESULT hr;
5314 TRACE("iface %p, material %p.\n", iface, Mat);
5316 wined3d_mutex_lock();
5317 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5318 hr = wined3d_device_get_material(This->wined3d_device, (struct wined3d_material *)Mat);
5319 wined3d_mutex_unlock();
5321 return hr_ddraw_from_wined3d(hr);
5324 static HRESULT WINAPI
5325 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5326 D3DMATERIAL7 *Mat)
5328 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5331 static HRESULT WINAPI
5332 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5333 D3DMATERIAL7 *Mat)
5335 HRESULT hr;
5336 WORD old_fpucw;
5338 old_fpucw = d3d_fpu_setup();
5339 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5340 set_fpu_control_word(old_fpucw);
5342 return hr;
5345 /*****************************************************************************
5346 * IDirect3DDevice7::SetLight
5348 * Assigns a light to a light index, but doesn't activate it yet.
5350 * Version 7, IDirect3DLight uses this method for older versions
5352 * Params:
5353 * LightIndex: The index of the new light
5354 * Light: A D3DLIGHT7 structure describing the light
5356 * Returns:
5357 * D3D_OK on success
5358 * For more details, see IWineD3DDevice::SetLight
5360 *****************************************************************************/
5361 static HRESULT
5362 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5363 DWORD LightIndex,
5364 D3DLIGHT7 *Light)
5366 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5367 HRESULT hr;
5369 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5371 wined3d_mutex_lock();
5372 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5373 hr = wined3d_device_set_light(This->wined3d_device, LightIndex, (struct wined3d_light *)Light);
5374 wined3d_mutex_unlock();
5376 return hr_ddraw_from_wined3d(hr);
5379 static HRESULT WINAPI
5380 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5381 DWORD LightIndex,
5382 D3DLIGHT7 *Light)
5384 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5387 static HRESULT WINAPI
5388 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5389 DWORD LightIndex,
5390 D3DLIGHT7 *Light)
5392 HRESULT hr;
5393 WORD old_fpucw;
5395 old_fpucw = d3d_fpu_setup();
5396 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5397 set_fpu_control_word(old_fpucw);
5399 return hr;
5402 /*****************************************************************************
5403 * IDirect3DDevice7::GetLight
5405 * Returns the light assigned to a light index
5407 * Params:
5408 * Light: Structure to write the light information to
5410 * Returns:
5411 * D3D_OK on success
5412 * DDERR_INVALIDPARAMS if Light is NULL
5413 * For details, see IWineD3DDevice::GetLight
5415 *****************************************************************************/
5416 static HRESULT
5417 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5418 DWORD LightIndex,
5419 D3DLIGHT7 *Light)
5421 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5422 HRESULT rc;
5424 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5426 wined3d_mutex_lock();
5427 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5428 rc = wined3d_device_get_light(This->wined3d_device, LightIndex, (struct wined3d_light *)Light);
5429 wined3d_mutex_unlock();
5431 /* Translate the result. WineD3D returns other values than D3D7 */
5432 return hr_ddraw_from_wined3d(rc);
5435 static HRESULT WINAPI
5436 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5437 DWORD LightIndex,
5438 D3DLIGHT7 *Light)
5440 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5443 static HRESULT WINAPI
5444 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5445 DWORD LightIndex,
5446 D3DLIGHT7 *Light)
5448 HRESULT hr;
5449 WORD old_fpucw;
5451 old_fpucw = d3d_fpu_setup();
5452 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5453 set_fpu_control_word(old_fpucw);
5455 return hr;
5458 /*****************************************************************************
5459 * IDirect3DDevice7::BeginStateBlock
5461 * Begins recording to a stateblock
5463 * Version 7
5465 * Returns:
5466 * D3D_OK on success
5467 * For details see IWineD3DDevice::BeginStateBlock
5469 *****************************************************************************/
5470 static HRESULT
5471 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5473 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5474 HRESULT hr;
5476 TRACE("iface %p.\n", iface);
5478 wined3d_mutex_lock();
5479 hr = wined3d_device_begin_stateblock(This->wined3d_device);
5480 wined3d_mutex_unlock();
5482 return hr_ddraw_from_wined3d(hr);
5485 static HRESULT WINAPI
5486 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5488 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5491 static HRESULT WINAPI
5492 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5494 HRESULT hr;
5495 WORD old_fpucw;
5497 old_fpucw = d3d_fpu_setup();
5498 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5499 set_fpu_control_word(old_fpucw);
5501 return hr;
5504 /*****************************************************************************
5505 * IDirect3DDevice7::EndStateBlock
5507 * Stops recording to a state block and returns the created stateblock
5508 * handle.
5510 * Version 7
5512 * Params:
5513 * BlockHandle: Address to store the stateblock's handle to
5515 * Returns:
5516 * D3D_OK on success
5517 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5518 * See IWineD3DDevice::EndStateBlock for more details
5520 *****************************************************************************/
5521 static HRESULT
5522 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5523 DWORD *BlockHandle)
5525 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5526 struct wined3d_stateblock *wined3d_sb;
5527 HRESULT hr;
5528 DWORD h;
5530 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5532 if(!BlockHandle)
5534 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5535 return DDERR_INVALIDPARAMS;
5538 wined3d_mutex_lock();
5540 hr = wined3d_device_end_stateblock(This->wined3d_device, &wined3d_sb);
5541 if (FAILED(hr))
5543 WARN("Failed to end stateblock, hr %#x.\n", hr);
5544 wined3d_mutex_unlock();
5545 *BlockHandle = 0;
5546 return hr_ddraw_from_wined3d(hr);
5549 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5550 if (h == DDRAW_INVALID_HANDLE)
5552 ERR("Failed to allocate a stateblock handle.\n");
5553 wined3d_stateblock_decref(wined3d_sb);
5554 wined3d_mutex_unlock();
5555 *BlockHandle = 0;
5556 return DDERR_OUTOFMEMORY;
5559 wined3d_mutex_unlock();
5560 *BlockHandle = h + 1;
5562 return hr_ddraw_from_wined3d(hr);
5565 static HRESULT WINAPI
5566 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5567 DWORD *BlockHandle)
5569 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5572 static HRESULT WINAPI
5573 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5574 DWORD *BlockHandle)
5576 HRESULT hr;
5577 WORD old_fpucw;
5579 old_fpucw = d3d_fpu_setup();
5580 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5581 set_fpu_control_word(old_fpucw);
5583 return hr;
5586 /*****************************************************************************
5587 * IDirect3DDevice7::PreLoad
5589 * Allows the app to signal that a texture will be used soon, to allow
5590 * the Direct3DDevice to load it to the video card in the meantime.
5592 * Version 7
5594 * Params:
5595 * Texture: The texture to preload
5597 * Returns:
5598 * D3D_OK on success
5599 * DDERR_INVALIDPARAMS if Texture is NULL
5600 * See IWineD3DSurface::PreLoad for details
5602 *****************************************************************************/
5603 static HRESULT
5604 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5605 IDirectDrawSurface7 *Texture)
5607 IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
5609 TRACE("iface %p, texture %p.\n", iface, Texture);
5611 if(!Texture)
5612 return DDERR_INVALIDPARAMS;
5614 wined3d_mutex_lock();
5615 wined3d_surface_preload(surf->wined3d_surface);
5616 wined3d_mutex_unlock();
5618 return D3D_OK;
5621 static HRESULT WINAPI
5622 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5623 IDirectDrawSurface7 *Texture)
5625 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5628 static HRESULT WINAPI
5629 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5630 IDirectDrawSurface7 *Texture)
5632 HRESULT hr;
5633 WORD old_fpucw;
5635 old_fpucw = d3d_fpu_setup();
5636 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5637 set_fpu_control_word(old_fpucw);
5639 return hr;
5642 /*****************************************************************************
5643 * IDirect3DDevice7::ApplyStateBlock
5645 * Activates the state stored in a state block handle.
5647 * Params:
5648 * BlockHandle: The stateblock handle to activate
5650 * Returns:
5651 * D3D_OK on success
5652 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5654 *****************************************************************************/
5655 static HRESULT
5656 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5657 DWORD BlockHandle)
5659 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5660 struct wined3d_stateblock *wined3d_sb;
5661 HRESULT hr;
5663 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5665 wined3d_mutex_lock();
5666 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5667 if (!wined3d_sb)
5669 WARN("Invalid stateblock handle.\n");
5670 wined3d_mutex_unlock();
5671 return D3DERR_INVALIDSTATEBLOCK;
5674 hr = wined3d_stateblock_apply(wined3d_sb);
5675 wined3d_mutex_unlock();
5677 return hr_ddraw_from_wined3d(hr);
5680 static HRESULT WINAPI
5681 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5682 DWORD BlockHandle)
5684 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5687 static HRESULT WINAPI
5688 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5689 DWORD BlockHandle)
5691 HRESULT hr;
5692 WORD old_fpucw;
5694 old_fpucw = d3d_fpu_setup();
5695 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5696 set_fpu_control_word(old_fpucw);
5698 return hr;
5701 /*****************************************************************************
5702 * IDirect3DDevice7::CaptureStateBlock
5704 * Updates a stateblock's values to the values currently set for the device
5706 * Version 7
5708 * Params:
5709 * BlockHandle: Stateblock to update
5711 * Returns:
5712 * D3D_OK on success
5713 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5714 * See IWineD3DDevice::CaptureStateBlock for more details
5716 *****************************************************************************/
5717 static HRESULT
5718 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5719 DWORD BlockHandle)
5721 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5722 struct wined3d_stateblock *wined3d_sb;
5723 HRESULT hr;
5725 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5727 wined3d_mutex_lock();
5728 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5729 if (!wined3d_sb)
5731 WARN("Invalid stateblock handle.\n");
5732 wined3d_mutex_unlock();
5733 return D3DERR_INVALIDSTATEBLOCK;
5736 hr = wined3d_stateblock_capture(wined3d_sb);
5737 wined3d_mutex_unlock();
5739 return hr_ddraw_from_wined3d(hr);
5742 static HRESULT WINAPI
5743 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5744 DWORD BlockHandle)
5746 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5749 static HRESULT WINAPI
5750 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5751 DWORD BlockHandle)
5753 HRESULT hr;
5754 WORD old_fpucw;
5756 old_fpucw = d3d_fpu_setup();
5757 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5758 set_fpu_control_word(old_fpucw);
5760 return hr;
5763 /*****************************************************************************
5764 * IDirect3DDevice7::DeleteStateBlock
5766 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5768 * Version 7
5770 * Params:
5771 * BlockHandle: Stateblock handle to delete
5773 * Returns:
5774 * D3D_OK on success
5775 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5777 *****************************************************************************/
5778 static HRESULT
5779 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5780 DWORD BlockHandle)
5782 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5783 struct wined3d_stateblock *wined3d_sb;
5784 ULONG ref;
5786 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5788 wined3d_mutex_lock();
5790 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5791 if (!wined3d_sb)
5793 WARN("Invalid stateblock handle.\n");
5794 wined3d_mutex_unlock();
5795 return D3DERR_INVALIDSTATEBLOCK;
5798 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5800 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5803 wined3d_mutex_unlock();
5805 return D3D_OK;
5808 static HRESULT WINAPI
5809 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5810 DWORD BlockHandle)
5812 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5815 static HRESULT WINAPI
5816 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5817 DWORD BlockHandle)
5819 HRESULT hr;
5820 WORD old_fpucw;
5822 old_fpucw = d3d_fpu_setup();
5823 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5824 set_fpu_control_word(old_fpucw);
5826 return hr;
5829 /*****************************************************************************
5830 * IDirect3DDevice7::CreateStateBlock
5832 * Creates a new state block handle.
5834 * Version 7
5836 * Params:
5837 * Type: The state block type
5838 * BlockHandle: Address to write the created handle to
5840 * Returns:
5841 * D3D_OK on success
5842 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5844 *****************************************************************************/
5845 static HRESULT
5846 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5847 D3DSTATEBLOCKTYPE Type,
5848 DWORD *BlockHandle)
5850 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5851 struct wined3d_stateblock *wined3d_sb;
5852 HRESULT hr;
5853 DWORD h;
5855 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5857 if(!BlockHandle)
5859 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5860 return DDERR_INVALIDPARAMS;
5862 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5863 Type != D3DSBT_VERTEXSTATE ) {
5864 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5865 return DDERR_INVALIDPARAMS;
5868 wined3d_mutex_lock();
5870 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5871 hr = wined3d_stateblock_create(This->wined3d_device, Type, &wined3d_sb);
5872 if (FAILED(hr))
5874 WARN("Failed to create stateblock, hr %#x.\n", hr);
5875 wined3d_mutex_unlock();
5876 return hr_ddraw_from_wined3d(hr);
5879 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5880 if (h == DDRAW_INVALID_HANDLE)
5882 ERR("Failed to allocate stateblock handle.\n");
5883 wined3d_stateblock_decref(wined3d_sb);
5884 wined3d_mutex_unlock();
5885 return DDERR_OUTOFMEMORY;
5888 *BlockHandle = h + 1;
5889 wined3d_mutex_unlock();
5891 return hr_ddraw_from_wined3d(hr);
5894 static HRESULT WINAPI
5895 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5896 D3DSTATEBLOCKTYPE Type,
5897 DWORD *BlockHandle)
5899 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5902 static HRESULT WINAPI
5903 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5904 D3DSTATEBLOCKTYPE Type,
5905 DWORD *BlockHandle)
5907 HRESULT hr;
5908 WORD old_fpucw;
5910 old_fpucw = d3d_fpu_setup();
5911 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5912 set_fpu_control_word(old_fpucw);
5914 return hr;
5917 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5918 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
5919 IDirectDrawSurfaceImpl *src)
5921 IDirectDrawSurfaceImpl *src_level, *dest_level;
5922 IDirectDrawSurface7 *temp;
5923 DDSURFACEDESC2 ddsd;
5924 BOOL levelFound; /* at least one suitable sublevel in dest found */
5926 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5927 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5928 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5930 levelFound = FALSE;
5932 src_level = src;
5933 dest_level = dest;
5935 for (;src_level && dest_level;)
5937 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5938 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5940 levelFound = TRUE;
5942 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5943 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5944 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5946 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5948 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5951 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5952 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5953 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5955 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5957 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5960 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5961 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5963 return !dest_level && levelFound;
5966 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5967 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
5968 IDirectDrawSurfaceImpl *dest,
5969 IDirectDrawSurfaceImpl *src,
5970 const POINT *DestPoint,
5971 const RECT *SrcRect)
5973 IDirectDrawSurfaceImpl *src_level, *dest_level;
5974 IDirectDrawSurface7 *temp;
5975 DDSURFACEDESC2 ddsd;
5976 POINT point;
5977 RECT src_rect;
5978 HRESULT hr;
5979 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5980 DWORD ckeyflag;
5981 DDCOLORKEY ddckey;
5983 /* Copy palette, if possible. */
5984 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
5985 IDirectDrawSurface7_GetPalette(&dest->IDirectDrawSurface7_iface, &pal);
5987 if (pal_src != NULL && pal != NULL)
5989 PALETTEENTRY palent[256];
5991 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5992 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5995 if (pal) IDirectDrawPalette_Release(pal);
5996 if (pal_src) IDirectDrawPalette_Release(pal_src);
5998 /* Copy colorkeys, if present. */
5999 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6001 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6003 if (SUCCEEDED(hr))
6005 IDirectDrawSurface7_SetColorKey(&dest->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6009 src_level = src;
6010 dest_level = dest;
6012 point = *DestPoint;
6013 src_rect = *SrcRect;
6015 for (;src_level && dest_level;)
6017 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6018 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6020 UINT src_w = src_rect.right - src_rect.left;
6021 UINT src_h = src_rect.bottom - src_rect.top;
6022 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
6024 if (FAILED(hr = wined3d_surface_blt(dest_level->wined3d_surface, &dst_rect,
6025 src_level->wined3d_surface, &src_rect, 0, NULL, WINED3DTEXF_POINT)))
6026 ERR("Blit failed, hr %#x.\n", hr);
6028 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6029 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6030 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6032 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6034 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6037 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6038 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6039 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6041 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6043 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6045 point.x /= 2;
6046 point.y /= 2;
6048 src_rect.top /= 2;
6049 src_rect.left /= 2;
6050 src_rect.right = (src_rect.right + 1) / 2;
6051 src_rect.bottom = (src_rect.bottom + 1) / 2;
6054 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6055 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6058 /*****************************************************************************
6059 * IDirect3DDevice7::Load
6061 * Loads a rectangular area from the source into the destination texture.
6062 * It can also copy the source to the faces of a cubic environment map
6064 * Version 7
6066 * Params:
6067 * DestTex: Destination texture
6068 * DestPoint: Point in the destination where the source image should be
6069 * written to
6070 * SrcTex: Source texture
6071 * SrcRect: Source rectangle
6072 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6073 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6074 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6076 * Returns:
6077 * D3D_OK on success
6078 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6081 *****************************************************************************/
6083 static HRESULT
6084 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6085 IDirectDrawSurface7 *DestTex,
6086 POINT *DestPoint,
6087 IDirectDrawSurface7 *SrcTex,
6088 RECT *SrcRect,
6089 DWORD Flags)
6091 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6092 IDirectDrawSurfaceImpl *dest = unsafe_impl_from_IDirectDrawSurface7(DestTex);
6093 IDirectDrawSurfaceImpl *src = unsafe_impl_from_IDirectDrawSurface7(SrcTex);
6094 POINT destpoint;
6095 RECT srcrect;
6097 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6098 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6100 if( (!src) || (!dest) )
6101 return DDERR_INVALIDPARAMS;
6103 wined3d_mutex_lock();
6105 if (SrcRect) srcrect = *SrcRect;
6106 else
6108 srcrect.left = srcrect.top = 0;
6109 srcrect.right = src->surface_desc.dwWidth;
6110 srcrect.bottom = src->surface_desc.dwHeight;
6113 if (DestPoint) destpoint = *DestPoint;
6114 else
6116 destpoint.x = destpoint.y = 0;
6118 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6119 * destination can be a subset of mip levels, in which case actual coordinates used
6120 * for it may be divided. If any dimension of dest is larger than source, it can't be
6121 * mip level subset, so an error can be returned early.
6123 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6124 srcrect.right > src->surface_desc.dwWidth ||
6125 srcrect.bottom > src->surface_desc.dwHeight ||
6126 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6127 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6128 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6129 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6131 wined3d_mutex_unlock();
6132 return DDERR_INVALIDPARAMS;
6135 /* Must be top level surfaces. */
6136 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6137 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6139 wined3d_mutex_unlock();
6140 return DDERR_INVALIDPARAMS;
6143 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6145 DWORD src_face_flag, dest_face_flag;
6146 IDirectDrawSurfaceImpl *src_face, *dest_face;
6147 IDirectDrawSurface7 *temp;
6148 DDSURFACEDESC2 ddsd;
6149 int i;
6151 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6153 wined3d_mutex_unlock();
6154 return DDERR_INVALIDPARAMS;
6157 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6158 * time it's actual surface loading. */
6159 for (i = 0; i < 2; i++)
6161 dest_face = dest;
6162 src_face = src;
6164 for (;dest_face && src_face;)
6166 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6167 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6169 if (src_face_flag == dest_face_flag)
6171 if (i == 0)
6173 /* Destination mip levels must be subset of source mip levels. */
6174 if (!is_mip_level_subset(dest_face, src_face))
6176 wined3d_mutex_unlock();
6177 return DDERR_INVALIDPARAMS;
6180 else if (Flags & dest_face_flag)
6182 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6185 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6187 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6188 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6189 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6191 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6193 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6195 else
6197 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6199 src_face = NULL;
6203 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6205 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6206 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6207 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6209 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6211 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6213 else
6215 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6217 dest_face = NULL;
6221 if (i == 0)
6223 /* Native returns error if src faces are not subset of dest faces. */
6224 if (src_face)
6226 wined3d_mutex_unlock();
6227 return DDERR_INVALIDPARAMS;
6232 wined3d_mutex_unlock();
6233 return D3D_OK;
6235 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6237 wined3d_mutex_unlock();
6238 return DDERR_INVALIDPARAMS;
6241 /* Handle non cube map textures. */
6243 /* Destination mip levels must be subset of source mip levels. */
6244 if (!is_mip_level_subset(dest, src))
6246 wined3d_mutex_unlock();
6247 return DDERR_INVALIDPARAMS;
6250 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6252 wined3d_mutex_unlock();
6254 return D3D_OK;
6257 static HRESULT WINAPI
6258 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6259 IDirectDrawSurface7 *DestTex,
6260 POINT *DestPoint,
6261 IDirectDrawSurface7 *SrcTex,
6262 RECT *SrcRect,
6263 DWORD Flags)
6265 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6268 static HRESULT WINAPI
6269 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6270 IDirectDrawSurface7 *DestTex,
6271 POINT *DestPoint,
6272 IDirectDrawSurface7 *SrcTex,
6273 RECT *SrcRect,
6274 DWORD Flags)
6276 HRESULT hr;
6277 WORD old_fpucw;
6279 old_fpucw = d3d_fpu_setup();
6280 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6281 set_fpu_control_word(old_fpucw);
6283 return hr;
6286 /*****************************************************************************
6287 * IDirect3DDevice7::LightEnable
6289 * Enables or disables a light
6291 * Version 7, IDirect3DLight uses this method too.
6293 * Params:
6294 * LightIndex: The index of the light to enable / disable
6295 * Enable: Enable or disable the light
6297 * Returns:
6298 * D3D_OK on success
6299 * For more details, see IWineD3DDevice::SetLightEnable
6301 *****************************************************************************/
6302 static HRESULT
6303 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6304 DWORD LightIndex,
6305 BOOL Enable)
6307 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6308 HRESULT hr;
6310 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6312 wined3d_mutex_lock();
6313 hr = wined3d_device_set_light_enable(This->wined3d_device, LightIndex, Enable);
6314 wined3d_mutex_unlock();
6316 return hr_ddraw_from_wined3d(hr);
6319 static HRESULT WINAPI
6320 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6321 DWORD LightIndex,
6322 BOOL Enable)
6324 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6327 static HRESULT WINAPI
6328 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6329 DWORD LightIndex,
6330 BOOL Enable)
6332 HRESULT hr;
6333 WORD old_fpucw;
6335 old_fpucw = d3d_fpu_setup();
6336 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6337 set_fpu_control_word(old_fpucw);
6339 return hr;
6342 /*****************************************************************************
6343 * IDirect3DDevice7::GetLightEnable
6345 * Retrieves if the light with the given index is enabled or not
6347 * Version 7
6349 * Params:
6350 * LightIndex: Index of desired light
6351 * Enable: Pointer to a BOOL which contains the result
6353 * Returns:
6354 * D3D_OK on success
6355 * DDERR_INVALIDPARAMS if Enable is NULL
6356 * See IWineD3DDevice::GetLightEnable for more details
6358 *****************************************************************************/
6359 static HRESULT
6360 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6361 DWORD LightIndex,
6362 BOOL* Enable)
6364 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6365 HRESULT hr;
6367 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6369 if(!Enable)
6370 return DDERR_INVALIDPARAMS;
6372 wined3d_mutex_lock();
6373 hr = wined3d_device_get_light_enable(This->wined3d_device, LightIndex, Enable);
6374 wined3d_mutex_unlock();
6376 return hr_ddraw_from_wined3d(hr);
6379 static HRESULT WINAPI
6380 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6381 DWORD LightIndex,
6382 BOOL* Enable)
6384 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6387 static HRESULT WINAPI
6388 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6389 DWORD LightIndex,
6390 BOOL* Enable)
6392 HRESULT hr;
6393 WORD old_fpucw;
6395 old_fpucw = d3d_fpu_setup();
6396 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6397 set_fpu_control_word(old_fpucw);
6399 return hr;
6402 /*****************************************************************************
6403 * IDirect3DDevice7::SetClipPlane
6405 * Sets custom clipping plane
6407 * Version 7
6409 * Params:
6410 * Index: The index of the clipping plane
6411 * PlaneEquation: An equation defining the clipping plane
6413 * Returns:
6414 * D3D_OK on success
6415 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6416 * See IWineD3DDevice::SetClipPlane for more details
6418 *****************************************************************************/
6419 static HRESULT
6420 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6421 DWORD Index,
6422 D3DVALUE* PlaneEquation)
6424 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6425 HRESULT hr;
6427 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6429 if(!PlaneEquation)
6430 return DDERR_INVALIDPARAMS;
6432 wined3d_mutex_lock();
6433 hr = wined3d_device_set_clip_plane(This->wined3d_device, Index, PlaneEquation);
6434 wined3d_mutex_unlock();
6436 return hr;
6439 static HRESULT WINAPI
6440 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6441 DWORD Index,
6442 D3DVALUE* PlaneEquation)
6444 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6447 static HRESULT WINAPI
6448 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6449 DWORD Index,
6450 D3DVALUE* PlaneEquation)
6452 HRESULT hr;
6453 WORD old_fpucw;
6455 old_fpucw = d3d_fpu_setup();
6456 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6457 set_fpu_control_word(old_fpucw);
6459 return hr;
6462 /*****************************************************************************
6463 * IDirect3DDevice7::GetClipPlane
6465 * Returns the clipping plane with a specific index
6467 * Params:
6468 * Index: The index of the desired plane
6469 * PlaneEquation: Address to store the plane equation to
6471 * Returns:
6472 * D3D_OK on success
6473 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6474 * See IWineD3DDevice::GetClipPlane for more details
6476 *****************************************************************************/
6477 static HRESULT
6478 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6479 DWORD Index,
6480 D3DVALUE* PlaneEquation)
6482 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6483 HRESULT hr;
6485 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6487 if(!PlaneEquation)
6488 return DDERR_INVALIDPARAMS;
6490 wined3d_mutex_lock();
6491 hr = wined3d_device_get_clip_plane(This->wined3d_device, Index, PlaneEquation);
6492 wined3d_mutex_unlock();
6494 return hr;
6497 static HRESULT WINAPI
6498 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6499 DWORD Index,
6500 D3DVALUE* PlaneEquation)
6502 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6505 static HRESULT WINAPI
6506 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6507 DWORD Index,
6508 D3DVALUE* PlaneEquation)
6510 HRESULT hr;
6511 WORD old_fpucw;
6513 old_fpucw = d3d_fpu_setup();
6514 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6515 set_fpu_control_word(old_fpucw);
6517 return hr;
6520 /*****************************************************************************
6521 * IDirect3DDevice7::GetInfo
6523 * Retrieves some information about the device. The DirectX sdk says that
6524 * this version returns S_FALSE for all retail builds of DirectX, that's what
6525 * this implementation does.
6527 * Params:
6528 * DevInfoID: Information type requested
6529 * DevInfoStruct: Pointer to a structure to store the info to
6530 * Size: Size of the structure
6532 * Returns:
6533 * S_FALSE, because it's a non-debug driver
6535 *****************************************************************************/
6536 static HRESULT WINAPI
6537 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6538 DWORD DevInfoID,
6539 void *DevInfoStruct,
6540 DWORD Size)
6542 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6543 iface, DevInfoID, DevInfoStruct, Size);
6545 if (TRACE_ON(ddraw))
6547 TRACE(" info requested : ");
6548 switch (DevInfoID)
6550 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6551 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6552 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6553 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6557 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6560 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6561 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6562 * are not duplicated.
6564 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6565 * has already been setup for optimal d3d operation.
6567 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6568 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6569 * by Sacrifice (game). */
6570 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6572 /*** IUnknown Methods ***/
6573 IDirect3DDeviceImpl_7_QueryInterface,
6574 IDirect3DDeviceImpl_7_AddRef,
6575 IDirect3DDeviceImpl_7_Release,
6576 /*** IDirect3DDevice7 ***/
6577 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6578 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6579 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6580 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6581 IDirect3DDeviceImpl_7_GetDirect3D,
6582 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6583 IDirect3DDeviceImpl_7_GetRenderTarget,
6584 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6585 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6586 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6587 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6588 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6589 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6590 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6591 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6592 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6593 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6594 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6595 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6596 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6597 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6598 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6599 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6600 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6601 IDirect3DDeviceImpl_7_SetClipStatus,
6602 IDirect3DDeviceImpl_7_GetClipStatus,
6603 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6604 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6605 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6606 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6607 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6608 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6609 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6610 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6611 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6612 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6613 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6614 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6615 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6616 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6617 IDirect3DDeviceImpl_7_Load_FPUSetup,
6618 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6619 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6620 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6621 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6622 IDirect3DDeviceImpl_7_GetInfo
6625 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6627 /*** IUnknown Methods ***/
6628 IDirect3DDeviceImpl_7_QueryInterface,
6629 IDirect3DDeviceImpl_7_AddRef,
6630 IDirect3DDeviceImpl_7_Release,
6631 /*** IDirect3DDevice7 ***/
6632 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6633 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6634 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6635 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6636 IDirect3DDeviceImpl_7_GetDirect3D,
6637 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6638 IDirect3DDeviceImpl_7_GetRenderTarget,
6639 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6640 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6641 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6642 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6643 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6644 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6645 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6646 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6647 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6648 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6649 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6650 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6651 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6652 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6653 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6654 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6655 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6656 IDirect3DDeviceImpl_7_SetClipStatus,
6657 IDirect3DDeviceImpl_7_GetClipStatus,
6658 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6659 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6660 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6661 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6662 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6663 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6664 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6665 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6666 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6667 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6668 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6669 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6670 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6671 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6672 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6673 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6674 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6675 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6676 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6677 IDirect3DDeviceImpl_7_GetInfo
6680 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6682 /*** IUnknown Methods ***/
6683 IDirect3DDeviceImpl_3_QueryInterface,
6684 IDirect3DDeviceImpl_3_AddRef,
6685 IDirect3DDeviceImpl_3_Release,
6686 /*** IDirect3DDevice3 ***/
6687 IDirect3DDeviceImpl_3_GetCaps,
6688 IDirect3DDeviceImpl_3_GetStats,
6689 IDirect3DDeviceImpl_3_AddViewport,
6690 IDirect3DDeviceImpl_3_DeleteViewport,
6691 IDirect3DDeviceImpl_3_NextViewport,
6692 IDirect3DDeviceImpl_3_EnumTextureFormats,
6693 IDirect3DDeviceImpl_3_BeginScene,
6694 IDirect3DDeviceImpl_3_EndScene,
6695 IDirect3DDeviceImpl_3_GetDirect3D,
6696 IDirect3DDeviceImpl_3_SetCurrentViewport,
6697 IDirect3DDeviceImpl_3_GetCurrentViewport,
6698 IDirect3DDeviceImpl_3_SetRenderTarget,
6699 IDirect3DDeviceImpl_3_GetRenderTarget,
6700 IDirect3DDeviceImpl_3_Begin,
6701 IDirect3DDeviceImpl_3_BeginIndexed,
6702 IDirect3DDeviceImpl_3_Vertex,
6703 IDirect3DDeviceImpl_3_Index,
6704 IDirect3DDeviceImpl_3_End,
6705 IDirect3DDeviceImpl_3_GetRenderState,
6706 IDirect3DDeviceImpl_3_SetRenderState,
6707 IDirect3DDeviceImpl_3_GetLightState,
6708 IDirect3DDeviceImpl_3_SetLightState,
6709 IDirect3DDeviceImpl_3_SetTransform,
6710 IDirect3DDeviceImpl_3_GetTransform,
6711 IDirect3DDeviceImpl_3_MultiplyTransform,
6712 IDirect3DDeviceImpl_3_DrawPrimitive,
6713 IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6714 IDirect3DDeviceImpl_3_SetClipStatus,
6715 IDirect3DDeviceImpl_3_GetClipStatus,
6716 IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6717 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6718 IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6719 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6720 IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6721 IDirect3DDeviceImpl_3_GetTexture,
6722 IDirect3DDeviceImpl_3_SetTexture,
6723 IDirect3DDeviceImpl_3_GetTextureStageState,
6724 IDirect3DDeviceImpl_3_SetTextureStageState,
6725 IDirect3DDeviceImpl_3_ValidateDevice
6728 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6730 /*** IUnknown Methods ***/
6731 IDirect3DDeviceImpl_2_QueryInterface,
6732 IDirect3DDeviceImpl_2_AddRef,
6733 IDirect3DDeviceImpl_2_Release,
6734 /*** IDirect3DDevice2 ***/
6735 IDirect3DDeviceImpl_2_GetCaps,
6736 IDirect3DDeviceImpl_2_SwapTextureHandles,
6737 IDirect3DDeviceImpl_2_GetStats,
6738 IDirect3DDeviceImpl_2_AddViewport,
6739 IDirect3DDeviceImpl_2_DeleteViewport,
6740 IDirect3DDeviceImpl_2_NextViewport,
6741 IDirect3DDeviceImpl_2_EnumTextureFormats,
6742 IDirect3DDeviceImpl_2_BeginScene,
6743 IDirect3DDeviceImpl_2_EndScene,
6744 IDirect3DDeviceImpl_2_GetDirect3D,
6745 IDirect3DDeviceImpl_2_SetCurrentViewport,
6746 IDirect3DDeviceImpl_2_GetCurrentViewport,
6747 IDirect3DDeviceImpl_2_SetRenderTarget,
6748 IDirect3DDeviceImpl_2_GetRenderTarget,
6749 IDirect3DDeviceImpl_2_Begin,
6750 IDirect3DDeviceImpl_2_BeginIndexed,
6751 IDirect3DDeviceImpl_2_Vertex,
6752 IDirect3DDeviceImpl_2_Index,
6753 IDirect3DDeviceImpl_2_End,
6754 IDirect3DDeviceImpl_2_GetRenderState,
6755 IDirect3DDeviceImpl_2_SetRenderState,
6756 IDirect3DDeviceImpl_2_GetLightState,
6757 IDirect3DDeviceImpl_2_SetLightState,
6758 IDirect3DDeviceImpl_2_SetTransform,
6759 IDirect3DDeviceImpl_2_GetTransform,
6760 IDirect3DDeviceImpl_2_MultiplyTransform,
6761 IDirect3DDeviceImpl_2_DrawPrimitive,
6762 IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6763 IDirect3DDeviceImpl_2_SetClipStatus,
6764 IDirect3DDeviceImpl_2_GetClipStatus
6767 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6769 /*** IUnknown Methods ***/
6770 IDirect3DDeviceImpl_1_QueryInterface,
6771 IDirect3DDeviceImpl_1_AddRef,
6772 IDirect3DDeviceImpl_1_Release,
6773 /*** IDirect3DDevice1 ***/
6774 IDirect3DDeviceImpl_1_Initialize,
6775 IDirect3DDeviceImpl_1_GetCaps,
6776 IDirect3DDeviceImpl_1_SwapTextureHandles,
6777 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6778 IDirect3DDeviceImpl_1_GetStats,
6779 IDirect3DDeviceImpl_1_Execute,
6780 IDirect3DDeviceImpl_1_AddViewport,
6781 IDirect3DDeviceImpl_1_DeleteViewport,
6782 IDirect3DDeviceImpl_1_NextViewport,
6783 IDirect3DDeviceImpl_1_Pick,
6784 IDirect3DDeviceImpl_1_GetPickRecords,
6785 IDirect3DDeviceImpl_1_EnumTextureFormats,
6786 IDirect3DDeviceImpl_1_CreateMatrix,
6787 IDirect3DDeviceImpl_1_SetMatrix,
6788 IDirect3DDeviceImpl_1_GetMatrix,
6789 IDirect3DDeviceImpl_1_DeleteMatrix,
6790 IDirect3DDeviceImpl_1_BeginScene,
6791 IDirect3DDeviceImpl_1_EndScene,
6792 IDirect3DDeviceImpl_1_GetDirect3D
6795 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6797 if (!iface) return NULL;
6798 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6799 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice7_iface);
6802 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6804 if (!iface) return NULL;
6805 assert(iface->lpVtbl == &d3d_device3_vtbl);
6806 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice3_iface);
6809 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6811 if (!iface) return NULL;
6812 assert(iface->lpVtbl == &d3d_device2_vtbl);
6813 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice2_iface);
6816 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6818 if (!iface) return NULL;
6819 assert(iface->lpVtbl == &d3d_device1_vtbl);
6820 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice_iface);
6823 /*****************************************************************************
6824 * IDirect3DDeviceImpl_UpdateDepthStencil
6826 * Checks the current render target for attached depth stencils and sets the
6827 * WineD3D depth stencil accordingly.
6829 * Returns:
6830 * The depth stencil state to set if creating the device
6832 *****************************************************************************/
6833 WINED3DZBUFFERTYPE
6834 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6836 IDirectDrawSurface7 *depthStencil = NULL;
6837 IDirectDrawSurfaceImpl *dsi;
6838 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6840 IDirectDrawSurface7_GetAttachedSurface(&This->target->IDirectDrawSurface7_iface, &depthcaps, &depthStencil);
6841 if(!depthStencil)
6843 TRACE("Setting wined3d depth stencil to NULL\n");
6844 wined3d_device_set_depth_stencil(This->wined3d_device, NULL);
6845 return WINED3DZB_FALSE;
6848 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6849 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
6850 wined3d_device_set_depth_stencil(This->wined3d_device, dsi->wined3d_surface);
6852 IDirectDrawSurface7_Release(depthStencil);
6853 return WINED3DZB_TRUE;
6856 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
6858 HRESULT hr;
6860 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6861 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6862 else
6863 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
6865 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6866 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6867 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6868 device->ref = 1;
6869 device->ddraw = ddraw;
6870 device->target = target;
6871 list_init(&device->viewport_list);
6873 if (!ddraw_handle_table_init(&device->handle_table, 64))
6875 ERR("Failed to initialize handle table.\n");
6876 return DDERR_OUTOFMEMORY;
6879 device->legacyTextureBlending = FALSE;
6881 /* Create an index buffer, it's needed for indexed drawing */
6882 hr = wined3d_buffer_create_ib(ddraw->wined3d_device, 0x40000 /* Length. Don't know how long it should be */,
6883 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, NULL,
6884 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
6885 if (FAILED(hr))
6887 ERR("Failed to create an index buffer, hr %#x.\n", hr);
6888 ddraw_handle_table_destroy(&device->handle_table);
6889 return hr;
6892 /* This is for convenience. */
6893 device->wined3d_device = ddraw->wined3d_device;
6894 wined3d_device_incref(ddraw->wined3d_device);
6896 /* Render to the back buffer */
6897 hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
6898 if (FAILED(hr))
6900 ERR("Failed to set render target, hr %#x.\n", hr);
6901 wined3d_buffer_decref(device->indexbuffer);
6902 ddraw_handle_table_destroy(&device->handle_table);
6903 return hr;
6906 /* FIXME: This is broken. The target AddRef() makes some sense, because
6907 * we store a pointer during initialization, but then that's also where
6908 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6909 /* AddRef the render target. Also AddRef the render target from ddraw,
6910 * because if it is released before the app releases the D3D device, the
6911 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6913 * In most cases, those surfaces are the same anyway, but this will simply
6914 * add another ref which is released when the device is destroyed. */
6915 IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
6917 ddraw->d3ddevice = device;
6919 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3DRS_ZENABLE,
6920 IDirect3DDeviceImpl_UpdateDepthStencil(device));
6922 return D3D_OK;