2 * Copyright (c) 1998-2004 Lionel Ulmer
3 * Copyright (c) 2002-2005 Christian Costa
4 * Copyright (c) 2006-2009, 2011-2013 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
30 #include "ddraw_private.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(ddraw
);
33 WINE_DECLARE_DEBUG_CHANNEL(winediag
);
36 const GUID IID_D3DDEVICE_WineD3D
= {
40 { 0xb7,0x98,0xc6,0x8a,0x77,0x2d,0x72,0x2a }
43 static inline void set_fpu_control_word(WORD fpucw
)
45 #if defined(__i386__) && defined(__GNUC__)
46 __asm__
volatile ("fldcw %0" : : "m" (fpucw
));
47 #elif defined(__i386__) && defined(_MSC_VER)
52 static inline WORD
d3d_fpu_setup(void)
56 #if defined(__i386__) && defined(__GNUC__)
57 __asm__
volatile ("fnstcw %0" : "=m" (oldcw
));
58 #elif defined(__i386__) && defined(_MSC_VER)
61 static BOOL warned
= FALSE
;
64 FIXME("FPUPRESERVE not implemented for this platform / compiler\n");
70 set_fpu_control_word(0x37f);
75 static inline struct d3d_device
*impl_from_IUnknown(IUnknown
*iface
)
77 return CONTAINING_RECORD(iface
, struct d3d_device
, IUnknown_inner
);
80 static HRESULT WINAPI
d3d_device_inner_QueryInterface(IUnknown
*iface
, REFIID riid
, void **out
)
82 struct d3d_device
*device
= impl_from_IUnknown(iface
);
84 TRACE("iface %p, riid %s, out %p.\n", iface
, debugstr_guid(riid
), out
);
89 return DDERR_INVALIDPARAMS
;
92 if (IsEqualGUID(&IID_IUnknown
, riid
))
94 IDirect3DDevice7_AddRef(&device
->IDirect3DDevice7_iface
);
95 *out
= &device
->IDirect3DDevice7_iface
;
99 if (device
->version
== 7)
101 if (IsEqualGUID(&IID_IDirect3DDevice7
, riid
))
103 IDirect3DDevice7_AddRef(&device
->IDirect3DDevice7_iface
);
104 *out
= &device
->IDirect3DDevice7_iface
;
110 if (IsEqualGUID(&IID_IDirect3DDevice3
, riid
) && device
->version
== 3)
112 IDirect3DDevice3_AddRef(&device
->IDirect3DDevice3_iface
);
113 *out
= &device
->IDirect3DDevice3_iface
;
117 if (IsEqualGUID(&IID_IDirect3DDevice2
, riid
) && device
->version
>= 2)
119 IDirect3DDevice2_AddRef(&device
->IDirect3DDevice2_iface
);
120 *out
= &device
->IDirect3DDevice2_iface
;
124 if (IsEqualGUID(&IID_IDirect3DDevice
, riid
))
126 IDirect3DDevice_AddRef(&device
->IDirect3DDevice_iface
);
127 *out
= &device
->IDirect3DDevice_iface
;
132 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid
));
135 return E_NOINTERFACE
;
138 static HRESULT WINAPI
d3d_device7_QueryInterface(IDirect3DDevice7
*iface
, REFIID riid
, void **out
)
140 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
142 TRACE("iface %p, riid %s, out %p.\n", iface
, debugstr_guid(riid
), out
);
144 return IUnknown_QueryInterface(device
->outer_unknown
, riid
, out
);
147 static HRESULT WINAPI
d3d_device3_QueryInterface(IDirect3DDevice3
*iface
, REFIID riid
, void **out
)
149 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
151 TRACE("iface %p, riid %s, out %p.\n", iface
, debugstr_guid(riid
), out
);
153 return IUnknown_QueryInterface(device
->outer_unknown
, riid
, out
);
156 static HRESULT WINAPI
d3d_device2_QueryInterface(IDirect3DDevice2
*iface
, REFIID riid
, void **out
)
158 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
160 TRACE("iface %p, riid %s, out %p.\n", iface
, debugstr_guid(riid
), out
);
162 return IUnknown_QueryInterface(device
->outer_unknown
, riid
, out
);
165 static HRESULT WINAPI
d3d_device1_QueryInterface(IDirect3DDevice
*iface
, REFIID riid
, void **out
)
167 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
169 TRACE("iface %p, riid %s, out %p.\n", iface
, debugstr_guid(riid
), out
);
171 return IUnknown_QueryInterface(device
->outer_unknown
, riid
, out
);
174 static ULONG WINAPI
d3d_device_inner_AddRef(IUnknown
*iface
)
176 struct d3d_device
*device
= impl_from_IUnknown(iface
);
177 ULONG ref
= InterlockedIncrement(&device
->ref
);
179 TRACE("%p increasing refcount to %u.\n", device
, ref
);
184 static ULONG WINAPI
d3d_device7_AddRef(IDirect3DDevice7
*iface
)
186 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
188 TRACE("iface %p.\n", iface
);
190 return IUnknown_AddRef(device
->outer_unknown
);
193 static ULONG WINAPI
d3d_device3_AddRef(IDirect3DDevice3
*iface
)
195 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
197 TRACE("iface %p.\n", iface
);
199 return IUnknown_AddRef(device
->outer_unknown
);
202 static ULONG WINAPI
d3d_device2_AddRef(IDirect3DDevice2
*iface
)
204 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
206 TRACE("iface %p.\n", iface
);
208 return IUnknown_AddRef(device
->outer_unknown
);
211 static ULONG WINAPI
d3d_device1_AddRef(IDirect3DDevice
*iface
)
213 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
215 TRACE("iface %p.\n", iface
);
217 return IUnknown_AddRef(device
->outer_unknown
);
220 static ULONG WINAPI
d3d_device_inner_Release(IUnknown
*iface
)
222 struct d3d_device
*This
= impl_from_IUnknown(iface
);
223 ULONG ref
= InterlockedDecrement(&This
->ref
);
226 TRACE("%p decreasing refcount to %u.\n", This
, ref
);
228 /* This method doesn't destroy the wined3d device, because it's still in
229 * use for 2D rendering. IDirectDrawSurface7::Release will destroy the
230 * wined3d device when the render target is released. */
234 struct list
*vp_entry
, *vp_entry2
;
236 wined3d_mutex_lock();
238 /* There is no need to unset any resources here, wined3d will take
239 * care of that on uninit_3d(). */
241 if (This
->index_buffer
)
242 wined3d_buffer_decref(This
->index_buffer
);
243 if (This
->vertex_buffer
)
244 wined3d_buffer_decref(This
->vertex_buffer
);
246 wined3d_device_set_rendertarget_view(This
->wined3d_device
, 0, NULL
, FALSE
);
248 /* Release the wined3d device. This won't destroy it. */
249 if (!wined3d_device_decref(This
->wined3d_device
))
250 ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This
->wined3d_device
);
252 /* The texture handles should be unset by now, but there might be some bits
253 * missing in our reference counting(needs test). Do a sanity check. */
254 for (i
= 0; i
< This
->handle_table
.entry_count
; ++i
)
256 struct ddraw_handle_entry
*entry
= &This
->handle_table
.entries
[i
];
260 case DDRAW_HANDLE_FREE
:
263 case DDRAW_HANDLE_MATERIAL
:
265 struct d3d_material
*m
= entry
->object
;
266 FIXME("Material handle %#x (%p) not unset properly.\n", i
+ 1, m
);
271 case DDRAW_HANDLE_MATRIX
:
273 /* No FIXME here because this might happen because of sloppy applications. */
274 WARN("Leftover matrix handle %#x (%p), deleting.\n", i
+ 1, entry
->object
);
275 IDirect3DDevice_DeleteMatrix(&This
->IDirect3DDevice_iface
, i
+ 1);
279 case DDRAW_HANDLE_STATEBLOCK
:
281 /* No FIXME here because this might happen because of sloppy applications. */
282 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i
+ 1, entry
->object
);
283 IDirect3DDevice7_DeleteStateBlock(&This
->IDirect3DDevice7_iface
, i
+ 1);
287 case DDRAW_HANDLE_SURFACE
:
289 struct ddraw_surface
*surf
= entry
->object
;
290 FIXME("Texture handle %#x (%p) not unset properly.\n", i
+ 1, surf
);
296 FIXME("Handle %#x (%p) has unknown type %#x.\n", i
+ 1, entry
->object
, entry
->type
);
301 ddraw_handle_table_destroy(&This
->handle_table
);
303 LIST_FOR_EACH_SAFE(vp_entry
, vp_entry2
, &This
->viewport_list
)
305 struct d3d_viewport
*vp
= LIST_ENTRY(vp_entry
, struct d3d_viewport
, entry
);
306 IDirect3DDevice3_DeleteViewport(&This
->IDirect3DDevice3_iface
, &vp
->IDirect3DViewport3_iface
);
309 TRACE("Releasing render target %p.\n", This
->rt_iface
);
310 rt_iface
= This
->rt_iface
;
311 This
->rt_iface
= NULL
;
312 if (This
->version
!= 1)
313 IUnknown_Release(rt_iface
);
314 TRACE("Render target release done.\n");
316 /* Releasing the render target above may have released the last
317 * reference to the ddraw object. */
319 This
->ddraw
->d3ddevice
= NULL
;
321 /* Now free the structure */
323 wined3d_mutex_unlock();
330 static ULONG WINAPI
d3d_device7_Release(IDirect3DDevice7
*iface
)
332 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
334 TRACE("iface %p.\n", iface
);
336 return IUnknown_Release(device
->outer_unknown
);
339 static ULONG WINAPI
d3d_device3_Release(IDirect3DDevice3
*iface
)
341 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
343 TRACE("iface %p.\n", iface
);
345 return IUnknown_Release(device
->outer_unknown
);
348 static ULONG WINAPI
d3d_device2_Release(IDirect3DDevice2
*iface
)
350 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
352 TRACE("iface %p.\n", iface
);
354 return IUnknown_Release(device
->outer_unknown
);
357 static ULONG WINAPI
d3d_device1_Release(IDirect3DDevice
*iface
)
359 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
361 TRACE("iface %p.\n", iface
);
363 return IUnknown_Release(device
->outer_unknown
);
366 /*****************************************************************************
367 * IDirect3DDevice Methods
368 *****************************************************************************/
370 /*****************************************************************************
371 * IDirect3DDevice::Initialize
373 * Initializes a Direct3DDevice. This implementation is a no-op, as all
374 * initialization is done at create time.
376 * Exists in Version 1
379 * No idea what they mean, as the MSDN page is gone
383 *****************************************************************************/
384 static HRESULT WINAPI
d3d_device1_Initialize(IDirect3DDevice
*iface
,
385 IDirect3D
*d3d
, GUID
*guid
, D3DDEVICEDESC
*device_desc
)
387 /* It shouldn't be crucial, but print a FIXME, I'm interested if
388 * any game calls it and when. */
389 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
390 iface
, d3d
, debugstr_guid(guid
), device_desc
);
395 static HRESULT
d3d_device7_GetCaps(IDirect3DDevice7
*iface
, D3DDEVICEDESC7
*device_desc
)
397 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
399 TRACE("iface %p, device_desc %p.\n", iface
, device_desc
);
403 WARN("device_desc is NULL, returning DDERR_INVALIDPARAMS.\n");
404 return DDERR_INVALIDPARAMS
;
407 /* Call the same function used by IDirect3D, this saves code */
408 return ddraw_get_d3dcaps(device
->ddraw
, device_desc
);
411 static HRESULT WINAPI
d3d_device7_GetCaps_FPUSetup(IDirect3DDevice7
*iface
, D3DDEVICEDESC7
*desc
)
413 return d3d_device7_GetCaps(iface
, desc
);
416 static HRESULT WINAPI
d3d_device7_GetCaps_FPUPreserve(IDirect3DDevice7
*iface
, D3DDEVICEDESC7
*desc
)
421 old_fpucw
= d3d_fpu_setup();
422 hr
= d3d_device7_GetCaps(iface
, desc
);
423 set_fpu_control_word(old_fpucw
);
427 /*****************************************************************************
428 * IDirect3DDevice3::GetCaps
430 * Retrieves the capabilities of the hardware device and the emulation
431 * device. For Wine, hardware and emulation are the same (it's all HW).
433 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
436 * HWDesc: Structure to fill with the HW caps
437 * HelDesc: Structure to fill with the hardware emulation caps
441 * D3DERR_* if a problem occurs. See WineD3D
443 *****************************************************************************/
445 /* There are 3 versions of D3DDEVICEDESC. All 3 share the same name because
446 * Microsoft just expanded the existing structure without naming them
447 * D3DDEVICEDESC2 and D3DDEVICEDESC3. Which version is used have depends
448 * on the version of the DirectX SDK. DirectX 6+ and Wine use the latest
449 * one with 252 bytes.
451 * All 3 versions are allowed as parameters and only the specified amount of
454 * Note that Direct3D7 and earlier are not available in native Win64
455 * ddraw.dll builds, so possible size differences between 32 bit and
456 * 64 bit are a non-issue.
458 static inline BOOL
check_d3ddevicedesc_size(DWORD size
)
460 if (size
== FIELD_OFFSET(D3DDEVICEDESC
, dwMinTextureWidth
) /* 172 */
461 || size
== FIELD_OFFSET(D3DDEVICEDESC
, dwMaxTextureRepeat
) /* 204 */
462 || size
== sizeof(D3DDEVICEDESC
) /* 252 */) return TRUE
;
466 static HRESULT WINAPI
d3d_device3_GetCaps(IDirect3DDevice3
*iface
,
467 D3DDEVICEDESC
*HWDesc
, D3DDEVICEDESC
*HelDesc
)
469 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
470 D3DDEVICEDESC7 desc7
;
474 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface
, HWDesc
, HelDesc
);
478 WARN("HWDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
479 return DDERR_INVALIDPARAMS
;
481 if (!check_d3ddevicedesc_size(HWDesc
->dwSize
))
483 WARN("HWDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HWDesc
->dwSize
);
484 return DDERR_INVALIDPARAMS
;
488 WARN("HelDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
489 return DDERR_INVALIDPARAMS
;
491 if (!check_d3ddevicedesc_size(HelDesc
->dwSize
))
493 WARN("HelDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HelDesc
->dwSize
);
494 return DDERR_INVALIDPARAMS
;
497 if (FAILED(hr
= ddraw_get_d3dcaps(device
->ddraw
, &desc7
)))
500 ddraw_d3dcaps1_from_7(&desc1
, &desc7
);
501 DD_STRUCT_COPY_BYSIZE(HWDesc
, &desc1
);
502 DD_STRUCT_COPY_BYSIZE(HelDesc
, &desc1
);
506 static HRESULT WINAPI
d3d_device2_GetCaps(IDirect3DDevice2
*iface
,
507 D3DDEVICEDESC
*hw_desc
, D3DDEVICEDESC
*hel_desc
)
509 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
511 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface
, hw_desc
, hel_desc
);
513 return d3d_device3_GetCaps(&device
->IDirect3DDevice3_iface
, hw_desc
, hel_desc
);
516 static HRESULT WINAPI
d3d_device1_GetCaps(IDirect3DDevice
*iface
,
517 D3DDEVICEDESC
*hw_desc
, D3DDEVICEDESC
*hel_desc
)
519 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
521 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface
, hw_desc
, hel_desc
);
523 return d3d_device3_GetCaps(&device
->IDirect3DDevice3_iface
, hw_desc
, hel_desc
);
526 /*****************************************************************************
527 * IDirect3DDevice2::SwapTextureHandles
529 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
532 * Tex1, Tex2: The 2 Textures to swap
537 *****************************************************************************/
538 static HRESULT WINAPI
d3d_device2_SwapTextureHandles(IDirect3DDevice2
*iface
,
539 IDirect3DTexture2
*tex1
, IDirect3DTexture2
*tex2
)
541 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
542 struct ddraw_surface
*surf1
= unsafe_impl_from_IDirect3DTexture2(tex1
);
543 struct ddraw_surface
*surf2
= unsafe_impl_from_IDirect3DTexture2(tex2
);
546 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface
, tex1
, tex2
);
548 wined3d_mutex_lock();
550 h1
= surf1
->Handle
- 1;
551 h2
= surf2
->Handle
- 1;
552 device
->handle_table
.entries
[h1
].object
= surf2
;
553 device
->handle_table
.entries
[h2
].object
= surf1
;
554 surf2
->Handle
= h1
+ 1;
555 surf1
->Handle
= h2
+ 1;
557 wined3d_mutex_unlock();
562 static HRESULT WINAPI
d3d_device1_SwapTextureHandles(IDirect3DDevice
*iface
,
563 IDirect3DTexture
*tex1
, IDirect3DTexture
*tex2
)
565 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
566 struct ddraw_surface
*surf1
= unsafe_impl_from_IDirect3DTexture(tex1
);
567 struct ddraw_surface
*surf2
= unsafe_impl_from_IDirect3DTexture(tex2
);
568 IDirect3DTexture2
*t1
= surf1
? &surf1
->IDirect3DTexture2_iface
: NULL
;
569 IDirect3DTexture2
*t2
= surf2
? &surf2
->IDirect3DTexture2_iface
: NULL
;
571 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface
, tex1
, tex2
);
573 return d3d_device2_SwapTextureHandles(&device
->IDirect3DDevice2_iface
, t1
, t2
);
576 /*****************************************************************************
577 * IDirect3DDevice3::GetStats
579 * This method seems to retrieve some stats from the device.
580 * The MSDN documentation doesn't exist any more, but the D3DSTATS
581 * structure suggests that the amount of drawn primitives and processed
582 * vertices is returned.
584 * Exists in Version 1, 2 and 3
587 * Stats: Pointer to a D3DSTATS structure to be filled
591 * DDERR_INVALIDPARAMS if Stats == NULL
593 *****************************************************************************/
594 static HRESULT WINAPI
d3d_device3_GetStats(IDirect3DDevice3
*iface
, D3DSTATS
*Stats
)
596 FIXME("iface %p, stats %p stub!\n", iface
, Stats
);
599 return DDERR_INVALIDPARAMS
;
601 /* Fill the Stats with 0 */
602 Stats
->dwTrianglesDrawn
= 0;
603 Stats
->dwLinesDrawn
= 0;
604 Stats
->dwPointsDrawn
= 0;
605 Stats
->dwSpansDrawn
= 0;
606 Stats
->dwVerticesProcessed
= 0;
611 static HRESULT WINAPI
d3d_device2_GetStats(IDirect3DDevice2
*iface
, D3DSTATS
*stats
)
613 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
615 TRACE("iface %p, stats %p.\n", iface
, stats
);
617 return d3d_device3_GetStats(&device
->IDirect3DDevice3_iface
, stats
);
620 static HRESULT WINAPI
d3d_device1_GetStats(IDirect3DDevice
*iface
, D3DSTATS
*stats
)
622 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
624 TRACE("iface %p, stats %p.\n", iface
, stats
);
626 return d3d_device3_GetStats(&device
->IDirect3DDevice3_iface
, stats
);
629 /*****************************************************************************
630 * IDirect3DDevice::CreateExecuteBuffer
632 * Creates an IDirect3DExecuteBuffer, used for rendering with a
638 * Desc: Buffer description
639 * ExecuteBuffer: Address to return the Interface pointer at
640 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
644 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
645 * DDERR_OUTOFMEMORY if we ran out of memory
648 *****************************************************************************/
649 static HRESULT WINAPI
d3d_device1_CreateExecuteBuffer(IDirect3DDevice
*iface
,
650 D3DEXECUTEBUFFERDESC
*buffer_desc
, IDirect3DExecuteBuffer
**ExecuteBuffer
, IUnknown
*outer_unknown
)
652 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
653 struct d3d_execute_buffer
*object
;
656 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
657 iface
, buffer_desc
, ExecuteBuffer
, outer_unknown
);
660 return CLASS_E_NOAGGREGATION
;
662 /* Allocate the new Execute Buffer */
663 if (!(object
= heap_alloc_zero(sizeof(*object
))))
665 ERR("Failed to allocate execute buffer memory.\n");
666 return DDERR_OUTOFMEMORY
;
669 hr
= d3d_execute_buffer_init(object
, device
, buffer_desc
);
672 WARN("Failed to initialize execute buffer, hr %#x.\n", hr
);
677 *ExecuteBuffer
= &object
->IDirect3DExecuteBuffer_iface
;
679 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer
, object
);
684 /*****************************************************************************
685 * IDirect3DDevice::Execute
687 * Executes all the stuff in an execute buffer.
690 * ExecuteBuffer: The buffer to execute
691 * Viewport: The viewport used for rendering
695 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
698 *****************************************************************************/
699 static HRESULT WINAPI
d3d_device1_Execute(IDirect3DDevice
*iface
,
700 IDirect3DExecuteBuffer
*ExecuteBuffer
, IDirect3DViewport
*viewport
, DWORD flags
)
702 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
703 struct d3d_execute_buffer
*buffer
= unsafe_impl_from_IDirect3DExecuteBuffer(ExecuteBuffer
);
704 struct d3d_viewport
*viewport_impl
= unsafe_impl_from_IDirect3DViewport(viewport
);
707 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface
, ExecuteBuffer
, viewport
, flags
);
710 return DDERR_INVALIDPARAMS
;
712 if (FAILED(hr
= IDirect3DDevice3_SetCurrentViewport
713 (&device
->IDirect3DDevice3_iface
, &viewport_impl
->IDirect3DViewport3_iface
)))
717 wined3d_mutex_lock();
718 hr
= d3d_execute_buffer_execute(buffer
, device
);
719 wined3d_mutex_unlock();
724 /*****************************************************************************
725 * IDirect3DDevice3::AddViewport
727 * Add a Direct3DViewport to the device's viewport list. These viewports
728 * are wrapped to IDirect3DDevice7 viewports in viewport.c
730 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
731 * are the same interfaces.
734 * Viewport: The viewport to add
737 * DDERR_INVALIDPARAMS if Viewport == NULL
740 *****************************************************************************/
741 static HRESULT WINAPI
d3d_device3_AddViewport(IDirect3DDevice3
*iface
, IDirect3DViewport3
*viewport
)
743 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
744 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport3(viewport
);
746 TRACE("iface %p, viewport %p.\n", iface
, viewport
);
750 return DDERR_INVALIDPARAMS
;
752 wined3d_mutex_lock();
753 IDirect3DViewport3_AddRef(viewport
);
754 list_add_head(&device
->viewport_list
, &vp
->entry
);
755 /* Viewport must be usable for Clear() after AddViewport, so set active_device here. */
756 vp
->active_device
= device
;
757 wined3d_mutex_unlock();
762 static HRESULT WINAPI
d3d_device2_AddViewport(IDirect3DDevice2
*iface
,
763 IDirect3DViewport2
*viewport
)
765 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
766 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport2(viewport
);
768 TRACE("iface %p, viewport %p.\n", iface
, viewport
);
770 return d3d_device3_AddViewport(&device
->IDirect3DDevice3_iface
, &vp
->IDirect3DViewport3_iface
);
773 static HRESULT WINAPI
d3d_device1_AddViewport(IDirect3DDevice
*iface
, IDirect3DViewport
*viewport
)
775 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
776 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport(viewport
);
778 TRACE("iface %p, viewport %p.\n", iface
, viewport
);
780 return d3d_device3_AddViewport(&device
->IDirect3DDevice3_iface
, &vp
->IDirect3DViewport3_iface
);
783 /*****************************************************************************
784 * IDirect3DDevice3::DeleteViewport
786 * Deletes a Direct3DViewport from the device's viewport list.
788 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
792 * Viewport: The viewport to delete
796 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
798 *****************************************************************************/
799 static HRESULT WINAPI
d3d_device3_DeleteViewport(IDirect3DDevice3
*iface
, IDirect3DViewport3
*viewport
)
801 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
802 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport3(viewport
);
804 TRACE("iface %p, viewport %p.\n", iface
, viewport
);
808 WARN("NULL viewport, returning DDERR_INVALIDPARAMS\n");
809 return DDERR_INVALIDPARAMS
;
812 wined3d_mutex_lock();
814 if (vp
->active_device
!= device
)
816 WARN("Viewport %p active device is %p.\n", vp
, vp
->active_device
);
817 wined3d_mutex_unlock();
818 return DDERR_INVALIDPARAMS
;
821 if (device
->current_viewport
== vp
)
823 TRACE("Deleting current viewport, unsetting and releasing.\n");
825 viewport_deactivate(vp
);
826 IDirect3DViewport3_Release(viewport
);
827 device
->current_viewport
= NULL
;
830 vp
->active_device
= NULL
;
831 list_remove(&vp
->entry
);
833 IDirect3DViewport3_Release(viewport
);
835 wined3d_mutex_unlock();
840 static HRESULT WINAPI
d3d_device2_DeleteViewport(IDirect3DDevice2
*iface
, IDirect3DViewport2
*viewport
)
842 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
843 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport2(viewport
);
845 TRACE("iface %p, viewport %p.\n", iface
, viewport
);
847 return d3d_device3_DeleteViewport(&device
->IDirect3DDevice3_iface
,
848 vp
? &vp
->IDirect3DViewport3_iface
: NULL
);
851 static HRESULT WINAPI
d3d_device1_DeleteViewport(IDirect3DDevice
*iface
, IDirect3DViewport
*viewport
)
853 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
854 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport(viewport
);
856 TRACE("iface %p, viewport %p.\n", iface
, viewport
);
858 return d3d_device3_DeleteViewport(&device
->IDirect3DDevice3_iface
,
859 vp
? &vp
->IDirect3DViewport3_iface
: NULL
);
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
872 * Viewport: Viewport to use for beginning the search
873 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
877 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
879 *****************************************************************************/
880 static HRESULT WINAPI
d3d_device3_NextViewport(IDirect3DDevice3
*iface
,
881 IDirect3DViewport3
*Viewport3
, IDirect3DViewport3
**lplpDirect3DViewport3
, DWORD flags
)
883 struct d3d_device
*This
= impl_from_IDirect3DDevice3(iface
);
884 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport3(Viewport3
);
885 struct d3d_viewport
*next
;
888 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
889 iface
, Viewport3
, lplpDirect3DViewport3
, flags
);
893 *lplpDirect3DViewport3
= NULL
;
894 return DDERR_INVALIDPARAMS
;
898 wined3d_mutex_lock();
902 entry
= list_next(&This
->viewport_list
, &vp
->entry
);
906 entry
= list_head(&This
->viewport_list
);
910 entry
= list_tail(&This
->viewport_list
);
914 WARN("Invalid flags %#x.\n", flags
);
915 *lplpDirect3DViewport3
= NULL
;
916 wined3d_mutex_unlock();
917 return DDERR_INVALIDPARAMS
;
922 next
= LIST_ENTRY(entry
, struct d3d_viewport
, entry
);
923 *lplpDirect3DViewport3
= &next
->IDirect3DViewport3_iface
;
926 *lplpDirect3DViewport3
= NULL
;
928 wined3d_mutex_unlock();
933 static HRESULT WINAPI
d3d_device2_NextViewport(IDirect3DDevice2
*iface
,
934 IDirect3DViewport2
*viewport
, IDirect3DViewport2
**next
, DWORD flags
)
936 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
937 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport2(viewport
);
938 IDirect3DViewport3
*res
;
941 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
942 iface
, viewport
, next
, flags
);
944 hr
= d3d_device3_NextViewport(&device
->IDirect3DDevice3_iface
,
945 &vp
->IDirect3DViewport3_iface
, &res
, flags
);
946 *next
= (IDirect3DViewport2
*)res
;
950 static HRESULT WINAPI
d3d_device1_NextViewport(IDirect3DDevice
*iface
,
951 IDirect3DViewport
*viewport
, IDirect3DViewport
**next
, DWORD flags
)
953 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
954 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport(viewport
);
955 IDirect3DViewport3
*res
;
958 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
959 iface
, viewport
, next
, flags
);
961 hr
= d3d_device3_NextViewport(&device
->IDirect3DDevice3_iface
,
962 &vp
->IDirect3DViewport3_iface
, &res
, flags
);
963 *next
= (IDirect3DViewport
*)res
;
967 /*****************************************************************************
968 * IDirect3DDevice::Pick
970 * Executes an execute buffer without performing rendering. Instead, a
971 * list of primitives that intersect with (x1,y1) of the passed rectangle
972 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
978 * ExecuteBuffer: Buffer to execute
979 * Viewport: Viewport to use for execution
980 * Flags: None are defined, according to the SDK
981 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
982 * x2 and y2 are ignored.
985 * D3D_OK because it's a stub
987 *****************************************************************************/
988 static HRESULT WINAPI
d3d_device1_Pick(IDirect3DDevice
*iface
, IDirect3DExecuteBuffer
*buffer
,
989 IDirect3DViewport
*viewport
, DWORD flags
, D3DRECT
*rect
)
991 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
992 iface
, buffer
, viewport
, flags
, wine_dbgstr_rect((RECT
*)rect
));
997 /*****************************************************************************
998 * IDirect3DDevice::GetPickRecords
1000 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1005 * Count: Pointer to a DWORD containing the numbers of pick records to
1007 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1010 * D3D_OK, because it's a stub
1012 *****************************************************************************/
1013 static HRESULT WINAPI
d3d_device1_GetPickRecords(IDirect3DDevice
*iface
,
1014 DWORD
*count
, D3DPICKRECORD
*records
)
1016 FIXME("iface %p, count %p, records %p stub!\n", iface
, count
, records
);
1021 /*****************************************************************************
1022 * IDirect3DDevice7::EnumTextureformats
1024 * Enumerates the supported texture formats. It checks against a list of all possible
1025 * formats to see if WineD3D supports it. If so, then it is passed to the app.
1027 * This is for Version 7 and 3, older versions have a different
1028 * callback function and their own implementation
1031 * Callback: Callback to call for each enumerated format
1032 * Arg: Argument to pass to the callback
1036 * DDERR_INVALIDPARAMS if Callback == NULL
1038 *****************************************************************************/
1039 static HRESULT
d3d_device7_EnumTextureFormats(IDirect3DDevice7
*iface
,
1040 LPD3DENUMPIXELFORMATSCALLBACK callback
, void *context
)
1042 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
1043 struct wined3d_display_mode mode
;
1047 static const enum wined3d_format_id FormatList
[] =
1050 WINED3DFMT_B5G5R5X1_UNORM
,
1051 WINED3DFMT_B5G5R5A1_UNORM
,
1052 WINED3DFMT_B4G4R4A4_UNORM
,
1053 WINED3DFMT_B5G6R5_UNORM
,
1055 WINED3DFMT_B8G8R8X8_UNORM
,
1056 WINED3DFMT_B8G8R8A8_UNORM
,
1058 WINED3DFMT_B2G3R3_UNORM
,
1068 static const enum wined3d_format_id BumpFormatList
[] =
1070 WINED3DFMT_R8G8_SNORM
,
1071 WINED3DFMT_R5G5_SNORM_L6_UNORM
,
1072 WINED3DFMT_R8G8_SNORM_L8X8_UNORM
,
1073 WINED3DFMT_R10G11B11_SNORM
,
1074 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1077 TRACE("iface %p, callback %p, context %p.\n", iface
, callback
, context
);
1080 return DDERR_INVALIDPARAMS
;
1082 wined3d_mutex_lock();
1084 memset(&mode
, 0, sizeof(mode
));
1085 if (FAILED(hr
= wined3d_get_adapter_display_mode(device
->ddraw
->wined3d
, WINED3DADAPTER_DEFAULT
, &mode
, NULL
)))
1087 wined3d_mutex_unlock();
1088 WARN("Cannot get the current adapter format\n");
1092 for (i
= 0; i
< ARRAY_SIZE(FormatList
); ++i
)
1094 if (wined3d_check_device_format(device
->ddraw
->wined3d
, WINED3DADAPTER_DEFAULT
, WINED3D_DEVICE_TYPE_HAL
,
1095 mode
.format_id
, 0, WINED3D_BIND_SHADER_RESOURCE
, WINED3D_RTYPE_TEXTURE_2D
, FormatList
[i
]) == D3D_OK
)
1097 DDPIXELFORMAT pformat
;
1099 memset(&pformat
, 0, sizeof(pformat
));
1100 pformat
.dwSize
= sizeof(pformat
);
1101 ddrawformat_from_wined3dformat(&pformat
, FormatList
[i
]);
1103 TRACE("Enumerating WineD3DFormat %d\n", FormatList
[i
]);
1104 hr
= callback(&pformat
, context
);
1105 if(hr
!= DDENUMRET_OK
)
1107 TRACE("Format enumeration cancelled by application\n");
1108 wined3d_mutex_unlock();
1114 for (i
= 0; i
< ARRAY_SIZE(BumpFormatList
); ++i
)
1116 if (wined3d_check_device_format(device
->ddraw
->wined3d
, WINED3DADAPTER_DEFAULT
,
1117 WINED3D_DEVICE_TYPE_HAL
, mode
.format_id
, WINED3DUSAGE_QUERY_LEGACYBUMPMAP
,
1118 WINED3D_BIND_SHADER_RESOURCE
, WINED3D_RTYPE_TEXTURE_2D
, BumpFormatList
[i
]) == D3D_OK
)
1120 DDPIXELFORMAT pformat
;
1122 memset(&pformat
, 0, sizeof(pformat
));
1123 pformat
.dwSize
= sizeof(pformat
);
1124 ddrawformat_from_wined3dformat(&pformat
, BumpFormatList
[i
]);
1126 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList
[i
]);
1127 hr
= callback(&pformat
, context
);
1128 if(hr
!= DDENUMRET_OK
)
1130 TRACE("Format enumeration cancelled by application\n");
1131 wined3d_mutex_unlock();
1136 TRACE("End of enumeration\n");
1137 wined3d_mutex_unlock();
1142 static HRESULT WINAPI
d3d_device7_EnumTextureFormats_FPUSetup(IDirect3DDevice7
*iface
,
1143 LPD3DENUMPIXELFORMATSCALLBACK callback
, void *context
)
1145 return d3d_device7_EnumTextureFormats(iface
, callback
, context
);
1148 static HRESULT WINAPI
d3d_device7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7
*iface
,
1149 LPD3DENUMPIXELFORMATSCALLBACK callback
, void *context
)
1154 old_fpucw
= d3d_fpu_setup();
1155 hr
= d3d_device7_EnumTextureFormats(iface
, callback
, context
);
1156 set_fpu_control_word(old_fpucw
);
1161 static HRESULT WINAPI
d3d_device3_EnumTextureFormats(IDirect3DDevice3
*iface
,
1162 LPD3DENUMPIXELFORMATSCALLBACK callback
, void *context
)
1164 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
1166 TRACE("iface %p, callback %p, context %p.\n", iface
, callback
, context
);
1168 return IDirect3DDevice7_EnumTextureFormats(&device
->IDirect3DDevice7_iface
, callback
, context
);
1171 /*****************************************************************************
1172 * IDirect3DDevice2::EnumTextureformats
1174 * EnumTextureFormats for Version 1 and 2, see
1175 * IDirect3DDevice7::EnumTextureFormats for a more detailed description.
1177 * This version has a different callback and does not enumerate FourCC
1180 *****************************************************************************/
1181 static HRESULT WINAPI
d3d_device2_EnumTextureFormats(IDirect3DDevice2
*iface
,
1182 LPD3DENUMTEXTUREFORMATSCALLBACK callback
, void *context
)
1184 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
1185 struct wined3d_display_mode mode
;
1189 static const enum wined3d_format_id FormatList
[] =
1192 WINED3DFMT_B5G5R5X1_UNORM
,
1193 WINED3DFMT_B5G5R5A1_UNORM
,
1194 WINED3DFMT_B4G4R4A4_UNORM
,
1195 WINED3DFMT_B5G6R5_UNORM
,
1197 WINED3DFMT_B8G8R8X8_UNORM
,
1198 WINED3DFMT_B8G8R8A8_UNORM
,
1200 WINED3DFMT_B2G3R3_UNORM
,
1202 /* FOURCC codes - Not in this version*/
1205 TRACE("iface %p, callback %p, context %p.\n", iface
, callback
, context
);
1208 return DDERR_INVALIDPARAMS
;
1210 wined3d_mutex_lock();
1212 memset(&mode
, 0, sizeof(mode
));
1213 if (FAILED(hr
= wined3d_get_adapter_display_mode(device
->ddraw
->wined3d
, WINED3DADAPTER_DEFAULT
, &mode
, NULL
)))
1215 wined3d_mutex_unlock();
1216 WARN("Cannot get the current adapter format\n");
1220 for (i
= 0; i
< ARRAY_SIZE(FormatList
); ++i
)
1222 if (wined3d_check_device_format(device
->ddraw
->wined3d
, WINED3DADAPTER_DEFAULT
, WINED3D_DEVICE_TYPE_HAL
,
1223 mode
.format_id
, 0, WINED3D_BIND_SHADER_RESOURCE
, WINED3D_RTYPE_TEXTURE_2D
, FormatList
[i
]) == D3D_OK
)
1225 DDSURFACEDESC sdesc
;
1227 memset(&sdesc
, 0, sizeof(sdesc
));
1228 sdesc
.dwSize
= sizeof(sdesc
);
1229 sdesc
.dwFlags
= DDSD_PIXELFORMAT
| DDSD_CAPS
;
1230 sdesc
.ddsCaps
.dwCaps
= DDSCAPS_TEXTURE
;
1231 sdesc
.ddpfPixelFormat
.dwSize
= sizeof(sdesc
.ddpfPixelFormat
);
1232 ddrawformat_from_wined3dformat(&sdesc
.ddpfPixelFormat
, FormatList
[i
]);
1234 TRACE("Enumerating WineD3DFormat %d\n", FormatList
[i
]);
1235 hr
= callback(&sdesc
, context
);
1236 if(hr
!= DDENUMRET_OK
)
1238 TRACE("Format enumeration cancelled by application\n");
1239 wined3d_mutex_unlock();
1244 TRACE("End of enumeration\n");
1245 wined3d_mutex_unlock();
1250 static HRESULT WINAPI
d3d_device1_EnumTextureFormats(IDirect3DDevice
*iface
,
1251 LPD3DENUMTEXTUREFORMATSCALLBACK callback
, void *context
)
1253 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
1255 TRACE("iface %p, callback %p, context %p.\n", iface
, callback
, context
);
1257 return d3d_device2_EnumTextureFormats(&device
->IDirect3DDevice2_iface
, callback
, context
);
1260 /*****************************************************************************
1261 * IDirect3DDevice::CreateMatrix
1263 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1264 * allocated for the handle.
1269 * D3DMatHandle: Address to return the handle at
1273 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1275 *****************************************************************************/
1276 static HRESULT WINAPI
d3d_device1_CreateMatrix(IDirect3DDevice
*iface
, D3DMATRIXHANDLE
*D3DMatHandle
)
1278 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
1282 TRACE("iface %p, matrix_handle %p.\n", iface
, D3DMatHandle
);
1285 return DDERR_INVALIDPARAMS
;
1287 if (!(matrix
= heap_alloc_zero(sizeof(*matrix
))))
1289 ERR("Out of memory when allocating a D3DMATRIX\n");
1290 return DDERR_OUTOFMEMORY
;
1293 wined3d_mutex_lock();
1295 h
= ddraw_allocate_handle(&device
->handle_table
, matrix
, DDRAW_HANDLE_MATRIX
);
1296 if (h
== DDRAW_INVALID_HANDLE
)
1298 ERR("Failed to allocate a matrix handle.\n");
1300 wined3d_mutex_unlock();
1301 return DDERR_OUTOFMEMORY
;
1304 *D3DMatHandle
= h
+ 1;
1306 TRACE(" returning matrix handle %d\n", *D3DMatHandle
);
1308 wined3d_mutex_unlock();
1313 /*****************************************************************************
1314 * IDirect3DDevice::SetMatrix
1316 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1317 * allocated for the handle
1322 * D3DMatHandle: Handle to set the matrix to
1323 * D3DMatrix: Matrix to set
1327 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1330 *****************************************************************************/
1331 static HRESULT WINAPI
d3d_device1_SetMatrix(IDirect3DDevice
*iface
,
1332 D3DMATRIXHANDLE D3DMatHandle
, D3DMATRIX
*D3DMatrix
)
1334 struct d3d_device
*This
= impl_from_IDirect3DDevice(iface
);
1337 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface
, D3DMatHandle
, D3DMatrix
);
1339 if (!D3DMatrix
) return DDERR_INVALIDPARAMS
;
1341 wined3d_mutex_lock();
1343 m
= ddraw_get_object(&This
->handle_table
, D3DMatHandle
- 1, DDRAW_HANDLE_MATRIX
);
1346 WARN("Invalid matrix handle.\n");
1347 wined3d_mutex_unlock();
1348 return DDERR_INVALIDPARAMS
;
1351 if (TRACE_ON(ddraw
))
1352 dump_D3DMATRIX(D3DMatrix
);
1356 if (D3DMatHandle
== This
->world
)
1357 wined3d_device_set_transform(This
->wined3d_device
,
1358 WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix
*)D3DMatrix
);
1360 if (D3DMatHandle
== This
->view
)
1361 wined3d_device_set_transform(This
->wined3d_device
,
1362 WINED3D_TS_VIEW
, (struct wined3d_matrix
*)D3DMatrix
);
1364 if (D3DMatHandle
== This
->proj
)
1365 wined3d_device_set_transform(This
->wined3d_device
,
1366 WINED3D_TS_PROJECTION
, (struct wined3d_matrix
*)D3DMatrix
);
1368 wined3d_mutex_unlock();
1373 /*****************************************************************************
1374 * IDirect3DDevice::GetMatrix
1376 * Returns the content of a D3DMATRIX handle
1381 * D3DMatHandle: Matrix handle to read the content from
1382 * D3DMatrix: Address to store the content at
1386 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1388 *****************************************************************************/
1389 static HRESULT WINAPI
d3d_device1_GetMatrix(IDirect3DDevice
*iface
,
1390 D3DMATRIXHANDLE D3DMatHandle
, D3DMATRIX
*D3DMatrix
)
1392 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
1395 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface
, D3DMatHandle
, D3DMatrix
);
1397 if (!D3DMatrix
) return DDERR_INVALIDPARAMS
;
1399 wined3d_mutex_lock();
1401 m
= ddraw_get_object(&device
->handle_table
, D3DMatHandle
- 1, DDRAW_HANDLE_MATRIX
);
1404 WARN("Invalid matrix handle.\n");
1405 wined3d_mutex_unlock();
1406 return DDERR_INVALIDPARAMS
;
1411 wined3d_mutex_unlock();
1416 /*****************************************************************************
1417 * IDirect3DDevice::DeleteMatrix
1419 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1424 * D3DMatHandle: Handle to destroy
1428 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1430 *****************************************************************************/
1431 static HRESULT WINAPI
d3d_device1_DeleteMatrix(IDirect3DDevice
*iface
, D3DMATRIXHANDLE D3DMatHandle
)
1433 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
1436 TRACE("iface %p, matrix_handle %#x.\n", iface
, D3DMatHandle
);
1438 wined3d_mutex_lock();
1440 m
= ddraw_free_handle(&device
->handle_table
, D3DMatHandle
- 1, DDRAW_HANDLE_MATRIX
);
1443 WARN("Invalid matrix handle.\n");
1444 wined3d_mutex_unlock();
1445 return DDERR_INVALIDPARAMS
;
1448 wined3d_mutex_unlock();
1455 /*****************************************************************************
1456 * IDirect3DDevice7::BeginScene
1458 * This method must be called before any rendering is performed.
1459 * IDirect3DDevice::EndScene has to be called after the scene is complete
1461 * Version 1, 2, 3 and 7
1464 * D3D_OK on success,
1465 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1468 *****************************************************************************/
1469 static HRESULT
d3d_device7_BeginScene(IDirect3DDevice7
*iface
)
1471 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
1474 TRACE("iface %p.\n", iface
);
1476 wined3d_mutex_lock();
1477 hr
= wined3d_device_begin_scene(device
->wined3d_device
);
1478 wined3d_mutex_unlock();
1480 if(hr
== WINED3D_OK
) return D3D_OK
;
1481 else return D3DERR_SCENE_IN_SCENE
; /* TODO: Other possible causes of failure */
1484 static HRESULT WINAPI
d3d_device7_BeginScene_FPUSetup(IDirect3DDevice7
*iface
)
1486 return d3d_device7_BeginScene(iface
);
1489 static HRESULT WINAPI
d3d_device7_BeginScene_FPUPreserve(IDirect3DDevice7
*iface
)
1494 old_fpucw
= d3d_fpu_setup();
1495 hr
= d3d_device7_BeginScene(iface
);
1496 set_fpu_control_word(old_fpucw
);
1501 static HRESULT WINAPI
d3d_device3_BeginScene(IDirect3DDevice3
*iface
)
1503 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
1505 TRACE("iface %p.\n", iface
);
1507 return IDirect3DDevice7_BeginScene(&device
->IDirect3DDevice7_iface
);
1510 static HRESULT WINAPI
d3d_device2_BeginScene(IDirect3DDevice2
*iface
)
1512 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
1514 TRACE("iface %p.\n", iface
);
1516 return IDirect3DDevice7_BeginScene(&device
->IDirect3DDevice7_iface
);
1519 static HRESULT WINAPI
d3d_device1_BeginScene(IDirect3DDevice
*iface
)
1521 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
1523 TRACE("iface %p.\n", iface
);
1525 return IDirect3DDevice7_BeginScene(&device
->IDirect3DDevice7_iface
);
1528 /*****************************************************************************
1529 * IDirect3DDevice7::EndScene
1531 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1532 * This method must be called after rendering is finished.
1534 * Version 1, 2, 3 and 7
1537 * D3D_OK on success,
1538 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1539 * that only if the scene was already ended.
1541 *****************************************************************************/
1542 static HRESULT
d3d_device7_EndScene(IDirect3DDevice7
*iface
)
1544 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
1547 TRACE("iface %p.\n", iface
);
1549 wined3d_mutex_lock();
1550 hr
= wined3d_device_end_scene(device
->wined3d_device
);
1551 wined3d_mutex_unlock();
1553 if(hr
== WINED3D_OK
) return D3D_OK
;
1554 else return D3DERR_SCENE_NOT_IN_SCENE
;
1557 static HRESULT WINAPI DECLSPEC_HOTPATCH
d3d_device7_EndScene_FPUSetup(IDirect3DDevice7
*iface
)
1559 return d3d_device7_EndScene(iface
);
1562 static HRESULT WINAPI DECLSPEC_HOTPATCH
d3d_device7_EndScene_FPUPreserve(IDirect3DDevice7
*iface
)
1567 old_fpucw
= d3d_fpu_setup();
1568 hr
= d3d_device7_EndScene(iface
);
1569 set_fpu_control_word(old_fpucw
);
1574 static HRESULT WINAPI DECLSPEC_HOTPATCH
d3d_device3_EndScene(IDirect3DDevice3
*iface
)
1576 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
1578 TRACE("iface %p.\n", iface
);
1580 return IDirect3DDevice7_EndScene(&device
->IDirect3DDevice7_iface
);
1583 static HRESULT WINAPI DECLSPEC_HOTPATCH
d3d_device2_EndScene(IDirect3DDevice2
*iface
)
1585 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
1587 TRACE("iface %p.\n", iface
);
1589 return IDirect3DDevice7_EndScene(&device
->IDirect3DDevice7_iface
);
1592 static HRESULT WINAPI DECLSPEC_HOTPATCH
d3d_device1_EndScene(IDirect3DDevice
*iface
)
1594 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
1596 TRACE("iface %p.\n", iface
);
1598 return IDirect3DDevice7_EndScene(&device
->IDirect3DDevice7_iface
);
1601 /*****************************************************************************
1602 * IDirect3DDevice7::GetDirect3D
1604 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1608 * Direct3D7: Address to store the interface pointer at
1612 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1614 *****************************************************************************/
1615 static HRESULT WINAPI
d3d_device7_GetDirect3D(IDirect3DDevice7
*iface
, IDirect3D7
**d3d
)
1617 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
1619 TRACE("iface %p, d3d %p.\n", iface
, d3d
);
1622 return DDERR_INVALIDPARAMS
;
1624 *d3d
= &device
->ddraw
->IDirect3D7_iface
;
1625 IDirect3D7_AddRef(*d3d
);
1627 TRACE("Returning interface %p.\n", *d3d
);
1631 static HRESULT WINAPI
d3d_device3_GetDirect3D(IDirect3DDevice3
*iface
, IDirect3D3
**d3d
)
1633 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
1635 TRACE("iface %p, d3d %p.\n", iface
, d3d
);
1638 return DDERR_INVALIDPARAMS
;
1640 *d3d
= &device
->ddraw
->IDirect3D3_iface
;
1641 IDirect3D3_AddRef(*d3d
);
1643 TRACE("Returning interface %p.\n", *d3d
);
1647 static HRESULT WINAPI
d3d_device2_GetDirect3D(IDirect3DDevice2
*iface
, IDirect3D2
**d3d
)
1649 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
1651 TRACE("iface %p, d3d %p.\n", iface
, d3d
);
1654 return DDERR_INVALIDPARAMS
;
1656 *d3d
= &device
->ddraw
->IDirect3D2_iface
;
1657 IDirect3D2_AddRef(*d3d
);
1659 TRACE("Returning interface %p.\n", *d3d
);
1663 static HRESULT WINAPI
d3d_device1_GetDirect3D(IDirect3DDevice
*iface
, IDirect3D
**d3d
)
1665 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
1667 TRACE("iface %p, d3d %p.\n", iface
, d3d
);
1670 return DDERR_INVALIDPARAMS
;
1672 *d3d
= &device
->ddraw
->IDirect3D_iface
;
1673 IDirect3D_AddRef(*d3d
);
1675 TRACE("Returning interface %p.\n", *d3d
);
1679 /*****************************************************************************
1680 * IDirect3DDevice3::SetCurrentViewport
1682 * Sets a Direct3DViewport as the current viewport.
1683 * For the thunks note that all viewport interface versions are equal
1686 * Direct3DViewport3: The viewport to set
1692 * (Is a NULL viewport valid?)
1694 *****************************************************************************/
1695 static HRESULT WINAPI
d3d_device3_SetCurrentViewport(IDirect3DDevice3
*iface
, IDirect3DViewport3
*viewport
)
1697 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport3(viewport
);
1698 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
1700 TRACE("iface %p, viewport %p, current_viewport %p.\n", iface
, viewport
, device
->current_viewport
);
1704 WARN("Direct3DViewport3 is NULL.\n");
1705 return DDERR_INVALIDPARAMS
;
1708 wined3d_mutex_lock();
1709 /* Do nothing if the specified viewport is the same as the current one */
1710 if (device
->current_viewport
== vp
)
1712 wined3d_mutex_unlock();
1716 if (vp
->active_device
!= device
)
1718 WARN("Viewport %p, active device %p.\n", vp
, vp
->active_device
);
1719 wined3d_mutex_unlock();
1720 return DDERR_INVALIDPARAMS
;
1723 IDirect3DViewport3_AddRef(viewport
);
1724 if (device
->current_viewport
)
1726 viewport_deactivate(device
->current_viewport
);
1727 IDirect3DViewport3_Release(&device
->current_viewport
->IDirect3DViewport3_iface
);
1729 device
->current_viewport
= vp
;
1730 viewport_activate(device
->current_viewport
, FALSE
);
1732 wined3d_mutex_unlock();
1737 static HRESULT WINAPI
d3d_device2_SetCurrentViewport(IDirect3DDevice2
*iface
, IDirect3DViewport2
*viewport
)
1739 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
1740 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport2(viewport
);
1742 TRACE("iface %p, viewport %p.\n", iface
, viewport
);
1744 return d3d_device3_SetCurrentViewport(&device
->IDirect3DDevice3_iface
,
1745 vp
? &vp
->IDirect3DViewport3_iface
: NULL
);
1748 /*****************************************************************************
1749 * IDirect3DDevice3::GetCurrentViewport
1751 * Returns the currently active viewport.
1756 * Direct3DViewport3: Address to return the interface pointer at
1760 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1762 *****************************************************************************/
1763 static HRESULT WINAPI
d3d_device3_GetCurrentViewport(IDirect3DDevice3
*iface
, IDirect3DViewport3
**viewport
)
1765 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
1767 TRACE("iface %p, viewport %p.\n", iface
, viewport
);
1769 wined3d_mutex_lock();
1770 if (!device
->current_viewport
)
1772 wined3d_mutex_unlock();
1773 WARN("No current viewport, returning D3DERR_NOCURRENTVIEWPORT\n");
1774 return D3DERR_NOCURRENTVIEWPORT
;
1777 *viewport
= &device
->current_viewport
->IDirect3DViewport3_iface
;
1778 IDirect3DViewport3_AddRef(*viewport
);
1780 TRACE("Returning interface %p.\n", *viewport
);
1781 wined3d_mutex_unlock();
1785 static HRESULT WINAPI
d3d_device2_GetCurrentViewport(IDirect3DDevice2
*iface
, IDirect3DViewport2
**viewport
)
1787 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
1789 TRACE("iface %p, viewport %p.\n", iface
, viewport
);
1791 return d3d_device3_GetCurrentViewport(&device
->IDirect3DDevice3_iface
,
1792 (IDirect3DViewport3
**)viewport
);
1795 static BOOL
validate_surface_palette(struct ddraw_surface
*surface
)
1797 return !format_is_paletteindexed(&surface
->surface_desc
.u4
.ddpfPixelFormat
)
1798 || surface
->palette
;
1801 static HRESULT
d3d_device_set_render_target(struct d3d_device
*device
,
1802 struct ddraw_surface
*target
, IUnknown
*rt_iface
)
1806 if (device
->rt_iface
== rt_iface
)
1808 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1813 WARN("Trying to set render target to NULL.\n");
1814 return DDERR_INVALIDPARAMS
;
1817 if (FAILED(hr
= wined3d_device_set_rendertarget_view(device
->wined3d_device
,
1818 0, ddraw_surface_get_rendertarget_view(target
), FALSE
)))
1821 IUnknown_AddRef(rt_iface
);
1822 IUnknown_Release(device
->rt_iface
);
1823 device
->rt_iface
= rt_iface
;
1824 d3d_device_update_depth_stencil(device
);
1829 static HRESULT
d3d_device7_SetRenderTarget(IDirect3DDevice7
*iface
,
1830 IDirectDrawSurface7
*target
, DWORD flags
)
1832 struct ddraw_surface
*target_impl
= unsafe_impl_from_IDirectDrawSurface7(target
);
1833 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
1836 TRACE("iface %p, target %p, flags %#x.\n", iface
, target
, flags
);
1838 wined3d_mutex_lock();
1840 if (!validate_surface_palette(target_impl
))
1842 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl
);
1843 wined3d_mutex_unlock();
1844 return DDERR_INVALIDCAPS
;
1847 if (!(target_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_3DDEVICE
))
1849 WARN("Surface %p is not a render target.\n", target_impl
);
1850 wined3d_mutex_unlock();
1851 return DDERR_INVALIDCAPS
;
1854 if (!(target_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_VIDEOMEMORY
))
1856 WARN("Surface %p is not in video memory.\n", target_impl
);
1857 wined3d_mutex_unlock();
1858 return DDERR_INVALIDPARAMS
;
1861 if (target_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_ZBUFFER
)
1863 WARN("Surface %p is a depth buffer.\n", target_impl
);
1864 IDirectDrawSurface7_AddRef(target
);
1865 IUnknown_Release(device
->rt_iface
);
1866 device
->rt_iface
= (IUnknown
*)target
;
1867 wined3d_mutex_unlock();
1868 return DDERR_INVALIDPIXELFORMAT
;
1871 hr
= d3d_device_set_render_target(device
, target_impl
, (IUnknown
*)target
);
1872 wined3d_mutex_unlock();
1876 static HRESULT WINAPI
d3d_device7_SetRenderTarget_FPUSetup(IDirect3DDevice7
*iface
,
1877 IDirectDrawSurface7
*NewTarget
, DWORD flags
)
1879 return d3d_device7_SetRenderTarget(iface
, NewTarget
, flags
);
1882 static HRESULT WINAPI
d3d_device7_SetRenderTarget_FPUPreserve(IDirect3DDevice7
*iface
,
1883 IDirectDrawSurface7
*NewTarget
, DWORD flags
)
1888 old_fpucw
= d3d_fpu_setup();
1889 hr
= d3d_device7_SetRenderTarget(iface
, NewTarget
, flags
);
1890 set_fpu_control_word(old_fpucw
);
1895 static HRESULT WINAPI
d3d_device3_SetRenderTarget(IDirect3DDevice3
*iface
,
1896 IDirectDrawSurface4
*target
, DWORD flags
)
1898 struct ddraw_surface
*target_impl
= unsafe_impl_from_IDirectDrawSurface4(target
);
1899 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
1902 TRACE("iface %p, target %p, flags %#x.\n", iface
, target
, flags
);
1904 wined3d_mutex_lock();
1906 if (!validate_surface_palette(target_impl
))
1908 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl
);
1909 wined3d_mutex_unlock();
1910 return DDERR_INVALIDCAPS
;
1913 if (!(target_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_3DDEVICE
))
1915 WARN("Surface %p is not a render target.\n", target_impl
);
1916 wined3d_mutex_unlock();
1917 return DDERR_INVALIDCAPS
;
1920 if (target_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_ZBUFFER
)
1922 WARN("Surface %p is a depth buffer.\n", target_impl
);
1923 IDirectDrawSurface4_AddRef(target
);
1924 IUnknown_Release(device
->rt_iface
);
1925 device
->rt_iface
= (IUnknown
*)target
;
1926 wined3d_mutex_unlock();
1927 return DDERR_INVALIDPIXELFORMAT
;
1930 if (!(target_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_VIDEOMEMORY
))
1932 WARN("Surface %p is not in video memory.\n", target_impl
);
1933 IDirectDrawSurface4_AddRef(target
);
1934 IUnknown_Release(device
->rt_iface
);
1935 device
->rt_iface
= (IUnknown
*)target
;
1936 wined3d_mutex_unlock();
1940 hr
= d3d_device_set_render_target(device
, target_impl
, (IUnknown
*)target
);
1941 wined3d_mutex_unlock();
1945 static HRESULT WINAPI
d3d_device2_SetRenderTarget(IDirect3DDevice2
*iface
,
1946 IDirectDrawSurface
*target
, DWORD flags
)
1948 struct ddraw_surface
*target_impl
= unsafe_impl_from_IDirectDrawSurface(target
);
1949 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
1952 TRACE("iface %p, target %p, flags %#x.\n", iface
, target
, flags
);
1954 wined3d_mutex_lock();
1956 if (!validate_surface_palette(target_impl
))
1958 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl
);
1959 wined3d_mutex_unlock();
1960 return DDERR_INVALIDCAPS
;
1963 if (!(target_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_3DDEVICE
))
1965 WARN("Surface %p is not a render target.\n", target_impl
);
1966 wined3d_mutex_unlock();
1967 return DDERR_INVALIDCAPS
;
1970 if (target_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_ZBUFFER
)
1972 WARN("Surface %p is a depth buffer.\n", target_impl
);
1973 IUnknown_Release(device
->rt_iface
);
1974 device
->rt_iface
= (IUnknown
*)target
;
1975 wined3d_mutex_unlock();
1976 return DDERR_INVALIDPIXELFORMAT
;
1979 if (!(target_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_VIDEOMEMORY
))
1981 WARN("Surface %p is not in video memory.\n", target_impl
);
1982 IDirectDrawSurface_AddRef(target
);
1983 IUnknown_Release(device
->rt_iface
);
1984 device
->rt_iface
= (IUnknown
*)target
;
1985 wined3d_mutex_unlock();
1989 hr
= d3d_device_set_render_target(device
, target_impl
, (IUnknown
*)target
);
1990 wined3d_mutex_unlock();
1994 /*****************************************************************************
1995 * IDirect3DDevice7::GetRenderTarget
1997 * Returns the current render target.
1998 * This is handled locally, because the WineD3D render target's parent
2001 * Version 2, 3 and 7
2004 * RenderTarget: Address to store the surface interface pointer
2008 * DDERR_INVALIDPARAMS if RenderTarget == NULL
2010 *****************************************************************************/
2011 static HRESULT WINAPI
d3d_device7_GetRenderTarget(IDirect3DDevice7
*iface
, IDirectDrawSurface7
**RenderTarget
)
2013 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
2016 TRACE("iface %p, target %p.\n", iface
, RenderTarget
);
2019 return DDERR_INVALIDPARAMS
;
2021 wined3d_mutex_lock();
2022 hr
= IUnknown_QueryInterface(device
->rt_iface
, &IID_IDirectDrawSurface7
, (void **)RenderTarget
);
2023 wined3d_mutex_unlock();
2028 static HRESULT WINAPI
d3d_device3_GetRenderTarget(IDirect3DDevice3
*iface
, IDirectDrawSurface4
**RenderTarget
)
2030 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
2031 IDirectDrawSurface7
*RenderTarget7
;
2032 struct ddraw_surface
*RenderTargetImpl
;
2035 TRACE("iface %p, target %p.\n", iface
, RenderTarget
);
2038 return DDERR_INVALIDPARAMS
;
2040 hr
= d3d_device7_GetRenderTarget(&device
->IDirect3DDevice7_iface
, &RenderTarget7
);
2041 if(hr
!= D3D_OK
) return hr
;
2042 RenderTargetImpl
= impl_from_IDirectDrawSurface7(RenderTarget7
);
2043 *RenderTarget
= &RenderTargetImpl
->IDirectDrawSurface4_iface
;
2044 IDirectDrawSurface4_AddRef(*RenderTarget
);
2045 IDirectDrawSurface7_Release(RenderTarget7
);
2049 static HRESULT WINAPI
d3d_device2_GetRenderTarget(IDirect3DDevice2
*iface
, IDirectDrawSurface
**RenderTarget
)
2051 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
2052 IDirectDrawSurface7
*RenderTarget7
;
2053 struct ddraw_surface
*RenderTargetImpl
;
2056 TRACE("iface %p, target %p.\n", iface
, RenderTarget
);
2059 return DDERR_INVALIDPARAMS
;
2061 hr
= d3d_device7_GetRenderTarget(&device
->IDirect3DDevice7_iface
, &RenderTarget7
);
2062 if(hr
!= D3D_OK
) return hr
;
2063 RenderTargetImpl
= impl_from_IDirectDrawSurface7(RenderTarget7
);
2064 *RenderTarget
= &RenderTargetImpl
->IDirectDrawSurface_iface
;
2065 IDirectDrawSurface_AddRef(*RenderTarget
);
2066 IDirectDrawSurface7_Release(RenderTarget7
);
2070 /*****************************************************************************
2071 * IDirect3DDevice3::Begin
2073 * Begins a description block of vertices. This is similar to glBegin()
2074 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2075 * described with IDirect3DDevice::Vertex are drawn.
2080 * PrimitiveType: The type of primitives to draw
2081 * VertexTypeDesc: A flexible vertex format description of the vertices
2082 * Flags: Some flags..
2087 *****************************************************************************/
2088 static HRESULT WINAPI
d3d_device3_Begin(IDirect3DDevice3
*iface
,
2089 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
, DWORD flags
)
2091 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
2093 TRACE("iface %p, primitive_type %#x, fvf %#x, flags %#x.\n",
2094 iface
, primitive_type
, fvf
, flags
);
2096 wined3d_mutex_lock();
2097 device
->primitive_type
= primitive_type
;
2098 device
->vertex_type
= fvf
;
2099 device
->render_flags
= flags
;
2100 device
->vertex_size
= get_flexible_vertex_size(device
->vertex_type
);
2101 device
->nb_vertices
= 0;
2102 wined3d_mutex_unlock();
2107 static HRESULT WINAPI
d3d_device2_Begin(IDirect3DDevice2
*iface
,
2108 D3DPRIMITIVETYPE primitive_type
, D3DVERTEXTYPE vertex_type
, DWORD flags
)
2110 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
2113 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2114 iface
, primitive_type
, vertex_type
, flags
);
2116 switch (vertex_type
)
2118 case D3DVT_VERTEX
: fvf
= D3DFVF_VERTEX
; break;
2119 case D3DVT_LVERTEX
: fvf
= D3DFVF_LVERTEX
; break;
2120 case D3DVT_TLVERTEX
: fvf
= D3DFVF_TLVERTEX
; break;
2122 ERR("Unexpected vertex type %#x.\n", vertex_type
);
2123 return DDERR_INVALIDPARAMS
; /* Should never happen */
2126 return d3d_device3_Begin(&device
->IDirect3DDevice3_iface
, primitive_type
, fvf
, flags
);
2129 /*****************************************************************************
2130 * IDirect3DDevice3::BeginIndexed
2132 * Draws primitives based on vertices in a vertex array which are specified
2138 * PrimitiveType: Primitive type to draw
2139 * VertexType: A FVF description of the vertex format
2140 * Vertices: pointer to an array containing the vertices
2141 * NumVertices: The number of vertices in the vertex array
2142 * Flags: Some flags ...
2145 * D3D_OK, because it's a stub
2147 *****************************************************************************/
2148 static HRESULT WINAPI
d3d_device3_BeginIndexed(IDirect3DDevice3
*iface
,
2149 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
,
2150 void *vertices
, DWORD vertex_count
, DWORD flags
)
2152 FIXME("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2153 iface
, primitive_type
, fvf
, vertices
, vertex_count
, flags
);
2159 static HRESULT WINAPI
d3d_device2_BeginIndexed(IDirect3DDevice2
*iface
,
2160 D3DPRIMITIVETYPE primitive_type
, D3DVERTEXTYPE vertex_type
,
2161 void *vertices
, DWORD vertex_count
, DWORD flags
)
2163 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
2166 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2167 iface
, primitive_type
, vertex_type
, vertices
, vertex_count
, flags
);
2169 switch (vertex_type
)
2171 case D3DVT_VERTEX
: fvf
= D3DFVF_VERTEX
; break;
2172 case D3DVT_LVERTEX
: fvf
= D3DFVF_LVERTEX
; break;
2173 case D3DVT_TLVERTEX
: fvf
= D3DFVF_TLVERTEX
; break;
2175 ERR("Unexpected vertex type %#x.\n", vertex_type
);
2176 return DDERR_INVALIDPARAMS
; /* Should never happen */
2179 return d3d_device3_BeginIndexed(&device
->IDirect3DDevice3_iface
,
2180 primitive_type
, fvf
, vertices
, vertex_count
, flags
);
2183 /*****************************************************************************
2184 * IDirect3DDevice3::Vertex
2186 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2187 * drawn vertices in a vertex buffer. If the buffer is too small, its
2188 * size is increased.
2193 * Vertex: Pointer to the vertex
2196 * D3D_OK, on success
2197 * DDERR_INVALIDPARAMS if Vertex is NULL
2199 *****************************************************************************/
2200 static HRESULT WINAPI
d3d_device3_Vertex(IDirect3DDevice3
*iface
, void *vertex
)
2202 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
2204 TRACE("iface %p, vertex %p.\n", iface
, vertex
);
2207 return DDERR_INVALIDPARAMS
;
2209 wined3d_mutex_lock();
2210 if ((device
->nb_vertices
+ 1) * device
->vertex_size
> device
->buffer_size
)
2214 device
->buffer_size
= device
->buffer_size
? device
->buffer_size
* 2 : device
->vertex_size
* 3;
2215 old_buffer
= device
->sysmem_vertex_buffer
;
2216 device
->sysmem_vertex_buffer
= heap_alloc(device
->buffer_size
);
2219 memcpy(device
->sysmem_vertex_buffer
, old_buffer
, device
->nb_vertices
* device
->vertex_size
);
2220 heap_free(old_buffer
);
2224 memcpy(device
->sysmem_vertex_buffer
+ device
->nb_vertices
++ * device
->vertex_size
, vertex
, device
->vertex_size
);
2225 wined3d_mutex_unlock();
2230 static HRESULT WINAPI
d3d_device2_Vertex(IDirect3DDevice2
*iface
, void *vertex
)
2232 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
2234 TRACE("iface %p, vertex %p.\n", iface
, vertex
);
2236 return d3d_device3_Vertex(&device
->IDirect3DDevice3_iface
, vertex
);
2239 /*****************************************************************************
2240 * IDirect3DDevice3::Index
2242 * Specifies an index to a vertex to be drawn. The vertex array has to
2243 * be specified with BeginIndexed first.
2246 * VertexIndex: The index of the vertex to draw
2249 * D3D_OK because it's a stub
2251 *****************************************************************************/
2252 static HRESULT WINAPI
d3d_device3_Index(IDirect3DDevice3
*iface
, WORD index
)
2254 FIXME("iface %p, index %#x stub!\n", iface
, index
);
2259 static HRESULT WINAPI
d3d_device2_Index(IDirect3DDevice2
*iface
, WORD index
)
2261 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
2263 TRACE("iface %p, index %#x.\n", iface
, index
);
2265 return d3d_device3_Index(&device
->IDirect3DDevice3_iface
, index
);
2268 /*****************************************************************************
2269 * IDirect3DDevice7::GetRenderState
2271 * Returns the value of a render state. The possible render states are
2272 * defined in include/d3dtypes.h
2274 * Version 2, 3 and 7
2277 * RenderStateType: Render state to return the current setting of
2278 * Value: Address to store the value at
2281 * D3D_OK on success,
2282 * DDERR_INVALIDPARAMS if Value == NULL
2284 *****************************************************************************/
2285 static HRESULT
d3d_device7_GetRenderState(IDirect3DDevice7
*iface
,
2286 D3DRENDERSTATETYPE state
, DWORD
*value
)
2288 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
2289 HRESULT hr
= D3D_OK
;
2291 TRACE("iface %p, state %#x, value %p.\n", iface
, state
, value
);
2294 return DDERR_INVALIDPARAMS
;
2296 wined3d_mutex_lock();
2299 case D3DRENDERSTATE_TEXTUREMAG
:
2301 enum wined3d_texture_filter_type tex_mag
;
2303 tex_mag
= wined3d_device_get_sampler_state(device
->wined3d_device
, 0, WINED3D_SAMP_MAG_FILTER
);
2306 case WINED3D_TEXF_POINT
:
2307 *value
= D3DFILTER_NEAREST
;
2309 case WINED3D_TEXF_LINEAR
:
2310 *value
= D3DFILTER_LINEAR
;
2313 ERR("Unhandled texture mag %d !\n",tex_mag
);
2319 case D3DRENDERSTATE_TEXTUREMIN
:
2321 enum wined3d_texture_filter_type tex_min
;
2322 enum wined3d_texture_filter_type tex_mip
;
2324 tex_min
= wined3d_device_get_sampler_state(device
->wined3d_device
, 0, WINED3D_SAMP_MIN_FILTER
);
2325 tex_mip
= wined3d_device_get_sampler_state(device
->wined3d_device
, 0, WINED3D_SAMP_MIP_FILTER
);
2328 case WINED3D_TEXF_POINT
:
2331 case WINED3D_TEXF_NONE
:
2332 *value
= D3DFILTER_NEAREST
;
2334 case WINED3D_TEXF_POINT
:
2335 *value
= D3DFILTER_MIPNEAREST
;
2337 case WINED3D_TEXF_LINEAR
:
2338 *value
= D3DFILTER_LINEARMIPNEAREST
;
2341 ERR("Unhandled mip filter %#x.\n", tex_mip
);
2342 *value
= D3DFILTER_NEAREST
;
2346 case WINED3D_TEXF_LINEAR
:
2349 case WINED3D_TEXF_NONE
:
2350 *value
= D3DFILTER_LINEAR
;
2352 case WINED3D_TEXF_POINT
:
2353 *value
= D3DFILTER_MIPLINEAR
;
2355 case WINED3D_TEXF_LINEAR
:
2356 *value
= D3DFILTER_LINEARMIPLINEAR
;
2359 ERR("Unhandled mip filter %#x.\n", tex_mip
);
2360 *value
= D3DFILTER_LINEAR
;
2365 ERR("Unhandled texture min filter %#x.\n",tex_min
);
2366 *value
= D3DFILTER_NEAREST
;
2372 case D3DRENDERSTATE_TEXTUREADDRESS
:
2373 case D3DRENDERSTATE_TEXTUREADDRESSU
:
2374 *value
= wined3d_device_get_sampler_state(device
->wined3d_device
, 0, WINED3D_SAMP_ADDRESS_U
);
2376 case D3DRENDERSTATE_TEXTUREADDRESSV
:
2377 *value
= wined3d_device_get_sampler_state(device
->wined3d_device
, 0, WINED3D_SAMP_ADDRESS_V
);
2380 case D3DRENDERSTATE_BORDERCOLOR
:
2381 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2385 case D3DRENDERSTATE_TEXTUREHANDLE
:
2386 case D3DRENDERSTATE_TEXTUREMAPBLEND
:
2387 WARN("Render state %#x is invalid in d3d7.\n", state
);
2388 hr
= DDERR_INVALIDPARAMS
;
2391 case D3DRENDERSTATE_ZBIAS
:
2392 *value
= wined3d_device_get_render_state(device
->wined3d_device
, WINED3D_RS_DEPTHBIAS
);
2396 if (state
>= D3DRENDERSTATE_STIPPLEPATTERN00
2397 && state
<= D3DRENDERSTATE_STIPPLEPATTERN31
)
2399 FIXME("Unhandled stipple pattern render state (%#x).\n", state
);
2403 *value
= wined3d_device_get_render_state(device
->wined3d_device
, state
);
2405 wined3d_mutex_unlock();
2410 static HRESULT WINAPI
d3d_device7_GetRenderState_FPUSetup(IDirect3DDevice7
*iface
,
2411 D3DRENDERSTATETYPE state
, DWORD
*value
)
2413 return d3d_device7_GetRenderState(iface
, state
, value
);
2416 static HRESULT WINAPI
d3d_device7_GetRenderState_FPUPreserve(IDirect3DDevice7
*iface
,
2417 D3DRENDERSTATETYPE state
, DWORD
*value
)
2422 old_fpucw
= d3d_fpu_setup();
2423 hr
= d3d_device7_GetRenderState(iface
, state
, value
);
2424 set_fpu_control_word(old_fpucw
);
2429 static HRESULT WINAPI
d3d_device3_GetRenderState(IDirect3DDevice3
*iface
,
2430 D3DRENDERSTATETYPE state
, DWORD
*value
)
2432 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
2434 TRACE("iface %p, state %#x, value %p.\n", iface
, state
, value
);
2438 case D3DRENDERSTATE_TEXTUREHANDLE
:
2440 /* This state is wrapped to SetTexture in SetRenderState, so
2441 * it has to be wrapped to GetTexture here. */
2442 struct wined3d_texture
*tex
= NULL
;
2445 wined3d_mutex_lock();
2446 if ((tex
= wined3d_device_get_texture(device
->wined3d_device
, 0)))
2448 /* The parent of the texture is the IDirectDrawSurface7
2449 * interface of the ddraw surface. */
2450 struct ddraw_texture
*parent
= wined3d_texture_get_parent(tex
);
2452 *value
= parent
->root
->Handle
;
2454 wined3d_mutex_unlock();
2459 case D3DRENDERSTATE_TEXTUREMAPBLEND
:
2461 *value
= device
->texture_map_blend
;
2465 case D3DRENDERSTATE_LIGHTING
:
2466 case D3DRENDERSTATE_NORMALIZENORMALS
:
2467 case D3DRENDERSTATE_LOCALVIEWER
:
2468 *value
= 0xffffffff;
2472 return IDirect3DDevice7_GetRenderState(&device
->IDirect3DDevice7_iface
, state
, value
);
2476 static HRESULT WINAPI
d3d_device2_GetRenderState(IDirect3DDevice2
*iface
,
2477 D3DRENDERSTATETYPE state
, DWORD
*value
)
2479 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
2481 TRACE("iface %p, state %#x, value %p.\n", iface
, state
, value
);
2483 return IDirect3DDevice3_GetRenderState(&device
->IDirect3DDevice3_iface
, state
, value
);
2486 /*****************************************************************************
2487 * IDirect3DDevice7::SetRenderState
2489 * Sets a render state. The possible render states are defined in
2490 * include/d3dtypes.h
2492 * Version 2, 3 and 7
2495 * RenderStateType: State to set
2496 * Value: Value to assign to that state
2498 *****************************************************************************/
2499 static HRESULT
d3d_device7_SetRenderState(IDirect3DDevice7
*iface
,
2500 D3DRENDERSTATETYPE state
, DWORD value
)
2502 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
2503 HRESULT hr
= D3D_OK
;
2505 TRACE("iface %p, state %#x, value %#x.\n", iface
, state
, value
);
2507 wined3d_mutex_lock();
2508 /* Some render states need special care */
2512 * The ddraw texture filter mapping works like this:
2513 * D3DFILTER_NEAREST Point min/mag, no mip
2514 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2515 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2517 * D3DFILTER_LINEAR Linear min/mag, no mip
2518 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2519 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2521 * This is the opposite of the GL naming convention,
2522 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2524 case D3DRENDERSTATE_TEXTUREMAG
:
2526 enum wined3d_texture_filter_type tex_mag
;
2530 case D3DFILTER_NEAREST
:
2531 case D3DFILTER_MIPNEAREST
:
2532 case D3DFILTER_LINEARMIPNEAREST
:
2533 tex_mag
= WINED3D_TEXF_POINT
;
2535 case D3DFILTER_LINEAR
:
2536 case D3DFILTER_MIPLINEAR
:
2537 case D3DFILTER_LINEARMIPLINEAR
:
2538 tex_mag
= WINED3D_TEXF_LINEAR
;
2541 tex_mag
= WINED3D_TEXF_POINT
;
2542 FIXME("Unhandled texture mag %#x.\n", value
);
2546 wined3d_device_set_sampler_state(device
->wined3d_device
, 0, WINED3D_SAMP_MAG_FILTER
, tex_mag
);
2550 case D3DRENDERSTATE_TEXTUREMIN
:
2552 enum wined3d_texture_filter_type tex_min
;
2553 enum wined3d_texture_filter_type tex_mip
;
2557 case D3DFILTER_NEAREST
:
2558 tex_min
= WINED3D_TEXF_POINT
;
2559 tex_mip
= WINED3D_TEXF_NONE
;
2561 case D3DFILTER_LINEAR
:
2562 tex_min
= WINED3D_TEXF_LINEAR
;
2563 tex_mip
= WINED3D_TEXF_NONE
;
2565 case D3DFILTER_MIPNEAREST
:
2566 tex_min
= WINED3D_TEXF_POINT
;
2567 tex_mip
= WINED3D_TEXF_POINT
;
2569 case D3DFILTER_MIPLINEAR
:
2570 tex_min
= WINED3D_TEXF_LINEAR
;
2571 tex_mip
= WINED3D_TEXF_POINT
;
2573 case D3DFILTER_LINEARMIPNEAREST
:
2574 tex_min
= WINED3D_TEXF_POINT
;
2575 tex_mip
= WINED3D_TEXF_LINEAR
;
2577 case D3DFILTER_LINEARMIPLINEAR
:
2578 tex_min
= WINED3D_TEXF_LINEAR
;
2579 tex_mip
= WINED3D_TEXF_LINEAR
;
2583 FIXME("Unhandled texture min %#x.\n",value
);
2584 tex_min
= WINED3D_TEXF_POINT
;
2585 tex_mip
= WINED3D_TEXF_NONE
;
2589 wined3d_device_set_sampler_state(device
->wined3d_device
,
2590 0, WINED3D_SAMP_MIP_FILTER
, tex_mip
);
2591 wined3d_device_set_sampler_state(device
->wined3d_device
,
2592 0, WINED3D_SAMP_MIN_FILTER
, tex_min
);
2596 case D3DRENDERSTATE_TEXTUREADDRESS
:
2597 wined3d_device_set_sampler_state(device
->wined3d_device
,
2598 0, WINED3D_SAMP_ADDRESS_V
, value
);
2600 case D3DRENDERSTATE_TEXTUREADDRESSU
:
2601 wined3d_device_set_sampler_state(device
->wined3d_device
,
2602 0, WINED3D_SAMP_ADDRESS_U
, value
);
2604 case D3DRENDERSTATE_TEXTUREADDRESSV
:
2605 wined3d_device_set_sampler_state(device
->wined3d_device
,
2606 0, WINED3D_SAMP_ADDRESS_V
, value
);
2609 case D3DRENDERSTATE_BORDERCOLOR
:
2610 /* This should probably just forward to the corresponding sampler
2611 * state. Needs tests. */
2612 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2616 case D3DRENDERSTATE_TEXTUREHANDLE
:
2617 case D3DRENDERSTATE_TEXTUREMAPBLEND
:
2618 WARN("Render state %#x is invalid in d3d7.\n", state
);
2619 hr
= DDERR_INVALIDPARAMS
;
2622 case D3DRENDERSTATE_ZBIAS
:
2623 wined3d_device_set_render_state(device
->wined3d_device
, WINED3D_RS_DEPTHBIAS
, value
);
2627 if (state
>= D3DRENDERSTATE_STIPPLEPATTERN00
2628 && state
<= D3DRENDERSTATE_STIPPLEPATTERN31
)
2630 FIXME("Unhandled stipple pattern render state (%#x).\n", state
);
2635 wined3d_device_set_render_state(device
->wined3d_device
, state
, value
);
2638 wined3d_mutex_unlock();
2643 static HRESULT WINAPI
d3d_device7_SetRenderState_FPUSetup(IDirect3DDevice7
*iface
,
2644 D3DRENDERSTATETYPE state
, DWORD value
)
2646 return d3d_device7_SetRenderState(iface
, state
, value
);
2649 static HRESULT WINAPI
d3d_device7_SetRenderState_FPUPreserve(IDirect3DDevice7
*iface
,
2650 D3DRENDERSTATETYPE state
, DWORD value
)
2655 old_fpucw
= d3d_fpu_setup();
2656 hr
= d3d_device7_SetRenderState(iface
, state
, value
);
2657 set_fpu_control_word(old_fpucw
);
2662 static void fixup_texture_alpha_op(struct d3d_device
*device
)
2664 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
2665 See d3d_device3_SetRenderState() for details. */
2666 struct wined3d_texture
*tex
;
2667 BOOL tex_alpha
= TRUE
;
2668 DDPIXELFORMAT ddfmt
;
2670 if (!(device
->legacyTextureBlending
&& device
->texture_map_blend
== D3DTBLEND_MODULATE
))
2673 if ((tex
= wined3d_device_get_texture(device
->wined3d_device
, 0)))
2675 struct wined3d_resource_desc desc
;
2677 wined3d_resource_get_desc(wined3d_texture_get_resource(tex
), &desc
);
2678 ddfmt
.dwSize
= sizeof(ddfmt
);
2679 ddrawformat_from_wined3dformat(&ddfmt
, desc
.format
);
2680 if (!ddfmt
.u5
.dwRGBAlphaBitMask
)
2684 /* Args 1 and 2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
2685 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2686 0, WINED3D_TSS_ALPHA_OP
, tex_alpha
? WINED3D_TOP_SELECT_ARG1
: WINED3D_TOP_SELECT_ARG2
);
2689 static HRESULT WINAPI
d3d_device3_SetRenderState(IDirect3DDevice3
*iface
,
2690 D3DRENDERSTATETYPE state
, DWORD value
)
2692 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2693 for this state can be directly mapped to texture stage colorop and alphaop, but
2694 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2695 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2696 alphaarg when needed.
2698 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2700 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2701 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2702 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2703 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2704 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2705 in device - TRUE if the app is using TEXTUREMAPBLEND.
2707 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2708 GetTextureStageState and vice versa. */
2710 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
2713 TRACE("iface %p, state %#x, value %#x.\n", iface
, state
, value
);
2715 if (state
>= D3DSTATE_OVERRIDE_BIAS
)
2717 WARN("Unhandled state %#x.\n", state
);
2718 return DDERR_INVALIDPARAMS
;
2721 wined3d_mutex_lock();
2725 case D3DRENDERSTATE_TEXTUREHANDLE
:
2727 struct ddraw_surface
*surf
;
2731 wined3d_device_set_texture(device
->wined3d_device
, 0, NULL
);
2736 surf
= ddraw_get_object(&device
->handle_table
, value
- 1, DDRAW_HANDLE_SURFACE
);
2739 WARN("Invalid texture handle.\n");
2740 hr
= DDERR_INVALIDPARAMS
;
2744 hr
= IDirect3DDevice3_SetTexture(iface
, 0, &surf
->IDirect3DTexture2_iface
);
2748 case D3DRENDERSTATE_TEXTUREMAPBLEND
:
2750 if (value
== device
->texture_map_blend
)
2752 TRACE("Application is setting the same value over, nothing to do.\n");
2758 device
->legacyTextureBlending
= TRUE
;
2759 device
->texture_map_blend
= value
;
2763 case D3DTBLEND_MODULATE
:
2765 fixup_texture_alpha_op(device
);
2767 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2768 0, WINED3D_TSS_ALPHA_ARG1
, WINED3DTA_TEXTURE
);
2769 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2770 0, WINED3D_TSS_ALPHA_ARG2
, WINED3DTA_CURRENT
);
2771 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2772 0, WINED3D_TSS_COLOR_ARG1
, WINED3DTA_TEXTURE
);
2773 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2774 0, WINED3D_TSS_COLOR_ARG2
, WINED3DTA_CURRENT
);
2775 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2776 0, WINED3D_TSS_COLOR_OP
, WINED3D_TOP_MODULATE
);
2781 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2782 0, WINED3D_TSS_COLOR_OP
, WINED3D_TOP_ADD
);
2783 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2784 0, WINED3D_TSS_COLOR_ARG1
, WINED3DTA_TEXTURE
);
2785 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2786 0, WINED3D_TSS_COLOR_ARG2
, WINED3DTA_CURRENT
);
2787 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2788 0, WINED3D_TSS_ALPHA_OP
, WINED3D_TOP_SELECT_ARG2
);
2789 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2790 0, WINED3D_TSS_ALPHA_ARG2
, WINED3DTA_CURRENT
);
2793 case D3DTBLEND_MODULATEALPHA
:
2794 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2795 0, WINED3D_TSS_COLOR_ARG1
, WINED3DTA_TEXTURE
);
2796 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2797 0, WINED3D_TSS_ALPHA_ARG1
, WINED3DTA_TEXTURE
);
2798 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2799 0, WINED3D_TSS_COLOR_ARG2
, WINED3DTA_CURRENT
);
2800 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2801 0, WINED3D_TSS_ALPHA_ARG2
, WINED3DTA_CURRENT
);
2802 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2803 0, WINED3D_TSS_COLOR_OP
, WINED3D_TOP_MODULATE
);
2804 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2805 0, WINED3D_TSS_ALPHA_OP
, WINED3D_TOP_MODULATE
);
2808 case D3DTBLEND_COPY
:
2809 case D3DTBLEND_DECAL
:
2810 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2811 0, WINED3D_TSS_COLOR_ARG1
, WINED3DTA_TEXTURE
);
2812 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2813 0, WINED3D_TSS_ALPHA_ARG1
, WINED3DTA_TEXTURE
);
2814 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2815 0, WINED3D_TSS_COLOR_OP
, WINED3D_TOP_SELECT_ARG1
);
2816 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2817 0, WINED3D_TSS_ALPHA_OP
, WINED3D_TOP_SELECT_ARG1
);
2820 case D3DTBLEND_DECALALPHA
:
2821 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2822 0, WINED3D_TSS_COLOR_OP
, WINED3D_TOP_BLEND_TEXTURE_ALPHA
);
2823 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2824 0, WINED3D_TSS_COLOR_ARG1
, WINED3DTA_TEXTURE
);
2825 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2826 0, WINED3D_TSS_COLOR_ARG2
, WINED3DTA_CURRENT
);
2827 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2828 0, WINED3D_TSS_ALPHA_OP
, WINED3D_TOP_SELECT_ARG2
);
2829 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2830 0, WINED3D_TSS_ALPHA_ARG2
, WINED3DTA_CURRENT
);
2834 FIXME("Unhandled texture environment %#x.\n", value
);
2840 case D3DRENDERSTATE_LIGHTING
:
2841 case D3DRENDERSTATE_NORMALIZENORMALS
:
2842 case D3DRENDERSTATE_LOCALVIEWER
:
2847 hr
= IDirect3DDevice7_SetRenderState(&device
->IDirect3DDevice7_iface
, state
, value
);
2850 wined3d_mutex_unlock();
2855 static HRESULT WINAPI
d3d_device2_SetRenderState(IDirect3DDevice2
*iface
,
2856 D3DRENDERSTATETYPE state
, DWORD value
)
2858 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
2860 TRACE("iface %p, state %#x, value %#x.\n", iface
, state
, value
);
2862 return IDirect3DDevice3_SetRenderState(&device
->IDirect3DDevice3_iface
, state
, value
);
2865 /*****************************************************************************
2866 * Direct3DDevice3::SetLightState
2868 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2869 * light states are forwarded to Direct3DDevice7 render states
2874 * LightStateType: The light state to change
2875 * Value: The value to assign to that light state
2879 * DDERR_INVALIDPARAMS if the parameters were incorrect
2880 * Also check IDirect3DDevice7::SetRenderState
2882 *****************************************************************************/
2883 static HRESULT WINAPI
d3d_device3_SetLightState(IDirect3DDevice3
*iface
,
2884 D3DLIGHTSTATETYPE state
, DWORD value
)
2886 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
2889 TRACE("iface %p, state %#x, value %#x.\n", iface
, state
, value
);
2891 if (!state
|| (state
> D3DLIGHTSTATE_COLORVERTEX
))
2893 TRACE("Unexpected Light State Type\n");
2894 return DDERR_INVALIDPARAMS
;
2897 wined3d_mutex_lock();
2898 if (state
== D3DLIGHTSTATE_MATERIAL
)
2902 struct d3d_material
*m
;
2904 if (!(m
= ddraw_get_object(&device
->handle_table
, value
- 1, DDRAW_HANDLE_MATERIAL
)))
2906 WARN("Invalid material handle.\n");
2907 wined3d_mutex_unlock();
2908 return DDERR_INVALIDPARAMS
;
2911 material_activate(m
);
2914 device
->material
= value
;
2916 else if (state
== D3DLIGHTSTATE_COLORMODEL
)
2921 ERR("DDCOLOR_MONO should not happen!\n");
2924 /* We are already in this mode */
2925 TRACE("Setting color model to RGB (no-op).\n");
2928 ERR("Unknown color model!\n");
2929 wined3d_mutex_unlock();
2930 return DDERR_INVALIDPARAMS
;
2935 D3DRENDERSTATETYPE rs
;
2938 case D3DLIGHTSTATE_AMBIENT
: /* 2 */
2939 rs
= D3DRENDERSTATE_AMBIENT
;
2941 case D3DLIGHTSTATE_FOGMODE
: /* 4 */
2942 rs
= D3DRENDERSTATE_FOGVERTEXMODE
;
2944 case D3DLIGHTSTATE_FOGSTART
: /* 5 */
2945 rs
= D3DRENDERSTATE_FOGSTART
;
2947 case D3DLIGHTSTATE_FOGEND
: /* 6 */
2948 rs
= D3DRENDERSTATE_FOGEND
;
2950 case D3DLIGHTSTATE_FOGDENSITY
: /* 7 */
2951 rs
= D3DRENDERSTATE_FOGDENSITY
;
2953 case D3DLIGHTSTATE_COLORVERTEX
: /* 8 */
2954 rs
= D3DRENDERSTATE_COLORVERTEX
;
2957 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state
);
2958 wined3d_mutex_unlock();
2959 return DDERR_INVALIDPARAMS
;
2962 hr
= IDirect3DDevice7_SetRenderState(&device
->IDirect3DDevice7_iface
, rs
, value
);
2963 wined3d_mutex_unlock();
2966 wined3d_mutex_unlock();
2971 static HRESULT WINAPI
d3d_device2_SetLightState(IDirect3DDevice2
*iface
,
2972 D3DLIGHTSTATETYPE state
, DWORD value
)
2974 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
2976 TRACE("iface %p, state %#x, value %#x.\n", iface
, state
, value
);
2978 return d3d_device3_SetLightState(&device
->IDirect3DDevice3_iface
, state
, value
);
2981 /*****************************************************************************
2982 * IDirect3DDevice3::GetLightState
2984 * Returns the current setting of a light state. The state is read from
2985 * the Direct3DDevice7 render state.
2990 * LightStateType: The light state to return
2991 * Value: The address to store the light state setting at
2995 * DDDERR_INVALIDPARAMS if the parameters were incorrect
2996 * Also see IDirect3DDevice7::GetRenderState
2998 *****************************************************************************/
2999 static HRESULT WINAPI
d3d_device3_GetLightState(IDirect3DDevice3
*iface
,
3000 D3DLIGHTSTATETYPE state
, DWORD
*value
)
3002 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
3005 TRACE("iface %p, state %#x, value %p.\n", iface
, state
, value
);
3007 if (!state
|| (state
> D3DLIGHTSTATE_COLORVERTEX
))
3009 TRACE("Unexpected Light State Type\n");
3010 return DDERR_INVALIDPARAMS
;
3014 return DDERR_INVALIDPARAMS
;
3016 wined3d_mutex_lock();
3017 if (state
== D3DLIGHTSTATE_MATERIAL
)
3019 *value
= device
->material
;
3021 else if (state
== D3DLIGHTSTATE_COLORMODEL
)
3023 *value
= D3DCOLOR_RGB
;
3027 D3DRENDERSTATETYPE rs
;
3030 case D3DLIGHTSTATE_AMBIENT
: /* 2 */
3031 rs
= D3DRENDERSTATE_AMBIENT
;
3033 case D3DLIGHTSTATE_FOGMODE
: /* 4 */
3034 rs
= D3DRENDERSTATE_FOGVERTEXMODE
;
3036 case D3DLIGHTSTATE_FOGSTART
: /* 5 */
3037 rs
= D3DRENDERSTATE_FOGSTART
;
3039 case D3DLIGHTSTATE_FOGEND
: /* 6 */
3040 rs
= D3DRENDERSTATE_FOGEND
;
3042 case D3DLIGHTSTATE_FOGDENSITY
: /* 7 */
3043 rs
= D3DRENDERSTATE_FOGDENSITY
;
3045 case D3DLIGHTSTATE_COLORVERTEX
: /* 8 */
3046 rs
= D3DRENDERSTATE_COLORVERTEX
;
3049 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state
);
3050 wined3d_mutex_unlock();
3051 return DDERR_INVALIDPARAMS
;
3054 hr
= IDirect3DDevice7_GetRenderState(&device
->IDirect3DDevice7_iface
, rs
, value
);
3055 wined3d_mutex_unlock();
3058 wined3d_mutex_unlock();
3063 static HRESULT WINAPI
d3d_device2_GetLightState(IDirect3DDevice2
*iface
,
3064 D3DLIGHTSTATETYPE state
, DWORD
*value
)
3066 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
3068 TRACE("iface %p, state %#x, value %p.\n", iface
, state
, value
);
3070 return d3d_device3_GetLightState(&device
->IDirect3DDevice3_iface
, state
, value
);
3073 /*****************************************************************************
3074 * IDirect3DDevice7::SetTransform
3076 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3077 * in include/d3dtypes.h.
3078 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3079 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3080 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3082 * Version 2, 3 and 7
3085 * TransformStateType: transform state to set
3086 * Matrix: Matrix to assign to the state
3090 * DDERR_INVALIDPARAMS if Matrix == NULL
3092 *****************************************************************************/
3093 static HRESULT
d3d_device7_SetTransform(IDirect3DDevice7
*iface
,
3094 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3096 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
3097 enum wined3d_transform_state wined3d_state
;
3099 TRACE("iface %p, state %#x, matrix %p.\n", iface
, state
, matrix
);
3103 case D3DTRANSFORMSTATE_WORLD
:
3104 wined3d_state
= WINED3D_TS_WORLD_MATRIX(0);
3106 case D3DTRANSFORMSTATE_WORLD1
:
3107 wined3d_state
= WINED3D_TS_WORLD_MATRIX(1);
3109 case D3DTRANSFORMSTATE_WORLD2
:
3110 wined3d_state
= WINED3D_TS_WORLD_MATRIX(2);
3112 case D3DTRANSFORMSTATE_WORLD3
:
3113 wined3d_state
= WINED3D_TS_WORLD_MATRIX(3);
3116 wined3d_state
= state
;
3120 return DDERR_INVALIDPARAMS
;
3122 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3123 wined3d_mutex_lock();
3124 wined3d_device_set_transform(device
->wined3d_device
, wined3d_state
, (struct wined3d_matrix
*)matrix
);
3125 wined3d_mutex_unlock();
3130 static HRESULT WINAPI
d3d_device7_SetTransform_FPUSetup(IDirect3DDevice7
*iface
,
3131 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3133 return d3d_device7_SetTransform(iface
, state
, matrix
);
3136 static HRESULT WINAPI
d3d_device7_SetTransform_FPUPreserve(IDirect3DDevice7
*iface
,
3137 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3142 old_fpucw
= d3d_fpu_setup();
3143 hr
= d3d_device7_SetTransform(iface
, state
, matrix
);
3144 set_fpu_control_word(old_fpucw
);
3149 static HRESULT WINAPI
d3d_device3_SetTransform(IDirect3DDevice3
*iface
,
3150 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3152 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
3154 TRACE("iface %p, state %#x, matrix %p.\n", iface
, state
, matrix
);
3157 return DDERR_INVALIDPARAMS
;
3159 if (state
== D3DTRANSFORMSTATE_PROJECTION
)
3161 D3DMATRIX projection
;
3163 wined3d_mutex_lock();
3164 multiply_matrix(&projection
, &device
->legacy_clipspace
, matrix
);
3165 wined3d_device_set_transform(device
->wined3d_device
,
3166 WINED3D_TS_PROJECTION
, (struct wined3d_matrix
*)&projection
);
3167 device
->legacy_projection
= *matrix
;
3168 wined3d_mutex_unlock();
3173 return IDirect3DDevice7_SetTransform(&device
->IDirect3DDevice7_iface
, state
, matrix
);
3176 static HRESULT WINAPI
d3d_device2_SetTransform(IDirect3DDevice2
*iface
,
3177 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3179 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
3181 TRACE("iface %p, state %#x, matrix %p.\n", iface
, state
, matrix
);
3183 return IDirect3DDevice3_SetTransform(&device
->IDirect3DDevice3_iface
, state
, matrix
);
3186 /*****************************************************************************
3187 * IDirect3DDevice7::GetTransform
3189 * Returns the matrix assigned to a transform state
3190 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3194 * TransformStateType: State to read the matrix from
3195 * Matrix: Address to store the matrix at
3199 * DDERR_INVALIDPARAMS if Matrix == NULL
3201 *****************************************************************************/
3202 static HRESULT
d3d_device7_GetTransform(IDirect3DDevice7
*iface
,
3203 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3205 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
3206 enum wined3d_transform_state wined3d_state
;
3208 TRACE("iface %p, state %#x, matrix %p.\n", iface
, state
, matrix
);
3212 case D3DTRANSFORMSTATE_WORLD
:
3213 wined3d_state
= WINED3D_TS_WORLD_MATRIX(0);
3215 case D3DTRANSFORMSTATE_WORLD1
:
3216 wined3d_state
= WINED3D_TS_WORLD_MATRIX(1);
3218 case D3DTRANSFORMSTATE_WORLD2
:
3219 wined3d_state
= WINED3D_TS_WORLD_MATRIX(2);
3221 case D3DTRANSFORMSTATE_WORLD3
:
3222 wined3d_state
= WINED3D_TS_WORLD_MATRIX(3);
3225 wined3d_state
= state
;
3229 return DDERR_INVALIDPARAMS
;
3231 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3232 wined3d_mutex_lock();
3233 wined3d_device_get_transform(device
->wined3d_device
, wined3d_state
, (struct wined3d_matrix
*)matrix
);
3234 wined3d_mutex_unlock();
3239 static HRESULT WINAPI
d3d_device7_GetTransform_FPUSetup(IDirect3DDevice7
*iface
,
3240 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3242 return d3d_device7_GetTransform(iface
, state
, matrix
);
3245 static HRESULT WINAPI
d3d_device7_GetTransform_FPUPreserve(IDirect3DDevice7
*iface
,
3246 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3251 old_fpucw
= d3d_fpu_setup();
3252 hr
= d3d_device7_GetTransform(iface
, state
, matrix
);
3253 set_fpu_control_word(old_fpucw
);
3258 static HRESULT WINAPI
d3d_device3_GetTransform(IDirect3DDevice3
*iface
,
3259 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3261 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
3263 TRACE("iface %p, state %#x, matrix %p.\n", iface
, state
, matrix
);
3266 return DDERR_INVALIDPARAMS
;
3268 if (state
== D3DTRANSFORMSTATE_PROJECTION
)
3270 wined3d_mutex_lock();
3271 *matrix
= device
->legacy_projection
;
3272 wined3d_mutex_unlock();
3276 return IDirect3DDevice7_GetTransform(&device
->IDirect3DDevice7_iface
, state
, matrix
);
3279 static HRESULT WINAPI
d3d_device2_GetTransform(IDirect3DDevice2
*iface
,
3280 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3282 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
3284 TRACE("iface %p, state %#x, matrix %p.\n", iface
, state
, matrix
);
3286 return IDirect3DDevice3_GetTransform(&device
->IDirect3DDevice3_iface
, state
, matrix
);
3289 /*****************************************************************************
3290 * IDirect3DDevice7::MultiplyTransform
3292 * Multiplies the already-set transform matrix of a transform state
3293 * with another matrix. For the world matrix, see SetTransform
3295 * Version 2, 3 and 7
3298 * TransformStateType: Transform state to multiply
3299 * D3DMatrix Matrix to multiply with.
3303 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3305 *****************************************************************************/
3306 static HRESULT
d3d_device7_MultiplyTransform(IDirect3DDevice7
*iface
,
3307 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3309 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
3310 enum wined3d_transform_state wined3d_state
;
3312 TRACE("iface %p, state %#x, matrix %p.\n", iface
, state
, matrix
);
3316 case D3DTRANSFORMSTATE_WORLD
:
3317 wined3d_state
= WINED3D_TS_WORLD_MATRIX(0);
3319 case D3DTRANSFORMSTATE_WORLD1
:
3320 wined3d_state
= WINED3D_TS_WORLD_MATRIX(1);
3322 case D3DTRANSFORMSTATE_WORLD2
:
3323 wined3d_state
= WINED3D_TS_WORLD_MATRIX(2);
3325 case D3DTRANSFORMSTATE_WORLD3
:
3326 wined3d_state
= WINED3D_TS_WORLD_MATRIX(3);
3329 wined3d_state
= state
;
3332 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3333 wined3d_mutex_lock();
3334 wined3d_device_multiply_transform(device
->wined3d_device
,
3335 wined3d_state
, (struct wined3d_matrix
*)matrix
);
3336 wined3d_mutex_unlock();
3341 static HRESULT WINAPI
d3d_device7_MultiplyTransform_FPUSetup(IDirect3DDevice7
*iface
,
3342 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3344 return d3d_device7_MultiplyTransform(iface
, state
, matrix
);
3347 static HRESULT WINAPI
d3d_device7_MultiplyTransform_FPUPreserve(IDirect3DDevice7
*iface
,
3348 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3353 old_fpucw
= d3d_fpu_setup();
3354 hr
= d3d_device7_MultiplyTransform(iface
, state
, matrix
);
3355 set_fpu_control_word(old_fpucw
);
3360 static HRESULT WINAPI
d3d_device3_MultiplyTransform(IDirect3DDevice3
*iface
,
3361 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3363 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
3365 TRACE("iface %p, state %#x, matrix %p.\n", iface
, state
, matrix
);
3367 if (state
== D3DTRANSFORMSTATE_PROJECTION
)
3369 D3DMATRIX projection
, tmp
;
3371 wined3d_mutex_lock();
3372 multiply_matrix(&tmp
, &device
->legacy_projection
, matrix
);
3373 multiply_matrix(&projection
, &device
->legacy_clipspace
, &tmp
);
3374 wined3d_device_set_transform(device
->wined3d_device
,
3375 WINED3D_TS_PROJECTION
, (struct wined3d_matrix
*)&projection
);
3376 device
->legacy_projection
= tmp
;
3377 wined3d_mutex_unlock();
3382 return IDirect3DDevice7_MultiplyTransform(&device
->IDirect3DDevice7_iface
, state
, matrix
);
3385 static HRESULT WINAPI
d3d_device2_MultiplyTransform(IDirect3DDevice2
*iface
,
3386 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3388 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
3390 TRACE("iface %p, state %#x, matrix %p.\n", iface
, state
, matrix
);
3392 return IDirect3DDevice3_MultiplyTransform(&device
->IDirect3DDevice3_iface
, state
, matrix
);
3395 /*****************************************************************************
3396 * IDirect3DDevice7::DrawPrimitive
3398 * Draws primitives based on vertices in an application-provided pointer
3400 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3401 * an FVF format for D3D7
3404 * PrimitiveType: The type of the primitives to draw
3405 * Vertex type: Flexible vertex format vertex description
3406 * Vertices: Pointer to the vertex array
3407 * VertexCount: The number of vertices to draw
3408 * Flags: As usual a few flags
3412 * DDERR_INVALIDPARAMS if Vertices is NULL
3414 *****************************************************************************/
3416 /* The caller is responsible for wined3d locking */
3417 static HRESULT
d3d_device_prepare_vertex_buffer(struct d3d_device
*device
, UINT min_size
)
3421 if (device
->vertex_buffer_size
< min_size
|| !device
->vertex_buffer
)
3423 UINT size
= max(device
->vertex_buffer_size
* 2, min_size
);
3424 struct wined3d_buffer_desc desc
;
3425 struct wined3d_buffer
*buffer
;
3427 TRACE("Growing vertex buffer to %u bytes\n", size
);
3429 desc
.byte_width
= size
;
3430 desc
.usage
= WINED3DUSAGE_DYNAMIC
;
3431 desc
.bind_flags
= WINED3D_BIND_VERTEX_BUFFER
;
3432 desc
.access
= WINED3D_RESOURCE_ACCESS_GPU
| WINED3D_RESOURCE_ACCESS_MAP_W
;
3433 desc
.misc_flags
= 0;
3434 desc
.structure_byte_stride
= 0;
3436 if (FAILED(hr
= wined3d_buffer_create(device
->wined3d_device
, &desc
,
3437 NULL
, NULL
, &ddraw_null_wined3d_parent_ops
, &buffer
)))
3439 ERR("Failed to create vertex buffer, hr %#x.\n", hr
);
3443 if (device
->vertex_buffer
)
3444 wined3d_buffer_decref(device
->vertex_buffer
);
3446 device
->vertex_buffer
= buffer
;
3447 device
->vertex_buffer_size
= size
;
3448 device
->vertex_buffer_pos
= 0;
3453 static HRESULT
d3d_device7_DrawPrimitive(IDirect3DDevice7
*iface
,
3454 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
, void *vertices
,
3455 DWORD vertex_count
, DWORD flags
)
3457 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
3458 struct wined3d_map_desc wined3d_map_desc
;
3459 struct wined3d_box wined3d_box
= {0};
3460 UINT stride
, vb_pos
, size
, align
;
3461 struct wined3d_resource
*vb
;
3464 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3465 iface
, primitive_type
, fvf
, vertices
, vertex_count
, flags
);
3469 WARN("0 vertex count.\n");
3473 /* Get the stride */
3474 stride
= get_flexible_vertex_size(fvf
);
3475 size
= vertex_count
* stride
;
3477 wined3d_mutex_lock();
3478 hr
= d3d_device_prepare_vertex_buffer(device
, size
);
3482 vb_pos
= device
->vertex_buffer_pos
;
3483 align
= vb_pos
% stride
;
3484 if (align
) align
= stride
- align
;
3485 if (vb_pos
+ size
+ align
> device
->vertex_buffer_size
)
3490 wined3d_box
.left
= vb_pos
;
3491 wined3d_box
.right
= vb_pos
+ size
;
3492 vb
= wined3d_buffer_get_resource(device
->vertex_buffer
);
3493 if (FAILED(hr
= wined3d_resource_map(vb
, 0, &wined3d_map_desc
, &wined3d_box
,
3494 WINED3D_MAP_WRITE
| (vb_pos
? WINED3D_MAP_NOOVERWRITE
: WINED3D_MAP_DISCARD
))))
3496 memcpy(wined3d_map_desc
.data
, vertices
, size
);
3497 wined3d_resource_unmap(vb
, 0);
3498 device
->vertex_buffer_pos
= vb_pos
+ size
;
3500 hr
= wined3d_device_set_stream_source(device
->wined3d_device
, 0, device
->vertex_buffer
, 0, stride
);
3504 wined3d_device_set_vertex_declaration(device
->wined3d_device
, ddraw_find_decl(device
->ddraw
, fvf
));
3505 wined3d_device_set_primitive_type(device
->wined3d_device
, primitive_type
, 0);
3506 hr
= wined3d_device_draw_primitive(device
->wined3d_device
, vb_pos
/ stride
, vertex_count
);
3509 wined3d_mutex_unlock();
3513 static HRESULT WINAPI
d3d_device7_DrawPrimitive_FPUSetup(IDirect3DDevice7
*iface
,
3514 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
, void *vertices
,
3515 DWORD vertex_count
, DWORD flags
)
3517 return d3d_device7_DrawPrimitive(iface
, primitive_type
, fvf
, vertices
, vertex_count
, flags
);
3520 static HRESULT WINAPI
d3d_device7_DrawPrimitive_FPUPreserve(IDirect3DDevice7
*iface
,
3521 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
, void *vertices
,
3522 DWORD vertex_count
, DWORD flags
)
3527 old_fpucw
= d3d_fpu_setup();
3528 hr
= d3d_device7_DrawPrimitive(iface
, primitive_type
, fvf
, vertices
, vertex_count
, flags
);
3529 set_fpu_control_word(old_fpucw
);
3534 static void setup_lighting(const struct d3d_device
*device
, DWORD fvf
, DWORD flags
)
3538 /* Ignore the D3DFVF_XYZRHW case here, wined3d takes care of that */
3539 if (!device
->material
|| !(fvf
& D3DFVF_NORMAL
) || (flags
& D3DDP_DONOTLIGHT
))
3542 wined3d_device_set_render_state(device
->wined3d_device
, WINED3D_RS_LIGHTING
, enable
);
3546 static HRESULT WINAPI
d3d_device3_DrawPrimitive(IDirect3DDevice3
*iface
,
3547 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
, void *vertices
, DWORD vertex_count
,
3550 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
3552 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3553 iface
, primitive_type
, fvf
, vertices
, vertex_count
, flags
);
3555 setup_lighting(device
, fvf
, flags
);
3557 return IDirect3DDevice7_DrawPrimitive(&device
->IDirect3DDevice7_iface
,
3558 primitive_type
, fvf
, vertices
, vertex_count
, flags
);
3561 static HRESULT WINAPI
d3d_device2_DrawPrimitive(IDirect3DDevice2
*iface
,
3562 D3DPRIMITIVETYPE primitive_type
, D3DVERTEXTYPE vertex_type
, void *vertices
,
3563 DWORD vertex_count
, DWORD flags
)
3565 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
3568 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3569 iface
, primitive_type
, vertex_type
, vertices
, vertex_count
, flags
);
3571 switch (vertex_type
)
3573 case D3DVT_VERTEX
: fvf
= D3DFVF_VERTEX
; break;
3574 case D3DVT_LVERTEX
: fvf
= D3DFVF_LVERTEX
; break;
3575 case D3DVT_TLVERTEX
: fvf
= D3DFVF_TLVERTEX
; break;
3577 FIXME("Unhandled vertex type %#x.\n", vertex_type
);
3578 return DDERR_INVALIDPARAMS
; /* Should never happen */
3581 return d3d_device3_DrawPrimitive(&device
->IDirect3DDevice3_iface
,
3582 primitive_type
, fvf
, vertices
, vertex_count
, flags
);
3585 /*****************************************************************************
3586 * IDirect3DDevice7::DrawIndexedPrimitive
3588 * Draws vertices from an application-provided pointer, based on the index
3589 * numbers in a WORD array.
3591 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3592 * an FVF format for D3D7
3595 * PrimitiveType: The primitive type to draw
3596 * VertexType: The FVF vertex description
3597 * Vertices: Pointer to the vertex array
3599 * Indices: Pointer to the index array
3600 * IndexCount: Number of indices = Number of vertices to draw
3601 * Flags: As usual, some flags
3605 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3607 *****************************************************************************/
3608 /* The caller is responsible for wined3d locking */
3609 static HRESULT
d3d_device_prepare_index_buffer(struct d3d_device
*device
, UINT min_size
)
3613 if (device
->index_buffer_size
< min_size
|| !device
->index_buffer
)
3615 UINT size
= max(device
->index_buffer_size
* 2, min_size
);
3616 struct wined3d_buffer_desc desc
;
3617 struct wined3d_buffer
*buffer
;
3619 TRACE("Growing index buffer to %u bytes\n", size
);
3621 desc
.byte_width
= size
;
3622 desc
.usage
= WINED3DUSAGE_DYNAMIC
| WINED3DUSAGE_STATICDECL
;
3623 desc
.bind_flags
= WINED3D_BIND_INDEX_BUFFER
;
3624 desc
.access
= WINED3D_RESOURCE_ACCESS_GPU
| WINED3D_RESOURCE_ACCESS_MAP_W
;
3625 desc
.misc_flags
= 0;
3626 desc
.structure_byte_stride
= 0;
3628 if (FAILED(hr
= wined3d_buffer_create(device
->wined3d_device
, &desc
,
3629 NULL
, NULL
, &ddraw_null_wined3d_parent_ops
, &buffer
)))
3631 ERR("Failed to create index buffer, hr %#x.\n", hr
);
3635 if (device
->index_buffer
)
3636 wined3d_buffer_decref(device
->index_buffer
);
3637 device
->index_buffer
= buffer
;
3638 device
->index_buffer_size
= size
;
3639 device
->index_buffer_pos
= 0;
3644 static HRESULT
d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7
*iface
,
3645 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
, void *vertices
, DWORD vertex_count
,
3646 WORD
*indices
, DWORD index_count
, DWORD flags
)
3648 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
3650 UINT stride
= get_flexible_vertex_size(fvf
);
3651 UINT vtx_size
= stride
* vertex_count
, idx_size
= index_count
* sizeof(*indices
);
3652 struct wined3d_map_desc wined3d_map_desc
;
3653 struct wined3d_box wined3d_box
= {0};
3654 struct wined3d_resource
*ib
, *vb
;
3655 UINT vb_pos
, ib_pos
, align
;
3657 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3658 "indices %p, index_count %u, flags %#x.\n",
3659 iface
, primitive_type
, fvf
, vertices
, vertex_count
, indices
, index_count
, flags
);
3661 if (!vertex_count
|| !index_count
)
3663 WARN("0 vertex or index count.\n");
3667 /* Set the D3DDevice's FVF */
3668 wined3d_mutex_lock();
3670 hr
= d3d_device_prepare_vertex_buffer(device
, vtx_size
);
3674 vb_pos
= device
->vertex_buffer_pos
;
3675 align
= vb_pos
% stride
;
3676 if (align
) align
= stride
- align
;
3677 if (vb_pos
+ vtx_size
+ align
> device
->vertex_buffer_size
)
3682 wined3d_box
.left
= vb_pos
;
3683 wined3d_box
.right
= vb_pos
+ vtx_size
;
3684 vb
= wined3d_buffer_get_resource(device
->vertex_buffer
);
3685 if (FAILED(hr
= wined3d_resource_map(vb
, 0, &wined3d_map_desc
, &wined3d_box
,
3686 WINED3D_MAP_WRITE
| (vb_pos
? WINED3D_MAP_NOOVERWRITE
: WINED3D_MAP_DISCARD
))))
3688 memcpy(wined3d_map_desc
.data
, vertices
, vtx_size
);
3689 wined3d_resource_unmap(vb
, 0);
3690 device
->vertex_buffer_pos
= vb_pos
+ vtx_size
;
3692 hr
= d3d_device_prepare_index_buffer(device
, idx_size
);
3695 ib_pos
= device
->index_buffer_pos
;
3696 if (device
->index_buffer_size
- idx_size
< ib_pos
)
3699 wined3d_box
.left
= ib_pos
;
3700 wined3d_box
.right
= ib_pos
+ idx_size
;
3701 ib
= wined3d_buffer_get_resource(device
->index_buffer
);
3702 if (FAILED(hr
= wined3d_resource_map(ib
, 0, &wined3d_map_desc
, &wined3d_box
,
3703 WINED3D_MAP_WRITE
| (ib_pos
? WINED3D_MAP_NOOVERWRITE
: WINED3D_MAP_DISCARD
))))
3705 memcpy(wined3d_map_desc
.data
, indices
, idx_size
);
3706 wined3d_resource_unmap(ib
, 0);
3707 device
->index_buffer_pos
= ib_pos
+ idx_size
;
3709 hr
= wined3d_device_set_stream_source(device
->wined3d_device
, 0, device
->vertex_buffer
, 0, stride
);
3712 wined3d_device_set_index_buffer(device
->wined3d_device
, device
->index_buffer
, WINED3DFMT_R16_UINT
, 0);
3714 wined3d_device_set_vertex_declaration(device
->wined3d_device
, ddraw_find_decl(device
->ddraw
, fvf
));
3715 wined3d_device_set_primitive_type(device
->wined3d_device
, primitive_type
, 0);
3716 wined3d_device_set_base_vertex_index(device
->wined3d_device
, vb_pos
/ stride
);
3717 hr
= wined3d_device_draw_indexed_primitive(device
->wined3d_device
, ib_pos
/ sizeof(*indices
), index_count
);
3720 wined3d_mutex_unlock();
3724 static HRESULT WINAPI
d3d_device7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7
*iface
,
3725 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
, void *vertices
, DWORD vertex_count
,
3726 WORD
*indices
, DWORD index_count
, DWORD flags
)
3728 return d3d_device7_DrawIndexedPrimitive(iface
, primitive_type
, fvf
,
3729 vertices
, vertex_count
, indices
, index_count
, flags
);
3732 static HRESULT WINAPI
d3d_device7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7
*iface
,
3733 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
, void *vertices
, DWORD vertex_count
,
3734 WORD
*indices
, DWORD index_count
, DWORD flags
)
3739 old_fpucw
= d3d_fpu_setup();
3740 hr
= d3d_device7_DrawIndexedPrimitive(iface
, primitive_type
, fvf
,
3741 vertices
, vertex_count
, indices
, index_count
, flags
);
3742 set_fpu_control_word(old_fpucw
);
3747 static HRESULT WINAPI
d3d_device3_DrawIndexedPrimitive(IDirect3DDevice3
*iface
,
3748 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
, void *vertices
, DWORD vertex_count
,
3749 WORD
*indices
, DWORD index_count
, DWORD flags
)
3751 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
3753 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3754 "indices %p, index_count %u, flags %#x.\n",
3755 iface
, primitive_type
, fvf
, vertices
, vertex_count
, indices
, index_count
, flags
);
3757 setup_lighting(device
, fvf
, flags
);
3759 return IDirect3DDevice7_DrawIndexedPrimitive(&device
->IDirect3DDevice7_iface
,
3760 primitive_type
, fvf
, vertices
, vertex_count
, indices
, index_count
, flags
);
3763 static HRESULT WINAPI
d3d_device2_DrawIndexedPrimitive(IDirect3DDevice2
*iface
,
3764 D3DPRIMITIVETYPE primitive_type
, D3DVERTEXTYPE vertex_type
, void *vertices
,
3765 DWORD vertex_count
, WORD
*indices
, DWORD index_count
, DWORD flags
)
3767 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
3770 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, "
3771 "indices %p, index_count %u, flags %#x.\n",
3772 iface
, primitive_type
, vertex_type
, vertices
, vertex_count
, indices
, index_count
, flags
);
3774 switch (vertex_type
)
3776 case D3DVT_VERTEX
: fvf
= D3DFVF_VERTEX
; break;
3777 case D3DVT_LVERTEX
: fvf
= D3DFVF_LVERTEX
; break;
3778 case D3DVT_TLVERTEX
: fvf
= D3DFVF_TLVERTEX
; break;
3780 ERR("Unhandled vertex type %#x.\n", vertex_type
);
3781 return DDERR_INVALIDPARAMS
; /* Should never happen */
3784 return d3d_device3_DrawIndexedPrimitive(&device
->IDirect3DDevice3_iface
,
3785 primitive_type
, fvf
, vertices
, vertex_count
, indices
, index_count
, flags
);
3788 /*****************************************************************************
3789 * IDirect3DDevice3::End
3791 * Ends a draw begun with IDirect3DDevice3::Begin or
3792 * IDirect3DDevice::BeginIndexed. The vertices specified with
3793 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
3794 * the IDirect3DDevice3::DrawPrimitive method. So far only
3795 * non-indexed mode is supported
3800 * Flags: Some flags, as usual. Don't know which are defined
3803 * The return value of IDirect3DDevice3::DrawPrimitive
3805 *****************************************************************************/
3806 static HRESULT WINAPI
d3d_device3_End(IDirect3DDevice3
*iface
, DWORD flags
)
3808 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
3810 TRACE("iface %p, flags %#x.\n", iface
, flags
);
3812 return d3d_device3_DrawPrimitive(&device
->IDirect3DDevice3_iface
, device
->primitive_type
,
3813 device
->vertex_type
, device
->sysmem_vertex_buffer
, device
->nb_vertices
, device
->render_flags
);
3816 static HRESULT WINAPI
d3d_device2_End(IDirect3DDevice2
*iface
, DWORD flags
)
3818 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
3820 TRACE("iface %p, flags %#x.\n", iface
, flags
);
3822 return d3d_device3_End(&device
->IDirect3DDevice3_iface
, flags
);
3825 /*****************************************************************************
3826 * IDirect3DDevice7::SetClipStatus
3828 * Sets the clip status. This defines things as clipping conditions and
3829 * the extents of the clipping region.
3831 * Version 2, 3 and 7
3837 * D3D_OK because it's a stub
3838 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3840 *****************************************************************************/
3841 static HRESULT WINAPI
d3d_device7_SetClipStatus(IDirect3DDevice7
*iface
, D3DCLIPSTATUS
*clip_status
)
3843 FIXME("iface %p, clip_status %p stub!\n", iface
, clip_status
);
3848 static HRESULT WINAPI
d3d_device3_SetClipStatus(IDirect3DDevice3
*iface
, D3DCLIPSTATUS
*clip_status
)
3850 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
3852 TRACE("iface %p, clip_status %p.\n", iface
, clip_status
);
3854 return IDirect3DDevice7_SetClipStatus(&device
->IDirect3DDevice7_iface
, clip_status
);
3857 static HRESULT WINAPI
d3d_device2_SetClipStatus(IDirect3DDevice2
*iface
, D3DCLIPSTATUS
*clip_status
)
3859 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
3861 TRACE("iface %p, clip_status %p.\n", iface
, clip_status
);
3863 return IDirect3DDevice7_SetClipStatus(&device
->IDirect3DDevice7_iface
, clip_status
);
3866 /*****************************************************************************
3867 * IDirect3DDevice7::GetClipStatus
3869 * Returns the clip status
3872 * ClipStatus: Address to write the clip status to
3875 * D3D_OK because it's a stub
3877 *****************************************************************************/
3878 static HRESULT WINAPI
d3d_device7_GetClipStatus(IDirect3DDevice7
*iface
, D3DCLIPSTATUS
*clip_status
)
3880 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
3881 struct wined3d_viewport vp
;
3883 FIXME("iface %p, clip_status %p stub.\n", iface
, clip_status
);
3885 wined3d_device_get_viewports(device
->wined3d_device
, NULL
, &vp
);
3886 clip_status
->minx
= vp
.x
;
3887 clip_status
->maxx
= vp
.x
+ vp
.width
;
3888 clip_status
->miny
= vp
.y
;
3889 clip_status
->maxy
= vp
.y
+ vp
.height
;
3890 clip_status
->minz
= 0.0f
;
3891 clip_status
->maxz
= 0.0f
;
3892 clip_status
->dwFlags
= D3DCLIPSTATUS_EXTENTS2
;
3893 clip_status
->dwStatus
= 0;
3898 static HRESULT WINAPI
d3d_device3_GetClipStatus(IDirect3DDevice3
*iface
, D3DCLIPSTATUS
*clip_status
)
3900 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
3902 TRACE("iface %p, clip_status %p.\n", iface
, clip_status
);
3904 return IDirect3DDevice7_GetClipStatus(&device
->IDirect3DDevice7_iface
, clip_status
);
3907 static HRESULT WINAPI
d3d_device2_GetClipStatus(IDirect3DDevice2
*iface
, D3DCLIPSTATUS
*clip_status
)
3909 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
3911 TRACE("iface %p, clip_status %p.\n", iface
, clip_status
);
3913 return IDirect3DDevice7_GetClipStatus(&device
->IDirect3DDevice7_iface
, clip_status
);
3916 /*****************************************************************************
3917 * IDirect3DDevice::DrawPrimitiveStrided
3919 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3924 * PrimitiveType: The primitive type to draw
3925 * VertexType: The FVF description of the vertices to draw (for the stride??)
3926 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3927 * the vertex data locations
3928 * VertexCount: The number of vertices to draw
3932 * D3D_OK, because it's a stub
3933 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3935 *****************************************************************************/
3936 static void pack_strided_data(BYTE
*dst
, DWORD count
, const D3DDRAWPRIMITIVESTRIDEDDATA
*src
, DWORD fvf
)
3938 DWORD i
, tex
, offset
;
3940 for (i
= 0; i
< count
; i
++)
3942 /* The contents of the strided data are determined by the fvf,
3943 * not by the members set in src. So it's valid
3944 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3945 * not set in the fvf. */
3946 if (fvf
& D3DFVF_POSITION_MASK
)
3948 offset
= i
* src
->position
.dwStride
;
3949 if (fvf
& D3DFVF_XYZRHW
)
3951 memcpy(dst
, ((BYTE
*)src
->position
.lpvData
) + offset
, 4 * sizeof(float));
3952 dst
+= 4 * sizeof(float);
3956 memcpy(dst
, ((BYTE
*)src
->position
.lpvData
) + offset
, 3 * sizeof(float));
3957 dst
+= 3 * sizeof(float);
3961 if (fvf
& D3DFVF_NORMAL
)
3963 offset
= i
* src
->normal
.dwStride
;
3964 memcpy(dst
, ((BYTE
*)src
->normal
.lpvData
) + offset
, 3 * sizeof(float));
3965 dst
+= 3 * sizeof(float);
3968 if (fvf
& D3DFVF_DIFFUSE
)
3970 offset
= i
* src
->diffuse
.dwStride
;
3971 memcpy(dst
, ((BYTE
*)src
->diffuse
.lpvData
) + offset
, sizeof(DWORD
));
3972 dst
+= sizeof(DWORD
);
3975 if (fvf
& D3DFVF_SPECULAR
)
3977 offset
= i
* src
->specular
.dwStride
;
3978 memcpy(dst
, ((BYTE
*)src
->specular
.lpvData
) + offset
, sizeof(DWORD
));
3979 dst
+= sizeof(DWORD
);
3982 for (tex
= 0; tex
< GET_TEXCOUNT_FROM_FVF(fvf
); ++tex
)
3984 DWORD attrib_count
= GET_TEXCOORD_SIZE_FROM_FVF(fvf
, tex
);
3985 offset
= i
* src
->textureCoords
[tex
].dwStride
;
3986 memcpy(dst
, ((BYTE
*)src
->textureCoords
[tex
].lpvData
) + offset
, attrib_count
* sizeof(float));
3987 dst
+= attrib_count
* sizeof(float);
3992 static HRESULT
d3d_device7_DrawPrimitiveStrided(IDirect3DDevice7
*iface
, D3DPRIMITIVETYPE primitive_type
,
3993 DWORD fvf
, D3DDRAWPRIMITIVESTRIDEDDATA
*strided_data
, DWORD vertex_count
, DWORD flags
)
3995 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
3997 UINT dst_stride
= get_flexible_vertex_size(fvf
);
3998 UINT dst_size
= dst_stride
* vertex_count
;
3999 struct wined3d_map_desc wined3d_map_desc
;
4000 struct wined3d_box wined3d_box
= {0};
4001 struct wined3d_resource
*vb
;
4004 TRACE("iface %p, primitive_type %#x, fvf %#x, strided_data %p, vertex_count %u, flags %#x.\n",
4005 iface
, primitive_type
, fvf
, strided_data
, vertex_count
, flags
);
4009 WARN("0 vertex count.\n");
4013 wined3d_mutex_lock();
4014 hr
= d3d_device_prepare_vertex_buffer(device
, dst_size
);
4018 vb_pos
= device
->vertex_buffer_pos
;
4019 align
= vb_pos
% dst_stride
;
4020 if (align
) align
= dst_stride
- align
;
4021 if (vb_pos
+ dst_size
+ align
> device
->vertex_buffer_size
)
4026 wined3d_box
.left
= vb_pos
;
4027 wined3d_box
.right
= vb_pos
+ dst_size
;
4028 vb
= wined3d_buffer_get_resource(device
->vertex_buffer
);
4029 if (FAILED(hr
= wined3d_resource_map(vb
, 0, &wined3d_map_desc
, &wined3d_box
,
4030 WINED3D_MAP_WRITE
| (vb_pos
? WINED3D_MAP_NOOVERWRITE
: WINED3D_MAP_DISCARD
))))
4032 pack_strided_data(wined3d_map_desc
.data
, vertex_count
, strided_data
, fvf
);
4033 wined3d_resource_unmap(vb
, 0);
4034 device
->vertex_buffer_pos
= vb_pos
+ dst_size
;
4036 hr
= wined3d_device_set_stream_source(device
->wined3d_device
, 0, device
->vertex_buffer
, 0, dst_stride
);
4039 wined3d_device_set_vertex_declaration(device
->wined3d_device
, ddraw_find_decl(device
->ddraw
, fvf
));
4041 wined3d_device_set_primitive_type(device
->wined3d_device
, primitive_type
, 0);
4042 hr
= wined3d_device_draw_primitive(device
->wined3d_device
, vb_pos
/ dst_stride
, vertex_count
);
4045 wined3d_mutex_unlock();
4049 static HRESULT WINAPI
d3d_device7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7
*iface
,
4050 D3DPRIMITIVETYPE PrimitiveType
, DWORD VertexType
,
4051 D3DDRAWPRIMITIVESTRIDEDDATA
*D3DDrawPrimStrideData
, DWORD VertexCount
, DWORD Flags
)
4053 return d3d_device7_DrawPrimitiveStrided(iface
, PrimitiveType
,
4054 VertexType
, D3DDrawPrimStrideData
, VertexCount
, Flags
);
4057 static HRESULT WINAPI
d3d_device7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7
*iface
,
4058 D3DPRIMITIVETYPE PrimitiveType
, DWORD VertexType
,
4059 D3DDRAWPRIMITIVESTRIDEDDATA
*D3DDrawPrimStrideData
, DWORD VertexCount
, DWORD Flags
)
4064 old_fpucw
= d3d_fpu_setup();
4065 hr
= d3d_device7_DrawPrimitiveStrided(iface
, PrimitiveType
,
4066 VertexType
, D3DDrawPrimStrideData
, VertexCount
, Flags
);
4067 set_fpu_control_word(old_fpucw
);
4072 static HRESULT WINAPI
d3d_device3_DrawPrimitiveStrided(IDirect3DDevice3
*iface
,
4073 D3DPRIMITIVETYPE PrimitiveType
, DWORD VertexType
,
4074 D3DDRAWPRIMITIVESTRIDEDDATA
*D3DDrawPrimStrideData
, DWORD VertexCount
, DWORD Flags
)
4076 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
4078 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
4079 iface
, PrimitiveType
, VertexType
, D3DDrawPrimStrideData
, VertexCount
, Flags
);
4081 setup_lighting(device
, VertexType
, Flags
);
4083 return IDirect3DDevice7_DrawPrimitiveStrided(&device
->IDirect3DDevice7_iface
,
4084 PrimitiveType
, VertexType
, D3DDrawPrimStrideData
, VertexCount
, Flags
);
4087 /*****************************************************************************
4088 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
4090 * Draws primitives specified by strided data locations based on indices
4098 * D3D_OK, because it's a stub
4099 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
4100 * (DDERR_INVALIDPARAMS if Indices is NULL)
4102 *****************************************************************************/
4103 static HRESULT
d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7
*iface
,
4104 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
, D3DDRAWPRIMITIVESTRIDEDDATA
*strided_data
,
4105 DWORD vertex_count
, WORD
*indices
, DWORD index_count
, DWORD flags
)
4107 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
4108 UINT vtx_dst_stride
= get_flexible_vertex_size(fvf
);
4109 UINT vtx_dst_size
= vertex_count
* vtx_dst_stride
;
4110 UINT idx_size
= index_count
* sizeof(WORD
);
4111 struct wined3d_map_desc wined3d_map_desc
;
4112 struct wined3d_box wined3d_box
= {0};
4113 struct wined3d_resource
*ib
, *vb
;
4118 TRACE("iface %p, primitive_type %#x, fvf %#x, strided_data %p, "
4119 "vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4120 iface
, primitive_type
, fvf
, strided_data
, vertex_count
, indices
, index_count
, flags
);
4122 if (!vertex_count
|| !index_count
)
4124 WARN("0 vertex or index count.\n");
4128 wined3d_mutex_lock();
4130 hr
= d3d_device_prepare_vertex_buffer(device
, vtx_dst_size
);
4134 vb_pos
= device
->vertex_buffer_pos
;
4135 align
= vb_pos
% vtx_dst_stride
;
4136 if (align
) align
= vtx_dst_stride
- align
;
4137 if (vb_pos
+ vtx_dst_size
+ align
> device
->vertex_buffer_size
)
4142 wined3d_box
.left
= vb_pos
;
4143 wined3d_box
.right
= vb_pos
+ vtx_dst_size
;
4144 vb
= wined3d_buffer_get_resource(device
->vertex_buffer
);
4145 if (FAILED(hr
= wined3d_resource_map(vb
, 0, &wined3d_map_desc
, &wined3d_box
,
4146 WINED3D_MAP_WRITE
| (vb_pos
? WINED3D_MAP_NOOVERWRITE
: WINED3D_MAP_DISCARD
))))
4148 pack_strided_data(wined3d_map_desc
.data
, vertex_count
, strided_data
, fvf
);
4149 wined3d_resource_unmap(vb
, 0);
4150 device
->vertex_buffer_pos
= vb_pos
+ vtx_dst_size
;
4152 hr
= d3d_device_prepare_index_buffer(device
, idx_size
);
4155 ib_pos
= device
->index_buffer_pos
;
4156 if (device
->index_buffer_size
- idx_size
< ib_pos
)
4159 wined3d_box
.left
= ib_pos
;
4160 wined3d_box
.right
= ib_pos
+ idx_size
;
4161 ib
= wined3d_buffer_get_resource(device
->index_buffer
);
4162 if (FAILED(hr
= wined3d_resource_map(ib
, 0, &wined3d_map_desc
, &wined3d_box
,
4163 WINED3D_MAP_WRITE
| (ib_pos
? WINED3D_MAP_NOOVERWRITE
: WINED3D_MAP_DISCARD
))))
4165 memcpy(wined3d_map_desc
.data
, indices
, idx_size
);
4166 wined3d_resource_unmap(ib
, 0);
4167 device
->index_buffer_pos
= ib_pos
+ idx_size
;
4169 hr
= wined3d_device_set_stream_source(device
->wined3d_device
, 0, device
->vertex_buffer
, 0, vtx_dst_stride
);
4172 wined3d_device_set_index_buffer(device
->wined3d_device
, device
->index_buffer
, WINED3DFMT_R16_UINT
, 0);
4173 wined3d_device_set_base_vertex_index(device
->wined3d_device
, vb_pos
/ vtx_dst_stride
);
4175 wined3d_device_set_vertex_declaration(device
->wined3d_device
, ddraw_find_decl(device
->ddraw
, fvf
));
4176 wined3d_device_set_primitive_type(device
->wined3d_device
, primitive_type
, 0);
4177 hr
= wined3d_device_draw_indexed_primitive(device
->wined3d_device
, ib_pos
/ sizeof(WORD
), index_count
);
4180 wined3d_mutex_unlock();
4184 static HRESULT WINAPI
d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7
*iface
,
4185 D3DPRIMITIVETYPE PrimitiveType
, DWORD VertexType
,
4186 D3DDRAWPRIMITIVESTRIDEDDATA
*D3DDrawPrimStrideData
, DWORD VertexCount
,
4187 WORD
*Indices
, DWORD IndexCount
, DWORD Flags
)
4189 return d3d_device7_DrawIndexedPrimitiveStrided(iface
, PrimitiveType
, VertexType
,
4190 D3DDrawPrimStrideData
, VertexCount
, Indices
, IndexCount
, Flags
);
4193 static HRESULT WINAPI
d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7
*iface
,
4194 D3DPRIMITIVETYPE PrimitiveType
, DWORD VertexType
,
4195 D3DDRAWPRIMITIVESTRIDEDDATA
*D3DDrawPrimStrideData
, DWORD VertexCount
,
4196 WORD
*Indices
, DWORD IndexCount
, DWORD Flags
)
4201 old_fpucw
= d3d_fpu_setup();
4202 hr
= d3d_device7_DrawIndexedPrimitiveStrided(iface
, PrimitiveType
, VertexType
,
4203 D3DDrawPrimStrideData
, VertexCount
, Indices
, IndexCount
, Flags
);
4204 set_fpu_control_word(old_fpucw
);
4209 static HRESULT WINAPI
d3d_device3_DrawIndexedPrimitiveStrided(IDirect3DDevice3
*iface
,
4210 D3DPRIMITIVETYPE PrimitiveType
, DWORD VertexType
,
4211 D3DDRAWPRIMITIVESTRIDEDDATA
*D3DDrawPrimStrideData
, DWORD VertexCount
, WORD
*Indices
,
4212 DWORD IndexCount
, DWORD Flags
)
4214 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
4216 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4217 iface
, PrimitiveType
, VertexType
, D3DDrawPrimStrideData
, VertexCount
, Indices
, IndexCount
, Flags
);
4219 setup_lighting(device
, VertexType
, Flags
);
4221 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&device
->IDirect3DDevice7_iface
,
4222 PrimitiveType
, VertexType
, D3DDrawPrimStrideData
, VertexCount
, Indices
, IndexCount
, Flags
);
4225 /*****************************************************************************
4226 * IDirect3DDevice7::DrawPrimitiveVB
4228 * Draws primitives from a vertex buffer to the screen.
4233 * PrimitiveType: Type of primitive to be rendered.
4234 * D3DVertexBuf: Source Vertex Buffer
4235 * StartVertex: Index of the first vertex from the buffer to be rendered
4236 * NumVertices: Number of vertices to be rendered
4237 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4241 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4243 *****************************************************************************/
4244 static HRESULT
d3d_device7_DrawPrimitiveVB(IDirect3DDevice7
*iface
, D3DPRIMITIVETYPE primitive_type
,
4245 IDirect3DVertexBuffer7
*vb
, DWORD start_vertex
, DWORD vertex_count
, DWORD flags
)
4247 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
4248 struct d3d_vertex_buffer
*vb_impl
= unsafe_impl_from_IDirect3DVertexBuffer7(vb
);
4249 struct wined3d_resource
*wined3d_resource
;
4250 struct wined3d_map_desc wined3d_map_desc
;
4251 struct wined3d_box wined3d_box
= {0};
4255 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4256 iface
, primitive_type
, vb
, start_vertex
, vertex_count
, flags
);
4260 WARN("0 vertex count.\n");
4264 stride
= get_flexible_vertex_size(vb_impl
->fvf
);
4266 if (vb_impl
->Caps
& D3DVBCAPS_SYSTEMMEMORY
)
4268 TRACE("Drawing from D3DVBCAPS_SYSTEMMEMORY vertex buffer, forwarding to DrawPrimitive().\n");
4269 wined3d_mutex_lock();
4270 wined3d_resource
= wined3d_buffer_get_resource(vb_impl
->wined3d_buffer
);
4271 wined3d_box
.left
= start_vertex
* stride
;
4272 wined3d_box
.right
= wined3d_box
.left
+ vertex_count
* stride
;
4273 if (FAILED(hr
= wined3d_resource_map(wined3d_resource
, 0, &wined3d_map_desc
,
4274 &wined3d_box
, WINED3D_MAP_READ
)))
4276 wined3d_mutex_unlock();
4277 return D3DERR_VERTEXBUFFERLOCKED
;
4279 hr
= d3d_device7_DrawPrimitive(iface
, primitive_type
, vb_impl
->fvf
, wined3d_map_desc
.data
,
4280 vertex_count
, flags
);
4281 wined3d_resource_unmap(wined3d_resource
, 0);
4282 wined3d_mutex_unlock();
4286 wined3d_mutex_lock();
4287 wined3d_device_set_vertex_declaration(device
->wined3d_device
, vb_impl
->wined3d_declaration
);
4288 if (FAILED(hr
= wined3d_device_set_stream_source(device
->wined3d_device
,
4289 0, vb_impl
->wined3d_buffer
, 0, stride
)))
4291 WARN("Failed to set stream source, hr %#x.\n", hr
);
4292 wined3d_mutex_unlock();
4296 /* Now draw the primitives */
4297 wined3d_device_set_primitive_type(device
->wined3d_device
, primitive_type
, 0);
4298 hr
= wined3d_device_draw_primitive(device
->wined3d_device
, start_vertex
, vertex_count
);
4300 wined3d_mutex_unlock();
4305 static HRESULT WINAPI
d3d_device7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7
*iface
, D3DPRIMITIVETYPE PrimitiveType
,
4306 IDirect3DVertexBuffer7
*D3DVertexBuf
, DWORD StartVertex
, DWORD NumVertices
, DWORD Flags
)
4308 return d3d_device7_DrawPrimitiveVB(iface
, PrimitiveType
, D3DVertexBuf
, StartVertex
, NumVertices
, Flags
);
4311 static HRESULT WINAPI
d3d_device7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7
*iface
, D3DPRIMITIVETYPE PrimitiveType
,
4312 IDirect3DVertexBuffer7
*D3DVertexBuf
, DWORD StartVertex
, DWORD NumVertices
, DWORD Flags
)
4317 old_fpucw
= d3d_fpu_setup();
4318 hr
= d3d_device7_DrawPrimitiveVB(iface
, PrimitiveType
, D3DVertexBuf
, StartVertex
, NumVertices
, Flags
);
4319 set_fpu_control_word(old_fpucw
);
4324 static HRESULT WINAPI
d3d_device3_DrawPrimitiveVB(IDirect3DDevice3
*iface
, D3DPRIMITIVETYPE PrimitiveType
,
4325 IDirect3DVertexBuffer
*D3DVertexBuf
, DWORD StartVertex
, DWORD NumVertices
, DWORD Flags
)
4327 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
4328 struct d3d_vertex_buffer
*vb
= unsafe_impl_from_IDirect3DVertexBuffer7((IDirect3DVertexBuffer7
*)D3DVertexBuf
);
4330 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4331 iface
, PrimitiveType
, D3DVertexBuf
, StartVertex
, NumVertices
, Flags
);
4333 setup_lighting(device
, vb
->fvf
, Flags
);
4335 return IDirect3DDevice7_DrawPrimitiveVB(&device
->IDirect3DDevice7_iface
,
4336 PrimitiveType
, &vb
->IDirect3DVertexBuffer7_iface
, StartVertex
, NumVertices
, Flags
);
4339 /*****************************************************************************
4340 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4342 * Draws primitives from a vertex buffer to the screen
4345 * PrimitiveType: Type of primitive to be rendered.
4346 * D3DVertexBuf: Source Vertex Buffer
4347 * StartVertex: Index of the first vertex from the buffer to be rendered
4348 * NumVertices: Number of vertices to be rendered
4349 * Indices: Array of DWORDs used to index into the Vertices
4350 * IndexCount: Number of indices in Indices
4351 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4355 *****************************************************************************/
4356 static HRESULT
d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7
*iface
,
4357 D3DPRIMITIVETYPE primitive_type
, IDirect3DVertexBuffer7
*vb
,
4358 DWORD start_vertex
, DWORD vertex_count
, WORD
*indices
, DWORD index_count
, DWORD flags
)
4360 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
4361 struct d3d_vertex_buffer
*vb_impl
= unsafe_impl_from_IDirect3DVertexBuffer7(vb
);
4362 DWORD stride
= get_flexible_vertex_size(vb_impl
->fvf
);
4363 struct wined3d_resource
*wined3d_resource
;
4364 struct wined3d_map_desc wined3d_map_desc
;
4365 struct wined3d_box wined3d_box
= {0};
4366 struct wined3d_resource
*ib
;
4370 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, "
4371 "vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4372 iface
, primitive_type
, vb
, start_vertex
, vertex_count
, indices
, index_count
, flags
);
4374 if (!vertex_count
|| !index_count
)
4376 WARN("0 vertex or index count.\n");
4380 if (vb_impl
->Caps
& D3DVBCAPS_SYSTEMMEMORY
)
4382 TRACE("Drawing from D3DVBCAPS_SYSTEMMEMORY vertex buffer, forwarding to DrawIndexedPrimitive().\n");
4383 wined3d_mutex_lock();
4384 wined3d_box
.left
= start_vertex
* stride
;
4385 wined3d_box
.right
= wined3d_box
.left
+ vertex_count
* stride
;
4386 wined3d_resource
= wined3d_buffer_get_resource(vb_impl
->wined3d_buffer
);
4387 if (FAILED(hr
= wined3d_resource_map(wined3d_resource
, 0, &wined3d_map_desc
,
4388 &wined3d_box
, WINED3D_MAP_READ
)))
4390 wined3d_mutex_unlock();
4391 return D3DERR_VERTEXBUFFERLOCKED
;
4393 hr
= d3d_device7_DrawIndexedPrimitive(iface
, primitive_type
, vb_impl
->fvf
,
4394 wined3d_map_desc
.data
, vertex_count
, indices
, index_count
, flags
);
4395 wined3d_resource_unmap(wined3d_resource
, 0);
4396 wined3d_mutex_unlock();
4401 * 1) Upload the indices to the index buffer
4402 * 2) Set the index source
4403 * 3) Set the Vertex Buffer as the Stream source
4404 * 4) Call wined3d_device_draw_indexed_primitive()
4407 wined3d_mutex_lock();
4409 wined3d_device_set_vertex_declaration(device
->wined3d_device
, vb_impl
->wined3d_declaration
);
4411 hr
= d3d_device_prepare_index_buffer(device
, index_count
* sizeof(WORD
));
4414 wined3d_mutex_unlock();
4417 ib_pos
= device
->index_buffer_pos
;
4419 if (device
->index_buffer_size
- index_count
* sizeof(WORD
) < ib_pos
)
4422 /* Copy the index stream into the index buffer. */
4423 wined3d_box
.left
= ib_pos
;
4424 wined3d_box
.right
= ib_pos
+ index_count
* sizeof(WORD
);
4425 ib
= wined3d_buffer_get_resource(device
->index_buffer
);
4426 if (FAILED(hr
= wined3d_resource_map(ib
, 0, &wined3d_map_desc
, &wined3d_box
,
4427 WINED3D_MAP_WRITE
| (ib_pos
? WINED3D_MAP_NOOVERWRITE
: WINED3D_MAP_DISCARD
))))
4429 ERR("Failed to map buffer, hr %#x.\n", hr
);
4430 wined3d_mutex_unlock();
4433 memcpy(wined3d_map_desc
.data
, indices
, index_count
* sizeof(WORD
));
4434 wined3d_resource_unmap(ib
, 0);
4435 device
->index_buffer_pos
= ib_pos
+ index_count
* sizeof(WORD
);
4437 /* Set the index stream */
4438 wined3d_device_set_base_vertex_index(device
->wined3d_device
, start_vertex
);
4439 wined3d_device_set_index_buffer(device
->wined3d_device
, device
->index_buffer
, WINED3DFMT_R16_UINT
, 0);
4441 /* Set the vertex stream source */
4442 if (FAILED(hr
= wined3d_device_set_stream_source(device
->wined3d_device
,
4443 0, vb_impl
->wined3d_buffer
, 0, stride
)))
4445 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", device
, hr
);
4446 wined3d_mutex_unlock();
4450 wined3d_device_set_primitive_type(device
->wined3d_device
, primitive_type
, 0);
4451 hr
= wined3d_device_draw_indexed_primitive(device
->wined3d_device
, ib_pos
/ sizeof(WORD
), index_count
);
4453 wined3d_mutex_unlock();
4458 static HRESULT WINAPI
d3d_device7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7
*iface
,
4459 D3DPRIMITIVETYPE PrimitiveType
, IDirect3DVertexBuffer7
*D3DVertexBuf
,
4460 DWORD StartVertex
, DWORD NumVertices
, WORD
*Indices
, DWORD IndexCount
, DWORD Flags
)
4462 return d3d_device7_DrawIndexedPrimitiveVB(iface
, PrimitiveType
,
4463 D3DVertexBuf
, StartVertex
, NumVertices
, Indices
, IndexCount
, Flags
);
4466 static HRESULT WINAPI
d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7
*iface
,
4467 D3DPRIMITIVETYPE PrimitiveType
, IDirect3DVertexBuffer7
*D3DVertexBuf
,
4468 DWORD StartVertex
, DWORD NumVertices
, WORD
*Indices
, DWORD IndexCount
, DWORD Flags
)
4473 old_fpucw
= d3d_fpu_setup();
4474 hr
= d3d_device7_DrawIndexedPrimitiveVB(iface
, PrimitiveType
,
4475 D3DVertexBuf
, StartVertex
, NumVertices
, Indices
, IndexCount
, Flags
);
4476 set_fpu_control_word(old_fpucw
);
4481 static HRESULT WINAPI
d3d_device3_DrawIndexedPrimitiveVB(IDirect3DDevice3
*iface
,
4482 D3DPRIMITIVETYPE primitive_type
, IDirect3DVertexBuffer
*vertex_buffer
,
4483 WORD
*indices
, DWORD index_count
, DWORD flags
)
4485 struct d3d_vertex_buffer
*vb
=
4486 unsafe_impl_from_IDirect3DVertexBuffer7((IDirect3DVertexBuffer7
*)vertex_buffer
);
4487 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
4490 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4491 iface
, primitive_type
, vertex_buffer
, indices
, index_count
, flags
);
4493 setup_lighting(device
, vb
->fvf
, flags
);
4495 if (!(stride
= get_flexible_vertex_size(vb
->fvf
)))
4498 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&device
->IDirect3DDevice7_iface
, primitive_type
,
4499 &vb
->IDirect3DVertexBuffer7_iface
, 0, vb
->size
/ stride
, indices
, index_count
, flags
);
4502 /*****************************************************************************
4503 * IDirect3DDevice7::ComputeSphereVisibility
4505 * Calculates the visibility of spheres in the current viewport. The spheres
4506 * are passed in the Centers and Radii arrays, the results are passed back
4507 * in the ReturnValues array. Return values are either completely visible,
4508 * partially visible or completely invisible.
4509 * The return value consists of a combination of D3DCLIP_* flags, or is
4510 * 0 if the sphere is completely visible (according to the SDK, not checked)
4515 * Centers: Array containing the sphere centers
4516 * Radii: Array containing the sphere radii
4517 * NumSpheres: The number of centers and radii in the arrays
4519 * ReturnValues: Array to write the results to
4523 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4524 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4527 *****************************************************************************/
4529 static DWORD
in_plane(UINT idx
, struct wined3d_vec4 p
, D3DVECTOR center
, D3DVALUE radius
, BOOL equality
)
4531 float distance
, norm
;
4533 norm
= sqrtf(p
.x
* p
.x
+ p
.y
* p
.y
+ p
.z
* p
.z
);
4534 distance
= (p
.x
* center
.u1
.x
+ p
.y
* center
.u2
.y
+ p
.z
* center
.u3
.z
+ p
.w
) / norm
;
4538 if (fabs(distance
) <= radius
)
4539 return D3DSTATUS_CLIPUNIONLEFT
<< idx
;
4540 if (distance
<= -radius
)
4541 return (D3DSTATUS_CLIPUNIONLEFT
| D3DSTATUS_CLIPINTERSECTIONLEFT
) << idx
;
4545 if (fabs(distance
) < radius
)
4546 return D3DSTATUS_CLIPUNIONLEFT
<< idx
;
4547 if (distance
< -radius
)
4548 return (D3DSTATUS_CLIPUNIONLEFT
| D3DSTATUS_CLIPINTERSECTIONLEFT
) << idx
;
4553 static void prepare_clip_space_planes(struct d3d_device
*device
, struct wined3d_vec4
*plane
)
4557 /* We want the wined3d matrices since those include the legacy viewport
4558 * transformation. */
4559 wined3d_mutex_lock();
4560 wined3d_device_get_transform(device
->wined3d_device
,
4561 WINED3D_TS_WORLD
, (struct wined3d_matrix
*)&m
);
4563 wined3d_device_get_transform(device
->wined3d_device
,
4564 WINED3D_TS_VIEW
, (struct wined3d_matrix
*)&temp
);
4565 multiply_matrix(&m
, &temp
, &m
);
4567 wined3d_device_get_transform(device
->wined3d_device
,
4568 WINED3D_TS_PROJECTION
, (struct wined3d_matrix
*)&temp
);
4569 multiply_matrix(&m
, &temp
, &m
);
4570 wined3d_mutex_unlock();
4573 plane
[0].x
= m
._14
+ m
._11
;
4574 plane
[0].y
= m
._24
+ m
._21
;
4575 plane
[0].z
= m
._34
+ m
._31
;
4576 plane
[0].w
= m
._44
+ m
._41
;
4579 plane
[1].x
= m
._14
- m
._11
;
4580 plane
[1].y
= m
._24
- m
._21
;
4581 plane
[1].z
= m
._34
- m
._31
;
4582 plane
[1].w
= m
._44
- m
._41
;
4585 plane
[2].x
= m
._14
- m
._12
;
4586 plane
[2].y
= m
._24
- m
._22
;
4587 plane
[2].z
= m
._34
- m
._32
;
4588 plane
[2].w
= m
._44
- m
._42
;
4591 plane
[3].x
= m
._14
+ m
._12
;
4592 plane
[3].y
= m
._24
+ m
._22
;
4593 plane
[3].z
= m
._34
+ m
._32
;
4594 plane
[3].w
= m
._44
+ m
._42
;
4603 plane
[5].x
= m
._14
- m
._13
;
4604 plane
[5].y
= m
._24
- m
._23
;
4605 plane
[5].z
= m
._34
- m
._33
;
4606 plane
[5].w
= m
._44
- m
._43
;
4609 static void compute_sphere_visibility(struct wined3d_vec4 plane
[12], DWORD enabled_planes
, BOOL equality
,
4610 D3DVECTOR
*centers
, D3DVALUE
*radii
, DWORD sphere_count
, DWORD
*return_values
)
4614 for (i
= 0; i
< sphere_count
; ++i
)
4616 return_values
[i
] = 0;
4617 for (j
= 0; j
< 12; ++j
)
4618 if (enabled_planes
& 1u << j
)
4619 return_values
[i
] |= in_plane(j
, plane
[j
], centers
[i
], radii
[i
], equality
);
4623 static HRESULT WINAPI
d3d_device7_ComputeSphereVisibility(IDirect3DDevice7
*iface
,
4624 D3DVECTOR
*centers
, D3DVALUE
*radii
, DWORD sphere_count
, DWORD flags
, DWORD
*return_values
)
4626 struct wined3d_vec4 plane
[12];
4627 DWORD enabled_planes
= 0x3f;
4628 DWORD user_clip_planes
;
4631 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4632 iface
, centers
, radii
, sphere_count
, flags
, return_values
);
4634 prepare_clip_space_planes(impl_from_IDirect3DDevice7(iface
), plane
);
4636 IDirect3DDevice7_GetRenderState(iface
, D3DRENDERSTATE_CLIPPLANEENABLE
, &user_clip_planes
);
4637 enabled_planes
|= user_clip_planes
<< 6;
4638 for (j
= 6; j
< 12; ++j
)
4639 IDirect3DDevice7_GetClipPlane(iface
, j
- 6, (D3DVALUE
*)&plane
[j
]);
4641 compute_sphere_visibility(plane
, enabled_planes
, FALSE
, centers
, radii
, sphere_count
, return_values
);
4645 static HRESULT WINAPI
d3d_device3_ComputeSphereVisibility(IDirect3DDevice3
*iface
,
4646 D3DVECTOR
*centers
, D3DVALUE
*radii
, DWORD sphere_count
, DWORD flags
, DWORD
*return_values
)
4648 static const DWORD enabled_planes
= 0x3f;
4649 struct wined3d_vec4 plane
[6];
4652 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4653 iface
, centers
, radii
, sphere_count
, flags
, return_values
);
4655 prepare_clip_space_planes(impl_from_IDirect3DDevice3(iface
), plane
);
4657 compute_sphere_visibility(plane
, enabled_planes
, TRUE
, centers
, radii
, sphere_count
, return_values
);
4658 for (i
= 0; i
< sphere_count
; ++i
)
4660 BOOL intersect_frustum
= FALSE
, outside_frustum
= FALSE
;
4661 DWORD d3d7_result
= return_values
[i
];
4663 return_values
[i
] = 0;
4665 for (j
= 0; j
< 6; ++j
)
4667 DWORD clip
= (d3d7_result
>> j
) & (D3DSTATUS_CLIPUNIONLEFT
| D3DSTATUS_CLIPINTERSECTIONLEFT
);
4669 if (clip
== D3DSTATUS_CLIPUNIONLEFT
)
4671 return_values
[i
] |= D3DVIS_INTERSECT_LEFT
<< j
* 2;
4672 intersect_frustum
= TRUE
;
4676 return_values
[i
] |= D3DVIS_OUTSIDE_LEFT
<< j
* 2;
4677 outside_frustum
= TRUE
;
4680 if (outside_frustum
)
4681 return_values
[i
] |= D3DVIS_OUTSIDE_FRUSTUM
;
4682 else if (intersect_frustum
)
4683 return_values
[i
] |= D3DVIS_INTERSECT_FRUSTUM
;
4688 /*****************************************************************************
4689 * IDirect3DDevice7::GetTexture
4691 * Returns the texture interface handle assigned to a texture stage.
4692 * The returned texture is AddRefed. This is taken from old ddraw,
4693 * not checked in Windows.
4698 * Stage: Texture stage to read the texture from
4699 * Texture: Address to store the interface pointer at
4703 * DDERR_INVALIDPARAMS if Texture is NULL
4705 *****************************************************************************/
4706 static HRESULT
d3d_device7_GetTexture(IDirect3DDevice7
*iface
,
4707 DWORD stage
, IDirectDrawSurface7
**texture
)
4709 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
4710 struct wined3d_texture
*wined3d_texture
;
4711 struct ddraw_texture
*ddraw_texture
;
4713 TRACE("iface %p, stage %u, texture %p.\n", iface
, stage
, texture
);
4716 return DDERR_INVALIDPARAMS
;
4718 wined3d_mutex_lock();
4719 if (!(wined3d_texture
= wined3d_device_get_texture(device
->wined3d_device
, stage
)))
4722 wined3d_mutex_unlock();
4726 ddraw_texture
= wined3d_texture_get_parent(wined3d_texture
);
4727 *texture
= &ddraw_texture
->root
->IDirectDrawSurface7_iface
;
4728 IDirectDrawSurface7_AddRef(*texture
);
4729 wined3d_mutex_unlock();
4734 static HRESULT WINAPI
d3d_device7_GetTexture_FPUSetup(IDirect3DDevice7
*iface
,
4735 DWORD stage
, IDirectDrawSurface7
**Texture
)
4737 return d3d_device7_GetTexture(iface
, stage
, Texture
);
4740 static HRESULT WINAPI
d3d_device7_GetTexture_FPUPreserve(IDirect3DDevice7
*iface
,
4741 DWORD stage
, IDirectDrawSurface7
**Texture
)
4746 old_fpucw
= d3d_fpu_setup();
4747 hr
= d3d_device7_GetTexture(iface
, stage
, Texture
);
4748 set_fpu_control_word(old_fpucw
);
4753 static HRESULT WINAPI
d3d_device3_GetTexture(IDirect3DDevice3
*iface
, DWORD stage
, IDirect3DTexture2
**Texture2
)
4755 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
4756 struct ddraw_surface
*ret_val_impl
;
4758 IDirectDrawSurface7
*ret_val
;
4760 TRACE("iface %p, stage %u, texture %p.\n", iface
, stage
, Texture2
);
4762 ret
= IDirect3DDevice7_GetTexture(&device
->IDirect3DDevice7_iface
, stage
, &ret_val
);
4764 ret_val_impl
= unsafe_impl_from_IDirectDrawSurface7(ret_val
);
4765 *Texture2
= ret_val_impl
? &ret_val_impl
->IDirect3DTexture2_iface
: NULL
;
4767 TRACE("Returning texture %p.\n", *Texture2
);
4772 /*****************************************************************************
4773 * IDirect3DDevice7::SetTexture
4775 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4780 * Stage: The stage to assign the texture to
4781 * Texture: Interface pointer to the texture surface
4786 *****************************************************************************/
4787 static HRESULT
d3d_device7_SetTexture(IDirect3DDevice7
*iface
,
4788 DWORD stage
, IDirectDrawSurface7
*texture
)
4790 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
4791 struct ddraw_surface
*surf
= unsafe_impl_from_IDirectDrawSurface7(texture
);
4792 struct wined3d_texture
*wined3d_texture
= NULL
;
4794 TRACE("iface %p, stage %u, texture %p.\n", iface
, stage
, texture
);
4796 if (surf
&& (surf
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_TEXTURE
))
4797 wined3d_texture
= surf
->wined3d_texture
;
4799 wined3d_mutex_lock();
4800 wined3d_device_set_texture(device
->wined3d_device
, stage
, wined3d_texture
);
4801 wined3d_mutex_unlock();
4806 static HRESULT WINAPI
d3d_device7_SetTexture_FPUSetup(IDirect3DDevice7
*iface
,
4807 DWORD stage
, IDirectDrawSurface7
*texture
)
4809 return d3d_device7_SetTexture(iface
, stage
, texture
);
4812 static HRESULT WINAPI
d3d_device7_SetTexture_FPUPreserve(IDirect3DDevice7
*iface
,
4813 DWORD stage
, IDirectDrawSurface7
*texture
)
4818 old_fpucw
= d3d_fpu_setup();
4819 hr
= d3d_device7_SetTexture(iface
, stage
, texture
);
4820 set_fpu_control_word(old_fpucw
);
4825 static HRESULT WINAPI
d3d_device3_SetTexture(IDirect3DDevice3
*iface
,
4826 DWORD stage
, IDirect3DTexture2
*texture
)
4828 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
4829 struct ddraw_surface
*tex
= unsafe_impl_from_IDirect3DTexture2(texture
);
4832 TRACE("iface %p, stage %u, texture %p.\n", iface
, stage
, texture
);
4834 wined3d_mutex_lock();
4836 hr
= IDirect3DDevice7_SetTexture(&device
->IDirect3DDevice7_iface
, stage
, &tex
->IDirectDrawSurface7_iface
);
4838 fixup_texture_alpha_op(device
);
4840 wined3d_mutex_unlock();
4845 static const struct tss_lookup
4850 enum wined3d_texture_stage_state texture_state
;
4851 enum wined3d_sampler_state sampler_state
;
4856 {FALSE
, {WINED3D_TSS_INVALID
}}, /* 0, unused */
4857 {FALSE
, {WINED3D_TSS_COLOR_OP
}}, /* 1, D3DTSS_COLOROP */
4858 {FALSE
, {WINED3D_TSS_COLOR_ARG1
}}, /* 2, D3DTSS_COLORARG1 */
4859 {FALSE
, {WINED3D_TSS_COLOR_ARG2
}}, /* 3, D3DTSS_COLORARG2 */
4860 {FALSE
, {WINED3D_TSS_ALPHA_OP
}}, /* 4, D3DTSS_ALPHAOP */
4861 {FALSE
, {WINED3D_TSS_ALPHA_ARG1
}}, /* 5, D3DTSS_ALPHAARG1 */
4862 {FALSE
, {WINED3D_TSS_ALPHA_ARG2
}}, /* 6, D3DTSS_ALPHAARG2 */
4863 {FALSE
, {WINED3D_TSS_BUMPENV_MAT00
}}, /* 7, D3DTSS_BUMPENVMAT00 */
4864 {FALSE
, {WINED3D_TSS_BUMPENV_MAT01
}}, /* 8, D3DTSS_BUMPENVMAT01 */
4865 {FALSE
, {WINED3D_TSS_BUMPENV_MAT10
}}, /* 9, D3DTSS_BUMPENVMAT10 */
4866 {FALSE
, {WINED3D_TSS_BUMPENV_MAT11
}}, /* 10, D3DTSS_BUMPENVMAT11 */
4867 {FALSE
, {WINED3D_TSS_TEXCOORD_INDEX
}}, /* 11, D3DTSS_TEXCOORDINDEX */
4868 {TRUE
, {WINED3D_SAMP_ADDRESS_U
}}, /* 12, D3DTSS_ADDRESS */
4869 {TRUE
, {WINED3D_SAMP_ADDRESS_U
}}, /* 13, D3DTSS_ADDRESSU */
4870 {TRUE
, {WINED3D_SAMP_ADDRESS_V
}}, /* 14, D3DTSS_ADDRESSV */
4871 {TRUE
, {WINED3D_SAMP_BORDER_COLOR
}}, /* 15, D3DTSS_BORDERCOLOR */
4872 {TRUE
, {WINED3D_SAMP_MAG_FILTER
}}, /* 16, D3DTSS_MAGFILTER */
4873 {TRUE
, {WINED3D_SAMP_MIN_FILTER
}}, /* 17, D3DTSS_MINFILTER */
4874 {TRUE
, {WINED3D_SAMP_MIP_FILTER
}}, /* 18, D3DTSS_MIPFILTER */
4875 {TRUE
, {WINED3D_SAMP_MIPMAP_LOD_BIAS
}}, /* 19, D3DTSS_MIPMAPLODBIAS */
4876 {TRUE
, {WINED3D_SAMP_MAX_MIP_LEVEL
}}, /* 20, D3DTSS_MAXMIPLEVEL */
4877 {TRUE
, {WINED3D_SAMP_MAX_ANISOTROPY
}}, /* 21, D3DTSS_MAXANISOTROPY */
4878 {FALSE
, {WINED3D_TSS_BUMPENV_LSCALE
}}, /* 22, D3DTSS_BUMPENVLSCALE */
4879 {FALSE
, {WINED3D_TSS_BUMPENV_LOFFSET
}}, /* 23, D3DTSS_BUMPENVLOFFSET */
4880 {FALSE
, {WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS
}}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4883 /*****************************************************************************
4884 * IDirect3DDevice7::GetTextureStageState
4886 * Retrieves a state from a texture stage.
4891 * Stage: The stage to retrieve the state from
4892 * TexStageStateType: The state type to retrieve
4893 * State: Address to store the state's value at
4897 * DDERR_INVALIDPARAMS if State is NULL
4899 *****************************************************************************/
4900 static HRESULT
d3d_device7_GetTextureStageState(IDirect3DDevice7
*iface
,
4901 DWORD stage
, D3DTEXTURESTAGESTATETYPE state
, DWORD
*value
)
4903 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
4904 const struct tss_lookup
*l
;
4906 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4907 iface
, stage
, state
, value
);
4910 return DDERR_INVALIDPARAMS
;
4912 if (state
> D3DTSS_TEXTURETRANSFORMFLAGS
)
4914 WARN("Invalid state %#x passed.\n", state
);
4918 l
= &tss_lookup
[state
];
4920 wined3d_mutex_lock();
4922 if (l
->sampler_state
)
4924 *value
= wined3d_device_get_sampler_state(device
->wined3d_device
, stage
, l
->u
.sampler_state
);
4928 /* Mipfilter is a sampler state with different values */
4929 case D3DTSS_MIPFILTER
:
4933 case WINED3D_TEXF_NONE
:
4934 *value
= D3DTFP_NONE
;
4936 case WINED3D_TEXF_POINT
:
4937 *value
= D3DTFP_POINT
;
4939 case WINED3D_TEXF_LINEAR
:
4940 *value
= D3DTFP_LINEAR
;
4943 ERR("Unexpected mipfilter value %#x.\n", *value
);
4944 *value
= D3DTFP_NONE
;
4950 /* Magfilter has slightly different values */
4951 case D3DTSS_MAGFILTER
:
4955 case WINED3D_TEXF_POINT
:
4956 *value
= D3DTFG_POINT
;
4958 case WINED3D_TEXF_LINEAR
:
4959 *value
= D3DTFG_LINEAR
;
4961 case WINED3D_TEXF_ANISOTROPIC
:
4962 *value
= D3DTFG_ANISOTROPIC
;
4964 case WINED3D_TEXF_FLAT_CUBIC
:
4965 *value
= D3DTFG_FLATCUBIC
;
4967 case WINED3D_TEXF_GAUSSIAN_CUBIC
:
4968 *value
= D3DTFG_GAUSSIANCUBIC
;
4971 ERR("Unexpected wined3d mag filter value %#x.\n", *value
);
4972 *value
= D3DTFG_POINT
;
4984 *value
= wined3d_device_get_texture_stage_state(device
->wined3d_device
, stage
, l
->u
.texture_state
);
4987 wined3d_mutex_unlock();
4992 static HRESULT WINAPI
d3d_device7_GetTextureStageState_FPUSetup(IDirect3DDevice7
*iface
,
4993 DWORD stage
, D3DTEXTURESTAGESTATETYPE state
, DWORD
*value
)
4995 return d3d_device7_GetTextureStageState(iface
, stage
, state
, value
);
4998 static HRESULT WINAPI
d3d_device7_GetTextureStageState_FPUPreserve(IDirect3DDevice7
*iface
,
4999 DWORD stage
, D3DTEXTURESTAGESTATETYPE state
, DWORD
*value
)
5004 old_fpucw
= d3d_fpu_setup();
5005 hr
= d3d_device7_GetTextureStageState(iface
, stage
, state
, value
);
5006 set_fpu_control_word(old_fpucw
);
5011 static HRESULT WINAPI
d3d_device3_GetTextureStageState(IDirect3DDevice3
*iface
,
5012 DWORD stage
, D3DTEXTURESTAGESTATETYPE state
, DWORD
*value
)
5014 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
5016 TRACE("iface %p, stage %u, state %#x, value %p.\n",
5017 iface
, stage
, state
, value
);
5019 return IDirect3DDevice7_GetTextureStageState(&device
->IDirect3DDevice7_iface
, stage
, state
, value
);
5022 /*****************************************************************************
5023 * IDirect3DDevice7::SetTextureStageState
5025 * Sets a texture stage state. Some stage types need to be handled specially,
5026 * because they do not exist in WineD3D and were moved to another place
5031 * Stage: The stage to modify
5032 * TexStageStateType: The state to change
5033 * State: The new value for the state
5038 *****************************************************************************/
5039 static HRESULT
d3d_device7_SetTextureStageState(IDirect3DDevice7
*iface
,
5040 DWORD stage
, D3DTEXTURESTAGESTATETYPE state
, DWORD value
)
5042 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5043 const struct tss_lookup
*l
;
5045 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5046 iface
, stage
, state
, value
);
5048 if (state
> D3DTSS_TEXTURETRANSFORMFLAGS
)
5050 WARN("Invalid state %#x passed.\n", state
);
5054 l
= &tss_lookup
[state
];
5056 wined3d_mutex_lock();
5058 if (l
->sampler_state
)
5062 /* Mipfilter is a sampler state with different values */
5063 case D3DTSS_MIPFILTER
:
5068 value
= WINED3D_TEXF_NONE
;
5071 value
= WINED3D_TEXF_POINT
;
5073 case 0: /* Unchecked */
5075 value
= WINED3D_TEXF_LINEAR
;
5078 ERR("Unexpected mipfilter value %#x.\n", value
);
5079 value
= WINED3D_TEXF_NONE
;
5085 /* Magfilter has slightly different values */
5086 case D3DTSS_MAGFILTER
:
5091 value
= WINED3D_TEXF_POINT
;
5094 value
= WINED3D_TEXF_LINEAR
;
5096 case D3DTFG_FLATCUBIC
:
5097 value
= WINED3D_TEXF_FLAT_CUBIC
;
5099 case D3DTFG_GAUSSIANCUBIC
:
5100 value
= WINED3D_TEXF_GAUSSIAN_CUBIC
;
5102 case D3DTFG_ANISOTROPIC
:
5103 value
= WINED3D_TEXF_ANISOTROPIC
;
5106 ERR("Unexpected d3d7 mag filter value %#x.\n", value
);
5107 value
= WINED3D_TEXF_POINT
;
5113 case D3DTSS_ADDRESS
:
5114 wined3d_device_set_sampler_state(device
->wined3d_device
, stage
, WINED3D_SAMP_ADDRESS_V
, value
);
5121 wined3d_device_set_sampler_state(device
->wined3d_device
, stage
, l
->u
.sampler_state
, value
);
5125 wined3d_device_set_texture_stage_state(device
->wined3d_device
, stage
, l
->u
.texture_state
, value
);
5128 wined3d_mutex_unlock();
5133 static HRESULT WINAPI
d3d_device7_SetTextureStageState_FPUSetup(IDirect3DDevice7
*iface
,
5134 DWORD stage
, D3DTEXTURESTAGESTATETYPE state
, DWORD value
)
5136 return d3d_device7_SetTextureStageState(iface
, stage
, state
, value
);
5139 static HRESULT WINAPI
d3d_device7_SetTextureStageState_FPUPreserve(IDirect3DDevice7
*iface
,
5140 DWORD stage
, D3DTEXTURESTAGESTATETYPE state
, DWORD value
)
5145 old_fpucw
= d3d_fpu_setup();
5146 hr
= d3d_device7_SetTextureStageState(iface
, stage
, state
, value
);
5147 set_fpu_control_word(old_fpucw
);
5152 static HRESULT WINAPI
d3d_device3_SetTextureStageState(IDirect3DDevice3
*iface
,
5153 DWORD stage
, D3DTEXTURESTAGESTATETYPE state
, DWORD value
)
5155 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
5159 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5160 iface
, stage
, state
, value
);
5162 /* Tests show that legacy texture blending is not reset if the texture stage state
5163 * value is unchanged. */
5164 if (FAILED(hr
= IDirect3DDevice7_GetTextureStageState(&device
->IDirect3DDevice7_iface
,
5165 stage
, state
, &old_value
)))
5168 if (old_value
== value
)
5170 TRACE("Application is setting the same value over, nothing to do.\n");
5174 device
->legacyTextureBlending
= FALSE
;
5176 return IDirect3DDevice7_SetTextureStageState(&device
->IDirect3DDevice7_iface
, stage
, state
, value
);
5179 /*****************************************************************************
5180 * IDirect3DDevice7::ValidateDevice
5182 * SDK: "Reports the device's ability to render the currently set
5183 * texture-blending operations in a single pass". Whatever that means
5189 * NumPasses: Address to write the number of necessary passes for the
5190 * desired effect to.
5195 *****************************************************************************/
5196 static HRESULT
d3d_device7_ValidateDevice(IDirect3DDevice7
*iface
, DWORD
*pass_count
)
5198 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5201 TRACE("iface %p, pass_count %p.\n", iface
, pass_count
);
5203 wined3d_mutex_lock();
5204 hr
= wined3d_device_validate_device(device
->wined3d_device
, pass_count
);
5205 wined3d_mutex_unlock();
5210 static HRESULT WINAPI
d3d_device7_ValidateDevice_FPUSetup(IDirect3DDevice7
*iface
, DWORD
*pass_count
)
5212 return d3d_device7_ValidateDevice(iface
, pass_count
);
5215 static HRESULT WINAPI
d3d_device7_ValidateDevice_FPUPreserve(IDirect3DDevice7
*iface
, DWORD
*pass_count
)
5220 old_fpucw
= d3d_fpu_setup();
5221 hr
= d3d_device7_ValidateDevice(iface
, pass_count
);
5222 set_fpu_control_word(old_fpucw
);
5227 static HRESULT WINAPI
d3d_device3_ValidateDevice(IDirect3DDevice3
*iface
, DWORD
*pass_count
)
5229 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
5231 TRACE("iface %p, pass_count %p.\n", iface
, pass_count
);
5233 return IDirect3DDevice7_ValidateDevice(&device
->IDirect3DDevice7_iface
, pass_count
);
5236 /*****************************************************************************
5237 * IDirect3DDevice7::Clear
5239 * Fills the render target, the z buffer and the stencil buffer with a
5240 * clear color / value
5245 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5246 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5247 * Flags: Some flags, as usual
5248 * Color: Clear color for the render target
5249 * Z: Clear value for the Z buffer
5250 * Stencil: Clear value to store in each stencil buffer entry
5255 *****************************************************************************/
5256 static HRESULT
d3d_device7_Clear(IDirect3DDevice7
*iface
, DWORD count
,
5257 D3DRECT
*rects
, DWORD flags
, D3DCOLOR color
, D3DVALUE z
, DWORD stencil
)
5259 const struct wined3d_color c
=
5261 ((color
>> 16) & 0xff) / 255.0f
,
5262 ((color
>> 8) & 0xff) / 255.0f
,
5263 (color
& 0xff) / 255.0f
,
5264 ((color
>> 24) & 0xff) / 255.0f
,
5266 struct d3d_device
*This
= impl_from_IDirect3DDevice7(iface
);
5269 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5270 iface
, count
, rects
, flags
, color
, z
, stencil
);
5272 if (count
&& !rects
)
5274 WARN("count %u with NULL rects.\n", count
);
5278 wined3d_mutex_lock();
5279 hr
= wined3d_device_clear(This
->wined3d_device
, count
, (RECT
*)rects
, flags
, &c
, z
, stencil
);
5280 wined3d_mutex_unlock();
5285 static HRESULT WINAPI
d3d_device7_Clear_FPUSetup(IDirect3DDevice7
*iface
, DWORD count
,
5286 D3DRECT
*rects
, DWORD flags
, D3DCOLOR color
, D3DVALUE z
, DWORD stencil
)
5288 return d3d_device7_Clear(iface
, count
, rects
, flags
, color
, z
, stencil
);
5291 static HRESULT WINAPI
d3d_device7_Clear_FPUPreserve(IDirect3DDevice7
*iface
, DWORD count
,
5292 D3DRECT
*rects
, DWORD flags
, D3DCOLOR color
, D3DVALUE z
, DWORD stencil
)
5297 old_fpucw
= d3d_fpu_setup();
5298 hr
= d3d_device7_Clear(iface
, count
, rects
, flags
, color
, z
, stencil
);
5299 set_fpu_control_word(old_fpucw
);
5304 static HRESULT
d3d_device7_SetViewport(IDirect3DDevice7
*iface
, D3DVIEWPORT7
*viewport
)
5306 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5307 struct wined3d_sub_resource_desc rt_desc
;
5308 struct wined3d_rendertarget_view
*rtv
;
5309 struct ddraw_surface
*surface
;
5310 struct wined3d_viewport vp
;
5312 TRACE("iface %p, viewport %p.\n", iface
, viewport
);
5315 return DDERR_INVALIDPARAMS
;
5317 wined3d_mutex_lock();
5318 if (!(rtv
= wined3d_device_get_rendertarget_view(device
->wined3d_device
, 0)))
5320 wined3d_mutex_unlock();
5321 return DDERR_INVALIDCAPS
;
5323 surface
= wined3d_rendertarget_view_get_sub_resource_parent(rtv
);
5324 wined3d_texture_get_sub_resource_desc(surface
->wined3d_texture
, surface
->sub_resource_idx
, &rt_desc
);
5326 if (viewport
->dwX
> rt_desc
.width
|| viewport
->dwWidth
> rt_desc
.width
- viewport
->dwX
5327 || viewport
->dwY
> rt_desc
.height
|| viewport
->dwHeight
> rt_desc
.height
- viewport
->dwY
)
5329 WARN("Invalid viewport, returning E_INVALIDARG.\n");
5330 wined3d_mutex_unlock();
5331 return E_INVALIDARG
;
5334 vp
.x
= viewport
->dwX
;
5335 vp
.y
= viewport
->dwY
;
5336 vp
.width
= viewport
->dwWidth
;
5337 vp
.height
= viewport
->dwHeight
;
5338 vp
.min_z
= viewport
->dvMinZ
;
5339 vp
.max_z
= viewport
->dvMaxZ
;
5341 wined3d_device_set_viewports(device
->wined3d_device
, 1, &vp
);
5342 wined3d_mutex_unlock();
5347 static HRESULT WINAPI
d3d_device7_SetViewport_FPUSetup(IDirect3DDevice7
*iface
, D3DVIEWPORT7
*viewport
)
5349 return d3d_device7_SetViewport(iface
, viewport
);
5352 static HRESULT WINAPI
d3d_device7_SetViewport_FPUPreserve(IDirect3DDevice7
*iface
, D3DVIEWPORT7
*viewport
)
5357 old_fpucw
= d3d_fpu_setup();
5358 hr
= d3d_device7_SetViewport(iface
, viewport
);
5359 set_fpu_control_word(old_fpucw
);
5364 static HRESULT
d3d_device7_GetViewport(IDirect3DDevice7
*iface
, D3DVIEWPORT7
*viewport
)
5366 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5367 struct wined3d_viewport wined3d_viewport
;
5369 TRACE("iface %p, viewport %p.\n", iface
, viewport
);
5372 return DDERR_INVALIDPARAMS
;
5374 wined3d_mutex_lock();
5375 wined3d_device_get_viewports(device
->wined3d_device
, NULL
, &wined3d_viewport
);
5376 wined3d_mutex_unlock();
5378 viewport
->dwX
= wined3d_viewport
.x
;
5379 viewport
->dwY
= wined3d_viewport
.y
;
5380 viewport
->dwWidth
= wined3d_viewport
.width
;
5381 viewport
->dwHeight
= wined3d_viewport
.height
;
5382 viewport
->dvMinZ
= wined3d_viewport
.min_z
;
5383 viewport
->dvMaxZ
= wined3d_viewport
.max_z
;
5388 static HRESULT WINAPI
d3d_device7_GetViewport_FPUSetup(IDirect3DDevice7
*iface
, D3DVIEWPORT7
*viewport
)
5390 return d3d_device7_GetViewport(iface
, viewport
);
5393 static HRESULT WINAPI
d3d_device7_GetViewport_FPUPreserve(IDirect3DDevice7
*iface
, D3DVIEWPORT7
*viewport
)
5398 old_fpucw
= d3d_fpu_setup();
5399 hr
= d3d_device7_GetViewport(iface
, viewport
);
5400 set_fpu_control_word(old_fpucw
);
5405 /*****************************************************************************
5406 * IDirect3DDevice7::SetMaterial
5413 * Mat: The material to set
5417 * DDERR_INVALIDPARAMS if Mat is NULL.
5419 *****************************************************************************/
5420 static HRESULT
d3d_device7_SetMaterial(IDirect3DDevice7
*iface
, D3DMATERIAL7
*material
)
5422 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5424 TRACE("iface %p, material %p.\n", iface
, material
);
5427 return DDERR_INVALIDPARAMS
;
5429 wined3d_mutex_lock();
5430 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5431 wined3d_device_set_material(device
->wined3d_device
, (struct wined3d_material
*)material
);
5432 wined3d_mutex_unlock();
5437 static HRESULT WINAPI
d3d_device7_SetMaterial_FPUSetup(IDirect3DDevice7
*iface
, D3DMATERIAL7
*material
)
5439 return d3d_device7_SetMaterial(iface
, material
);
5442 static HRESULT WINAPI
d3d_device7_SetMaterial_FPUPreserve(IDirect3DDevice7
*iface
, D3DMATERIAL7
*material
)
5447 old_fpucw
= d3d_fpu_setup();
5448 hr
= d3d_device7_SetMaterial(iface
, material
);
5449 set_fpu_control_word(old_fpucw
);
5454 /*****************************************************************************
5455 * IDirect3DDevice7::GetMaterial
5457 * Returns the current material
5462 * Mat: D3DMATERIAL7 structure to write the material parameters to
5466 * DDERR_INVALIDPARAMS if Mat is NULL
5468 *****************************************************************************/
5469 static HRESULT
d3d_device7_GetMaterial(IDirect3DDevice7
*iface
, D3DMATERIAL7
*material
)
5471 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5473 TRACE("iface %p, material %p.\n", iface
, material
);
5475 wined3d_mutex_lock();
5476 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5477 wined3d_device_get_material(device
->wined3d_device
, (struct wined3d_material
*)material
);
5478 wined3d_mutex_unlock();
5483 static HRESULT WINAPI
d3d_device7_GetMaterial_FPUSetup(IDirect3DDevice7
*iface
, D3DMATERIAL7
*material
)
5485 return d3d_device7_GetMaterial(iface
, material
);
5488 static HRESULT WINAPI
d3d_device7_GetMaterial_FPUPreserve(IDirect3DDevice7
*iface
, D3DMATERIAL7
*material
)
5493 old_fpucw
= d3d_fpu_setup();
5494 hr
= d3d_device7_GetMaterial(iface
, material
);
5495 set_fpu_control_word(old_fpucw
);
5500 /*****************************************************************************
5501 * IDirect3DDevice7::SetLight
5503 * Assigns a light to a light index, but doesn't activate it yet.
5505 * Version 7, IDirect3DLight uses this method for older versions
5508 * LightIndex: The index of the new light
5509 * Light: A D3DLIGHT7 structure describing the light
5514 *****************************************************************************/
5515 static HRESULT
d3d_device7_SetLight(IDirect3DDevice7
*iface
, DWORD light_idx
, D3DLIGHT7
*light
)
5517 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5520 TRACE("iface %p, light_idx %u, light %p.\n", iface
, light_idx
, light
);
5522 wined3d_mutex_lock();
5523 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5524 hr
= wined3d_device_set_light(device
->wined3d_device
, light_idx
, (struct wined3d_light
*)light
);
5525 wined3d_mutex_unlock();
5527 return hr_ddraw_from_wined3d(hr
);
5530 static HRESULT WINAPI
d3d_device7_SetLight_FPUSetup(IDirect3DDevice7
*iface
, DWORD light_idx
, D3DLIGHT7
*light
)
5532 return d3d_device7_SetLight(iface
, light_idx
, light
);
5535 static HRESULT WINAPI
d3d_device7_SetLight_FPUPreserve(IDirect3DDevice7
*iface
, DWORD light_idx
, D3DLIGHT7
*light
)
5540 old_fpucw
= d3d_fpu_setup();
5541 hr
= d3d_device7_SetLight(iface
, light_idx
, light
);
5542 set_fpu_control_word(old_fpucw
);
5547 /*****************************************************************************
5548 * IDirect3DDevice7::GetLight
5550 * Returns the light assigned to a light index
5553 * Light: Structure to write the light information to
5557 * DDERR_INVALIDPARAMS if Light is NULL
5559 *****************************************************************************/
5560 static HRESULT
d3d_device7_GetLight(IDirect3DDevice7
*iface
, DWORD light_idx
, D3DLIGHT7
*light
)
5562 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5565 TRACE("iface %p, light_idx %u, light %p.\n", iface
, light_idx
, light
);
5567 wined3d_mutex_lock();
5568 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5569 rc
= wined3d_device_get_light(device
->wined3d_device
, light_idx
, (struct wined3d_light
*)light
);
5570 wined3d_mutex_unlock();
5572 /* Translate the result. WineD3D returns other values than D3D7 */
5573 return hr_ddraw_from_wined3d(rc
);
5576 static HRESULT WINAPI
d3d_device7_GetLight_FPUSetup(IDirect3DDevice7
*iface
, DWORD light_idx
, D3DLIGHT7
*light
)
5578 return d3d_device7_GetLight(iface
, light_idx
, light
);
5581 static HRESULT WINAPI
d3d_device7_GetLight_FPUPreserve(IDirect3DDevice7
*iface
, DWORD light_idx
, D3DLIGHT7
*light
)
5586 old_fpucw
= d3d_fpu_setup();
5587 hr
= d3d_device7_GetLight(iface
, light_idx
, light
);
5588 set_fpu_control_word(old_fpucw
);
5593 /*****************************************************************************
5594 * IDirect3DDevice7::BeginStateBlock
5596 * Begins recording to a stateblock
5603 *****************************************************************************/
5604 static HRESULT
d3d_device7_BeginStateBlock(IDirect3DDevice7
*iface
)
5606 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5609 TRACE("iface %p.\n", iface
);
5611 wined3d_mutex_lock();
5612 if (device
->recording
)
5614 wined3d_mutex_unlock();
5615 WARN("Trying to begin a stateblock while recording, returning D3DERR_INBEGINSTATEBLOCK.\n");
5616 return D3DERR_INBEGINSTATEBLOCK
;
5618 if (SUCCEEDED(hr
= wined3d_device_begin_stateblock(device
->wined3d_device
)))
5619 device
->recording
= TRUE
;
5620 wined3d_mutex_unlock();
5622 return hr_ddraw_from_wined3d(hr
);
5625 static HRESULT WINAPI
d3d_device7_BeginStateBlock_FPUSetup(IDirect3DDevice7
*iface
)
5627 return d3d_device7_BeginStateBlock(iface
);
5630 static HRESULT WINAPI
d3d_device7_BeginStateBlock_FPUPreserve(IDirect3DDevice7
*iface
)
5635 old_fpucw
= d3d_fpu_setup();
5636 hr
= d3d_device7_BeginStateBlock(iface
);
5637 set_fpu_control_word(old_fpucw
);
5642 /*****************************************************************************
5643 * IDirect3DDevice7::EndStateBlock
5645 * Stops recording to a state block and returns the created stateblock
5651 * BlockHandle: Address to store the stateblock's handle to
5655 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5657 *****************************************************************************/
5658 static HRESULT
d3d_device7_EndStateBlock(IDirect3DDevice7
*iface
, DWORD
*stateblock
)
5660 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5661 struct wined3d_stateblock
*wined3d_sb
;
5665 TRACE("iface %p, stateblock %p.\n", iface
, stateblock
);
5668 return DDERR_INVALIDPARAMS
;
5670 wined3d_mutex_lock();
5671 if (!device
->recording
)
5673 wined3d_mutex_unlock();
5674 WARN("Trying to end a stateblock, but no stateblock is being recorded.\n");
5675 return D3DERR_NOTINBEGINSTATEBLOCK
;
5677 hr
= wined3d_device_end_stateblock(device
->wined3d_device
, &wined3d_sb
);
5680 WARN("Failed to end stateblock, hr %#x.\n", hr
);
5681 wined3d_mutex_unlock();
5683 return hr_ddraw_from_wined3d(hr
);
5685 device
->recording
= FALSE
;
5687 h
= ddraw_allocate_handle(&device
->handle_table
, wined3d_sb
, DDRAW_HANDLE_STATEBLOCK
);
5688 if (h
== DDRAW_INVALID_HANDLE
)
5690 ERR("Failed to allocate a stateblock handle.\n");
5691 wined3d_stateblock_decref(wined3d_sb
);
5692 wined3d_mutex_unlock();
5694 return DDERR_OUTOFMEMORY
;
5697 wined3d_mutex_unlock();
5698 *stateblock
= h
+ 1;
5700 return hr_ddraw_from_wined3d(hr
);
5703 static HRESULT WINAPI
d3d_device7_EndStateBlock_FPUSetup(IDirect3DDevice7
*iface
, DWORD
*stateblock
)
5705 return d3d_device7_EndStateBlock(iface
, stateblock
);
5708 static HRESULT WINAPI
d3d_device7_EndStateBlock_FPUPreserve(IDirect3DDevice7
*iface
, DWORD
*stateblock
)
5713 old_fpucw
= d3d_fpu_setup();
5714 hr
= d3d_device7_EndStateBlock(iface
, stateblock
);
5715 set_fpu_control_word(old_fpucw
);
5720 /*****************************************************************************
5721 * IDirect3DDevice7::PreLoad
5723 * Allows the app to signal that a texture will be used soon, to allow
5724 * the Direct3DDevice to load it to the video card in the meantime.
5729 * Texture: The texture to preload
5733 * DDERR_INVALIDPARAMS if Texture is NULL
5735 *****************************************************************************/
5736 static HRESULT
d3d_device7_PreLoad(IDirect3DDevice7
*iface
, IDirectDrawSurface7
*texture
)
5738 struct ddraw_surface
*surface
= unsafe_impl_from_IDirectDrawSurface7(texture
);
5740 TRACE("iface %p, texture %p.\n", iface
, texture
);
5743 return DDERR_INVALIDPARAMS
;
5745 wined3d_mutex_lock();
5746 wined3d_resource_preload(wined3d_texture_get_resource(surface
->wined3d_texture
));
5747 wined3d_mutex_unlock();
5752 static HRESULT WINAPI
d3d_device7_PreLoad_FPUSetup(IDirect3DDevice7
*iface
, IDirectDrawSurface7
*texture
)
5754 return d3d_device7_PreLoad(iface
, texture
);
5757 static HRESULT WINAPI
d3d_device7_PreLoad_FPUPreserve(IDirect3DDevice7
*iface
, IDirectDrawSurface7
*texture
)
5762 old_fpucw
= d3d_fpu_setup();
5763 hr
= d3d_device7_PreLoad(iface
, texture
);
5764 set_fpu_control_word(old_fpucw
);
5769 /*****************************************************************************
5770 * IDirect3DDevice7::ApplyStateBlock
5772 * Activates the state stored in a state block handle.
5775 * BlockHandle: The stateblock handle to activate
5779 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5781 *****************************************************************************/
5782 static HRESULT
d3d_device7_ApplyStateBlock(IDirect3DDevice7
*iface
, DWORD stateblock
)
5784 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5785 struct wined3d_stateblock
*wined3d_sb
;
5787 TRACE("iface %p, stateblock %#x.\n", iface
, stateblock
);
5789 wined3d_mutex_lock();
5790 if (device
->recording
)
5792 wined3d_mutex_unlock();
5793 WARN("Trying to apply a stateblock while recording, returning D3DERR_INBEGINSTATEBLOCK.\n");
5794 return D3DERR_INBEGINSTATEBLOCK
;
5796 wined3d_sb
= ddraw_get_object(&device
->handle_table
, stateblock
- 1, DDRAW_HANDLE_STATEBLOCK
);
5799 WARN("Invalid stateblock handle.\n");
5800 wined3d_mutex_unlock();
5801 return D3DERR_INVALIDSTATEBLOCK
;
5804 wined3d_stateblock_apply(wined3d_sb
);
5805 wined3d_mutex_unlock();
5810 static HRESULT WINAPI
d3d_device7_ApplyStateBlock_FPUSetup(IDirect3DDevice7
*iface
, DWORD stateblock
)
5812 return d3d_device7_ApplyStateBlock(iface
, stateblock
);
5815 static HRESULT WINAPI
d3d_device7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7
*iface
, DWORD stateblock
)
5820 old_fpucw
= d3d_fpu_setup();
5821 hr
= d3d_device7_ApplyStateBlock(iface
, stateblock
);
5822 set_fpu_control_word(old_fpucw
);
5827 /*****************************************************************************
5828 * IDirect3DDevice7::CaptureStateBlock
5830 * Updates a stateblock's values to the values currently set for the device
5835 * BlockHandle: Stateblock to update
5839 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5841 *****************************************************************************/
5842 static HRESULT
d3d_device7_CaptureStateBlock(IDirect3DDevice7
*iface
, DWORD stateblock
)
5844 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5845 struct wined3d_stateblock
*wined3d_sb
;
5847 TRACE("iface %p, stateblock %#x.\n", iface
, stateblock
);
5849 wined3d_mutex_lock();
5850 if (device
->recording
)
5852 wined3d_mutex_unlock();
5853 WARN("Trying to capture a stateblock while recording, returning D3DERR_INBEGINSTATEBLOCK.\n");
5854 return D3DERR_INBEGINSTATEBLOCK
;
5856 wined3d_sb
= ddraw_get_object(&device
->handle_table
, stateblock
- 1, DDRAW_HANDLE_STATEBLOCK
);
5859 WARN("Invalid stateblock handle.\n");
5860 wined3d_mutex_unlock();
5861 return D3DERR_INVALIDSTATEBLOCK
;
5864 wined3d_stateblock_capture(wined3d_sb
);
5865 wined3d_mutex_unlock();
5870 static HRESULT WINAPI
d3d_device7_CaptureStateBlock_FPUSetup(IDirect3DDevice7
*iface
, DWORD stateblock
)
5872 return d3d_device7_CaptureStateBlock(iface
, stateblock
);
5875 static HRESULT WINAPI
d3d_device7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7
*iface
, DWORD stateblock
)
5880 old_fpucw
= d3d_fpu_setup();
5881 hr
= d3d_device7_CaptureStateBlock(iface
, stateblock
);
5882 set_fpu_control_word(old_fpucw
);
5887 /*****************************************************************************
5888 * IDirect3DDevice7::DeleteStateBlock
5890 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5895 * BlockHandle: Stateblock handle to delete
5899 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5901 *****************************************************************************/
5902 static HRESULT
d3d_device7_DeleteStateBlock(IDirect3DDevice7
*iface
, DWORD stateblock
)
5904 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5905 struct wined3d_stateblock
*wined3d_sb
;
5908 TRACE("iface %p, stateblock %#x.\n", iface
, stateblock
);
5910 wined3d_mutex_lock();
5912 wined3d_sb
= ddraw_free_handle(&device
->handle_table
, stateblock
- 1, DDRAW_HANDLE_STATEBLOCK
);
5915 WARN("Invalid stateblock handle.\n");
5916 wined3d_mutex_unlock();
5917 return D3DERR_INVALIDSTATEBLOCK
;
5920 if ((ref
= wined3d_stateblock_decref(wined3d_sb
)))
5922 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb
, ref
);
5925 wined3d_mutex_unlock();
5930 static HRESULT WINAPI
d3d_device7_DeleteStateBlock_FPUSetup(IDirect3DDevice7
*iface
, DWORD stateblock
)
5932 return d3d_device7_DeleteStateBlock(iface
, stateblock
);
5935 static HRESULT WINAPI
d3d_device7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7
*iface
, DWORD stateblock
)
5940 old_fpucw
= d3d_fpu_setup();
5941 hr
= d3d_device7_DeleteStateBlock(iface
, stateblock
);
5942 set_fpu_control_word(old_fpucw
);
5947 /*****************************************************************************
5948 * IDirect3DDevice7::CreateStateBlock
5950 * Creates a new state block handle.
5955 * Type: The state block type
5956 * BlockHandle: Address to write the created handle to
5960 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5962 *****************************************************************************/
5963 static HRESULT
d3d_device7_CreateStateBlock(IDirect3DDevice7
*iface
,
5964 D3DSTATEBLOCKTYPE type
, DWORD
*stateblock
)
5966 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5967 struct wined3d_stateblock
*wined3d_sb
;
5971 TRACE("iface %p, type %#x, stateblock %p.\n", iface
, type
, stateblock
);
5974 return DDERR_INVALIDPARAMS
;
5976 if (type
!= D3DSBT_ALL
5977 && type
!= D3DSBT_PIXELSTATE
5978 && type
!= D3DSBT_VERTEXSTATE
)
5980 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5981 return DDERR_INVALIDPARAMS
;
5984 wined3d_mutex_lock();
5986 if (device
->recording
)
5988 wined3d_mutex_unlock();
5989 WARN("Trying to apply a stateblock while recording, returning D3DERR_INBEGINSTATEBLOCK.\n");
5990 return D3DERR_INBEGINSTATEBLOCK
;
5993 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5994 hr
= wined3d_stateblock_create(device
->wined3d_device
, type
, &wined3d_sb
);
5997 WARN("Failed to create stateblock, hr %#x.\n", hr
);
5998 wined3d_mutex_unlock();
5999 return hr_ddraw_from_wined3d(hr
);
6002 h
= ddraw_allocate_handle(&device
->handle_table
, wined3d_sb
, DDRAW_HANDLE_STATEBLOCK
);
6003 if (h
== DDRAW_INVALID_HANDLE
)
6005 ERR("Failed to allocate stateblock handle.\n");
6006 wined3d_stateblock_decref(wined3d_sb
);
6007 wined3d_mutex_unlock();
6008 return DDERR_OUTOFMEMORY
;
6011 *stateblock
= h
+ 1;
6012 wined3d_mutex_unlock();
6014 return hr_ddraw_from_wined3d(hr
);
6017 static HRESULT WINAPI
d3d_device7_CreateStateBlock_FPUSetup(IDirect3DDevice7
*iface
,
6018 D3DSTATEBLOCKTYPE type
, DWORD
*stateblock
)
6020 return d3d_device7_CreateStateBlock(iface
, type
, stateblock
);
6023 static HRESULT WINAPI
d3d_device7_CreateStateBlock_FPUPreserve(IDirect3DDevice7
*iface
,
6024 D3DSTATEBLOCKTYPE type
, DWORD
*stateblock
)
6029 old_fpucw
= d3d_fpu_setup();
6030 hr
= d3d_device7_CreateStateBlock(iface
, type
, stateblock
);
6031 set_fpu_control_word(old_fpucw
);
6036 static BOOL
is_mip_level_subset(struct ddraw_surface
*dest
, struct ddraw_surface
*src
)
6038 struct ddraw_surface
*src_level
, *dest_level
;
6039 IDirectDrawSurface7
*temp
;
6040 DDSURFACEDESC2 ddsd
;
6041 BOOL levelFound
; /* at least one suitable sublevel in dest found */
6043 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
6044 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
6045 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
6052 for (;src_level
&& dest_level
;)
6054 if (src_level
->surface_desc
.dwWidth
== dest_level
->surface_desc
.dwWidth
&&
6055 src_level
->surface_desc
.dwHeight
== dest_level
->surface_desc
.dwHeight
)
6059 ddsd
.ddsCaps
.dwCaps
= DDSCAPS_TEXTURE
;
6060 ddsd
.ddsCaps
.dwCaps2
= DDSCAPS2_MIPMAPSUBLEVEL
;
6061 IDirectDrawSurface7_GetAttachedSurface(&dest_level
->IDirectDrawSurface7_iface
, &ddsd
.ddsCaps
, &temp
);
6063 if (dest_level
!= dest
) IDirectDrawSurface7_Release(&dest_level
->IDirectDrawSurface7_iface
);
6065 dest_level
= unsafe_impl_from_IDirectDrawSurface7(temp
);
6068 ddsd
.ddsCaps
.dwCaps
= DDSCAPS_TEXTURE
;
6069 ddsd
.ddsCaps
.dwCaps2
= DDSCAPS2_MIPMAPSUBLEVEL
;
6070 IDirectDrawSurface7_GetAttachedSurface(&src_level
->IDirectDrawSurface7_iface
, &ddsd
.ddsCaps
, &temp
);
6072 if (src_level
!= src
) IDirectDrawSurface7_Release(&src_level
->IDirectDrawSurface7_iface
);
6074 src_level
= unsafe_impl_from_IDirectDrawSurface7(temp
);
6077 if (src_level
&& src_level
!= src
) IDirectDrawSurface7_Release(&src_level
->IDirectDrawSurface7_iface
);
6078 if (dest_level
&& dest_level
!= dest
) IDirectDrawSurface7_Release(&dest_level
->IDirectDrawSurface7_iface
);
6080 return !dest_level
&& levelFound
;
6083 static void copy_mipmap_chain(struct d3d_device
*device
, struct ddraw_surface
*dst
,
6084 struct ddraw_surface
*src
, const POINT
*DestPoint
, const RECT
*SrcRect
)
6086 struct ddraw_surface
*dst_level
, *src_level
;
6087 IDirectDrawSurface7
*temp
;
6088 DDSURFACEDESC2 ddsd
;
6092 IDirectDrawPalette
*pal
= NULL
, *pal_src
= NULL
;
6096 /* Copy palette, if possible. */
6097 IDirectDrawSurface7_GetPalette(&src
->IDirectDrawSurface7_iface
, &pal_src
);
6098 IDirectDrawSurface7_GetPalette(&dst
->IDirectDrawSurface7_iface
, &pal
);
6100 if (pal_src
!= NULL
&& pal
!= NULL
)
6102 PALETTEENTRY palent
[256];
6104 IDirectDrawPalette_GetEntries(pal_src
, 0, 0, 256, palent
);
6105 IDirectDrawPalette_SetEntries(pal
, 0, 0, 256, palent
);
6108 if (pal
) IDirectDrawPalette_Release(pal
);
6109 if (pal_src
) IDirectDrawPalette_Release(pal_src
);
6111 /* Copy colorkeys, if present. */
6112 for (ckeyflag
= DDCKEY_DESTBLT
; ckeyflag
<= DDCKEY_SRCOVERLAY
; ckeyflag
<<= 1)
6114 hr
= IDirectDrawSurface7_GetColorKey(&src
->IDirectDrawSurface7_iface
, ckeyflag
, &ddckey
);
6118 IDirectDrawSurface7_SetColorKey(&dst
->IDirectDrawSurface7_iface
, ckeyflag
, &ddckey
);
6126 src_rect
= *SrcRect
;
6128 for (;src_level
&& dst_level
;)
6130 if (src_level
->surface_desc
.dwWidth
== dst_level
->surface_desc
.dwWidth
6131 && src_level
->surface_desc
.dwHeight
== dst_level
->surface_desc
.dwHeight
)
6133 UINT src_w
= src_rect
.right
- src_rect
.left
;
6134 UINT src_h
= src_rect
.bottom
- src_rect
.top
;
6135 RECT dst_rect
= {point
.x
, point
.y
, point
.x
+ src_w
, point
.y
+ src_h
};
6137 if (FAILED(hr
= wined3d_texture_blt(dst_level
->wined3d_texture
, dst_level
->sub_resource_idx
, &dst_rect
,
6138 src_level
->wined3d_texture
, src_level
->sub_resource_idx
, &src_rect
, 0, NULL
, WINED3D_TEXF_POINT
)))
6139 ERR("Blit failed, hr %#x.\n", hr
);
6141 ddsd
.ddsCaps
.dwCaps
= DDSCAPS_TEXTURE
;
6142 ddsd
.ddsCaps
.dwCaps2
= DDSCAPS2_MIPMAPSUBLEVEL
;
6143 IDirectDrawSurface7_GetAttachedSurface(&dst_level
->IDirectDrawSurface7_iface
, &ddsd
.ddsCaps
, &temp
);
6145 if (dst_level
!= dst
)
6146 IDirectDrawSurface7_Release(&dst_level
->IDirectDrawSurface7_iface
);
6148 dst_level
= unsafe_impl_from_IDirectDrawSurface7(temp
);
6151 ddsd
.ddsCaps
.dwCaps
= DDSCAPS_TEXTURE
;
6152 ddsd
.ddsCaps
.dwCaps2
= DDSCAPS2_MIPMAPSUBLEVEL
;
6153 IDirectDrawSurface7_GetAttachedSurface(&src_level
->IDirectDrawSurface7_iface
, &ddsd
.ddsCaps
, &temp
);
6155 if (src_level
!= src
) IDirectDrawSurface7_Release(&src_level
->IDirectDrawSurface7_iface
);
6157 src_level
= unsafe_impl_from_IDirectDrawSurface7(temp
);
6164 src_rect
.right
= (src_rect
.right
+ 1) / 2;
6165 src_rect
.bottom
= (src_rect
.bottom
+ 1) / 2;
6168 if (src_level
&& src_level
!= src
)
6169 IDirectDrawSurface7_Release(&src_level
->IDirectDrawSurface7_iface
);
6170 if (dst_level
&& dst_level
!= dst
)
6171 IDirectDrawSurface7_Release(&dst_level
->IDirectDrawSurface7_iface
);
6174 /*****************************************************************************
6175 * IDirect3DDevice7::Load
6177 * Loads a rectangular area from the source into the destination texture.
6178 * It can also copy the source to the faces of a cubic environment map
6183 * DestTex: Destination texture
6184 * DestPoint: Point in the destination where the source image should be
6186 * SrcTex: Source texture
6187 * SrcRect: Source rectangle
6188 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6189 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6190 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6194 * DDERR_INVALIDPARAMS if dst_texture or src_texture is NULL, broken coordinates or anything unexpected.
6197 *****************************************************************************/
6198 static HRESULT
d3d_device7_Load(IDirect3DDevice7
*iface
, IDirectDrawSurface7
*dst_texture
, POINT
*dst_pos
,
6199 IDirectDrawSurface7
*src_texture
, RECT
*src_rect
, DWORD flags
)
6201 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
6202 struct ddraw_surface
*dest
= unsafe_impl_from_IDirectDrawSurface7(dst_texture
);
6203 struct ddraw_surface
*src
= unsafe_impl_from_IDirectDrawSurface7(src_texture
);
6207 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6208 iface
, dst_texture
, wine_dbgstr_point(dst_pos
), src_texture
, wine_dbgstr_rect(src_rect
), flags
);
6210 if( (!src
) || (!dest
) )
6211 return DDERR_INVALIDPARAMS
;
6213 wined3d_mutex_lock();
6216 SetRect(&srcrect
, 0, 0, src
->surface_desc
.dwWidth
, src
->surface_desc
.dwHeight
);
6218 srcrect
= *src_rect
;
6221 destpoint
.x
= destpoint
.y
= 0;
6223 destpoint
= *dst_pos
;
6225 /* Check bad dimensions. dst_pos is validated against src, not dest, because
6226 * destination can be a subset of mip levels, in which case actual coordinates used
6227 * for it may be divided. If any dimension of dest is larger than source, it can't be
6228 * mip level subset, so an error can be returned early.
6230 if (IsRectEmpty(&srcrect
) || srcrect
.right
> src
->surface_desc
.dwWidth
||
6231 srcrect
.bottom
> src
->surface_desc
.dwHeight
||
6232 destpoint
.x
+ srcrect
.right
- srcrect
.left
> src
->surface_desc
.dwWidth
||
6233 destpoint
.y
+ srcrect
.bottom
- srcrect
.top
> src
->surface_desc
.dwHeight
||
6234 dest
->surface_desc
.dwWidth
> src
->surface_desc
.dwWidth
||
6235 dest
->surface_desc
.dwHeight
> src
->surface_desc
.dwHeight
)
6237 wined3d_mutex_unlock();
6238 return DDERR_INVALIDPARAMS
;
6241 /* Must be top level surfaces. */
6242 if (src
->surface_desc
.ddsCaps
.dwCaps2
& DDSCAPS2_MIPMAPSUBLEVEL
||
6243 dest
->surface_desc
.ddsCaps
.dwCaps2
& DDSCAPS2_MIPMAPSUBLEVEL
)
6245 wined3d_mutex_unlock();
6246 return DDERR_INVALIDPARAMS
;
6249 if (src
->surface_desc
.ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP
)
6251 struct ddraw_surface
*src_face
, *dest_face
;
6252 DWORD src_face_flag
, dest_face_flag
;
6253 IDirectDrawSurface7
*temp
;
6254 DDSURFACEDESC2 ddsd
;
6257 if (!(dest
->surface_desc
.ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP
))
6259 wined3d_mutex_unlock();
6260 return DDERR_INVALIDPARAMS
;
6263 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6264 * time it's actual surface loading. */
6265 for (i
= 0; i
< 2; i
++)
6270 for (;dest_face
&& src_face
;)
6272 src_face_flag
= src_face
->surface_desc
.ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP_ALLFACES
;
6273 dest_face_flag
= dest_face
->surface_desc
.ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP_ALLFACES
;
6275 if (src_face_flag
== dest_face_flag
)
6279 /* Destination mip levels must be subset of source mip levels. */
6280 if (!is_mip_level_subset(dest_face
, src_face
))
6282 wined3d_mutex_unlock();
6283 return DDERR_INVALIDPARAMS
;
6286 else if (flags
& dest_face_flag
)
6288 copy_mipmap_chain(device
, dest_face
, src_face
, &destpoint
, &srcrect
);
6291 if (src_face_flag
< DDSCAPS2_CUBEMAP_NEGATIVEZ
)
6293 ddsd
.ddsCaps
.dwCaps
= DDSCAPS_TEXTURE
;
6294 ddsd
.ddsCaps
.dwCaps2
= DDSCAPS2_CUBEMAP
| (src_face_flag
<< 1);
6295 IDirectDrawSurface7_GetAttachedSurface(&src
->IDirectDrawSurface7_iface
, &ddsd
.ddsCaps
, &temp
);
6297 if (src_face
!= src
) IDirectDrawSurface7_Release(&src_face
->IDirectDrawSurface7_iface
);
6299 src_face
= unsafe_impl_from_IDirectDrawSurface7(temp
);
6303 if (src_face
!= src
) IDirectDrawSurface7_Release(&src_face
->IDirectDrawSurface7_iface
);
6309 if (dest_face_flag
< DDSCAPS2_CUBEMAP_NEGATIVEZ
)
6311 ddsd
.ddsCaps
.dwCaps
= DDSCAPS_TEXTURE
;
6312 ddsd
.ddsCaps
.dwCaps2
= DDSCAPS2_CUBEMAP
| (dest_face_flag
<< 1);
6313 IDirectDrawSurface7_GetAttachedSurface(&dest
->IDirectDrawSurface7_iface
, &ddsd
.ddsCaps
, &temp
);
6315 if (dest_face
!= dest
) IDirectDrawSurface7_Release(&dest_face
->IDirectDrawSurface7_iface
);
6317 dest_face
= unsafe_impl_from_IDirectDrawSurface7(temp
);
6321 if (dest_face
!= dest
) IDirectDrawSurface7_Release(&dest_face
->IDirectDrawSurface7_iface
);
6329 /* Native returns error if src faces are not subset of dest faces. */
6332 wined3d_mutex_unlock();
6333 return DDERR_INVALIDPARAMS
;
6338 wined3d_mutex_unlock();
6341 else if (dest
->surface_desc
.ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP
)
6343 wined3d_mutex_unlock();
6344 return DDERR_INVALIDPARAMS
;
6347 /* Handle non cube map textures. */
6349 /* Destination mip levels must be subset of source mip levels. */
6350 if (!is_mip_level_subset(dest
, src
))
6352 wined3d_mutex_unlock();
6353 return DDERR_INVALIDPARAMS
;
6356 copy_mipmap_chain(device
, dest
, src
, &destpoint
, &srcrect
);
6358 wined3d_mutex_unlock();
6363 static HRESULT WINAPI
d3d_device7_Load_FPUSetup(IDirect3DDevice7
*iface
, IDirectDrawSurface7
*dst_texture
,
6364 POINT
*dst_pos
, IDirectDrawSurface7
*src_texture
, RECT
*src_rect
, DWORD flags
)
6366 return d3d_device7_Load(iface
, dst_texture
, dst_pos
, src_texture
, src_rect
, flags
);
6369 static HRESULT WINAPI
d3d_device7_Load_FPUPreserve(IDirect3DDevice7
*iface
, IDirectDrawSurface7
*dst_texture
,
6370 POINT
*dst_pos
, IDirectDrawSurface7
*src_texture
, RECT
*src_rect
, DWORD flags
)
6375 old_fpucw
= d3d_fpu_setup();
6376 hr
= d3d_device7_Load(iface
, dst_texture
, dst_pos
, src_texture
, src_rect
, flags
);
6377 set_fpu_control_word(old_fpucw
);
6382 /*****************************************************************************
6383 * IDirect3DDevice7::LightEnable
6385 * Enables or disables a light
6387 * Version 7, IDirect3DLight uses this method too.
6390 * LightIndex: The index of the light to enable / disable
6391 * Enable: Enable or disable the light
6396 *****************************************************************************/
6397 static HRESULT
d3d_device7_LightEnable(IDirect3DDevice7
*iface
, DWORD light_idx
, BOOL enabled
)
6399 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
6402 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface
, light_idx
, enabled
);
6404 wined3d_mutex_lock();
6405 hr
= wined3d_device_set_light_enable(device
->wined3d_device
, light_idx
, enabled
);
6406 wined3d_mutex_unlock();
6408 return hr_ddraw_from_wined3d(hr
);
6411 static HRESULT WINAPI
d3d_device7_LightEnable_FPUSetup(IDirect3DDevice7
*iface
, DWORD light_idx
, BOOL enabled
)
6413 return d3d_device7_LightEnable(iface
, light_idx
, enabled
);
6416 static HRESULT WINAPI
d3d_device7_LightEnable_FPUPreserve(IDirect3DDevice7
*iface
, DWORD light_idx
, BOOL enabled
)
6421 old_fpucw
= d3d_fpu_setup();
6422 hr
= d3d_device7_LightEnable(iface
, light_idx
, enabled
);
6423 set_fpu_control_word(old_fpucw
);
6428 /*****************************************************************************
6429 * IDirect3DDevice7::GetLightEnable
6431 * Retrieves if the light with the given index is enabled or not
6436 * LightIndex: Index of desired light
6437 * Enable: Pointer to a BOOL which contains the result
6441 * DDERR_INVALIDPARAMS if Enable is NULL
6443 *****************************************************************************/
6444 static HRESULT
d3d_device7_GetLightEnable(IDirect3DDevice7
*iface
, DWORD light_idx
, BOOL
*enabled
)
6446 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
6449 TRACE("iface %p, light_idx %u, enabled %p.\n", iface
, light_idx
, enabled
);
6452 return DDERR_INVALIDPARAMS
;
6454 wined3d_mutex_lock();
6455 hr
= wined3d_device_get_light_enable(device
->wined3d_device
, light_idx
, enabled
);
6456 wined3d_mutex_unlock();
6458 return hr_ddraw_from_wined3d(hr
);
6461 static HRESULT WINAPI
d3d_device7_GetLightEnable_FPUSetup(IDirect3DDevice7
*iface
, DWORD light_idx
, BOOL
*enabled
)
6463 return d3d_device7_GetLightEnable(iface
, light_idx
, enabled
);
6466 static HRESULT WINAPI
d3d_device7_GetLightEnable_FPUPreserve(IDirect3DDevice7
*iface
, DWORD light_idx
, BOOL
*enabled
)
6471 old_fpucw
= d3d_fpu_setup();
6472 hr
= d3d_device7_GetLightEnable(iface
, light_idx
, enabled
);
6473 set_fpu_control_word(old_fpucw
);
6478 /*****************************************************************************
6479 * IDirect3DDevice7::SetClipPlane
6481 * Sets custom clipping plane
6486 * Index: The index of the clipping plane
6487 * PlaneEquation: An equation defining the clipping plane
6491 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6493 *****************************************************************************/
6494 static HRESULT
d3d_device7_SetClipPlane(IDirect3DDevice7
*iface
, DWORD idx
, D3DVALUE
*plane
)
6496 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
6497 const struct wined3d_vec4
*wined3d_plane
;
6500 TRACE("iface %p, idx %u, plane %p.\n", iface
, idx
, plane
);
6503 return DDERR_INVALIDPARAMS
;
6505 wined3d_plane
= (struct wined3d_vec4
*)plane
;
6507 wined3d_mutex_lock();
6508 hr
= wined3d_device_set_clip_plane(device
->wined3d_device
, idx
, wined3d_plane
);
6509 if (idx
< ARRAY_SIZE(device
->user_clip_planes
))
6511 device
->user_clip_planes
[idx
] = *wined3d_plane
;
6512 if (hr
== WINED3DERR_INVALIDCALL
)
6514 WARN("Clip plane %u is not supported.\n", idx
);
6518 wined3d_mutex_unlock();
6523 static HRESULT WINAPI
d3d_device7_SetClipPlane_FPUSetup(IDirect3DDevice7
*iface
, DWORD idx
, D3DVALUE
*plane
)
6525 return d3d_device7_SetClipPlane(iface
, idx
, plane
);
6528 static HRESULT WINAPI
d3d_device7_SetClipPlane_FPUPreserve(IDirect3DDevice7
*iface
, DWORD idx
, D3DVALUE
*plane
)
6533 old_fpucw
= d3d_fpu_setup();
6534 hr
= d3d_device7_SetClipPlane(iface
, idx
, plane
);
6535 set_fpu_control_word(old_fpucw
);
6540 /*****************************************************************************
6541 * IDirect3DDevice7::GetClipPlane
6543 * Returns the clipping plane with a specific index
6546 * Index: The index of the desired plane
6547 * PlaneEquation: Address to store the plane equation to
6551 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6553 *****************************************************************************/
6554 static HRESULT
d3d_device7_GetClipPlane(IDirect3DDevice7
*iface
, DWORD idx
, D3DVALUE
*plane
)
6556 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
6557 struct wined3d_vec4
*wined3d_plane
;
6560 TRACE("iface %p, idx %u, plane %p.\n", iface
, idx
, plane
);
6563 return DDERR_INVALIDPARAMS
;
6565 wined3d_plane
= (struct wined3d_vec4
*)plane
;
6567 wined3d_mutex_lock();
6568 hr
= wined3d_device_get_clip_plane(device
->wined3d_device
, idx
, wined3d_plane
);
6569 if (hr
== WINED3DERR_INVALIDCALL
&& idx
< ARRAY_SIZE(device
->user_clip_planes
))
6571 WARN("Clip plane %u is not supported.\n", idx
);
6572 *wined3d_plane
= device
->user_clip_planes
[idx
];
6575 wined3d_mutex_unlock();
6580 static HRESULT WINAPI
d3d_device7_GetClipPlane_FPUSetup(IDirect3DDevice7
*iface
, DWORD idx
, D3DVALUE
*plane
)
6582 return d3d_device7_GetClipPlane(iface
, idx
, plane
);
6585 static HRESULT WINAPI
d3d_device7_GetClipPlane_FPUPreserve(IDirect3DDevice7
*iface
, DWORD idx
, D3DVALUE
*plane
)
6590 old_fpucw
= d3d_fpu_setup();
6591 hr
= d3d_device7_GetClipPlane(iface
, idx
, plane
);
6592 set_fpu_control_word(old_fpucw
);
6597 /*****************************************************************************
6598 * IDirect3DDevice7::GetInfo
6600 * Retrieves some information about the device. The DirectX sdk says that
6601 * this version returns S_FALSE for all retail builds of DirectX, that's what
6602 * this implementation does.
6605 * DevInfoID: Information type requested
6606 * DevInfoStruct: Pointer to a structure to store the info to
6607 * Size: Size of the structure
6610 * S_FALSE, because it's a non-debug driver
6612 *****************************************************************************/
6613 static HRESULT WINAPI
d3d_device7_GetInfo(IDirect3DDevice7
*iface
, DWORD info_id
, void *info
, DWORD info_size
)
6615 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6616 iface
, info_id
, info
, info_size
);
6618 if (TRACE_ON(ddraw
))
6620 TRACE(" info requested : ");
6623 case D3DDEVINFOID_TEXTUREMANAGER
: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6624 case D3DDEVINFOID_D3DTEXTUREMANAGER
: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6625 case D3DDEVINFOID_TEXTURING
: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6626 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS
;
6630 return S_FALSE
; /* According to MSDN, this is valid for a non-debug driver */
6633 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6634 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6635 * are not duplicated.
6637 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6638 * has already been setup for optimal d3d operation.
6640 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6641 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6642 * by Sacrifice (game). */
6643 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl
=
6645 /*** IUnknown Methods ***/
6646 d3d_device7_QueryInterface
,
6648 d3d_device7_Release
,
6649 /*** IDirect3DDevice7 ***/
6650 d3d_device7_GetCaps_FPUSetup
,
6651 d3d_device7_EnumTextureFormats_FPUSetup
,
6652 d3d_device7_BeginScene_FPUSetup
,
6653 d3d_device7_EndScene_FPUSetup
,
6654 d3d_device7_GetDirect3D
,
6655 d3d_device7_SetRenderTarget_FPUSetup
,
6656 d3d_device7_GetRenderTarget
,
6657 d3d_device7_Clear_FPUSetup
,
6658 d3d_device7_SetTransform_FPUSetup
,
6659 d3d_device7_GetTransform_FPUSetup
,
6660 d3d_device7_SetViewport_FPUSetup
,
6661 d3d_device7_MultiplyTransform_FPUSetup
,
6662 d3d_device7_GetViewport_FPUSetup
,
6663 d3d_device7_SetMaterial_FPUSetup
,
6664 d3d_device7_GetMaterial_FPUSetup
,
6665 d3d_device7_SetLight_FPUSetup
,
6666 d3d_device7_GetLight_FPUSetup
,
6667 d3d_device7_SetRenderState_FPUSetup
,
6668 d3d_device7_GetRenderState_FPUSetup
,
6669 d3d_device7_BeginStateBlock_FPUSetup
,
6670 d3d_device7_EndStateBlock_FPUSetup
,
6671 d3d_device7_PreLoad_FPUSetup
,
6672 d3d_device7_DrawPrimitive_FPUSetup
,
6673 d3d_device7_DrawIndexedPrimitive_FPUSetup
,
6674 d3d_device7_SetClipStatus
,
6675 d3d_device7_GetClipStatus
,
6676 d3d_device7_DrawPrimitiveStrided_FPUSetup
,
6677 d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup
,
6678 d3d_device7_DrawPrimitiveVB_FPUSetup
,
6679 d3d_device7_DrawIndexedPrimitiveVB_FPUSetup
,
6680 d3d_device7_ComputeSphereVisibility
,
6681 d3d_device7_GetTexture_FPUSetup
,
6682 d3d_device7_SetTexture_FPUSetup
,
6683 d3d_device7_GetTextureStageState_FPUSetup
,
6684 d3d_device7_SetTextureStageState_FPUSetup
,
6685 d3d_device7_ValidateDevice_FPUSetup
,
6686 d3d_device7_ApplyStateBlock_FPUSetup
,
6687 d3d_device7_CaptureStateBlock_FPUSetup
,
6688 d3d_device7_DeleteStateBlock_FPUSetup
,
6689 d3d_device7_CreateStateBlock_FPUSetup
,
6690 d3d_device7_Load_FPUSetup
,
6691 d3d_device7_LightEnable_FPUSetup
,
6692 d3d_device7_GetLightEnable_FPUSetup
,
6693 d3d_device7_SetClipPlane_FPUSetup
,
6694 d3d_device7_GetClipPlane_FPUSetup
,
6698 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl
=
6700 /*** IUnknown Methods ***/
6701 d3d_device7_QueryInterface
,
6703 d3d_device7_Release
,
6704 /*** IDirect3DDevice7 ***/
6705 d3d_device7_GetCaps_FPUPreserve
,
6706 d3d_device7_EnumTextureFormats_FPUPreserve
,
6707 d3d_device7_BeginScene_FPUPreserve
,
6708 d3d_device7_EndScene_FPUPreserve
,
6709 d3d_device7_GetDirect3D
,
6710 d3d_device7_SetRenderTarget_FPUPreserve
,
6711 d3d_device7_GetRenderTarget
,
6712 d3d_device7_Clear_FPUPreserve
,
6713 d3d_device7_SetTransform_FPUPreserve
,
6714 d3d_device7_GetTransform_FPUPreserve
,
6715 d3d_device7_SetViewport_FPUPreserve
,
6716 d3d_device7_MultiplyTransform_FPUPreserve
,
6717 d3d_device7_GetViewport_FPUPreserve
,
6718 d3d_device7_SetMaterial_FPUPreserve
,
6719 d3d_device7_GetMaterial_FPUPreserve
,
6720 d3d_device7_SetLight_FPUPreserve
,
6721 d3d_device7_GetLight_FPUPreserve
,
6722 d3d_device7_SetRenderState_FPUPreserve
,
6723 d3d_device7_GetRenderState_FPUPreserve
,
6724 d3d_device7_BeginStateBlock_FPUPreserve
,
6725 d3d_device7_EndStateBlock_FPUPreserve
,
6726 d3d_device7_PreLoad_FPUPreserve
,
6727 d3d_device7_DrawPrimitive_FPUPreserve
,
6728 d3d_device7_DrawIndexedPrimitive_FPUPreserve
,
6729 d3d_device7_SetClipStatus
,
6730 d3d_device7_GetClipStatus
,
6731 d3d_device7_DrawPrimitiveStrided_FPUPreserve
,
6732 d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve
,
6733 d3d_device7_DrawPrimitiveVB_FPUPreserve
,
6734 d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve
,
6735 d3d_device7_ComputeSphereVisibility
,
6736 d3d_device7_GetTexture_FPUPreserve
,
6737 d3d_device7_SetTexture_FPUPreserve
,
6738 d3d_device7_GetTextureStageState_FPUPreserve
,
6739 d3d_device7_SetTextureStageState_FPUPreserve
,
6740 d3d_device7_ValidateDevice_FPUPreserve
,
6741 d3d_device7_ApplyStateBlock_FPUPreserve
,
6742 d3d_device7_CaptureStateBlock_FPUPreserve
,
6743 d3d_device7_DeleteStateBlock_FPUPreserve
,
6744 d3d_device7_CreateStateBlock_FPUPreserve
,
6745 d3d_device7_Load_FPUPreserve
,
6746 d3d_device7_LightEnable_FPUPreserve
,
6747 d3d_device7_GetLightEnable_FPUPreserve
,
6748 d3d_device7_SetClipPlane_FPUPreserve
,
6749 d3d_device7_GetClipPlane_FPUPreserve
,
6753 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl
=
6755 /*** IUnknown Methods ***/
6756 d3d_device3_QueryInterface
,
6758 d3d_device3_Release
,
6759 /*** IDirect3DDevice3 ***/
6760 d3d_device3_GetCaps
,
6761 d3d_device3_GetStats
,
6762 d3d_device3_AddViewport
,
6763 d3d_device3_DeleteViewport
,
6764 d3d_device3_NextViewport
,
6765 d3d_device3_EnumTextureFormats
,
6766 d3d_device3_BeginScene
,
6767 d3d_device3_EndScene
,
6768 d3d_device3_GetDirect3D
,
6769 d3d_device3_SetCurrentViewport
,
6770 d3d_device3_GetCurrentViewport
,
6771 d3d_device3_SetRenderTarget
,
6772 d3d_device3_GetRenderTarget
,
6774 d3d_device3_BeginIndexed
,
6778 d3d_device3_GetRenderState
,
6779 d3d_device3_SetRenderState
,
6780 d3d_device3_GetLightState
,
6781 d3d_device3_SetLightState
,
6782 d3d_device3_SetTransform
,
6783 d3d_device3_GetTransform
,
6784 d3d_device3_MultiplyTransform
,
6785 d3d_device3_DrawPrimitive
,
6786 d3d_device3_DrawIndexedPrimitive
,
6787 d3d_device3_SetClipStatus
,
6788 d3d_device3_GetClipStatus
,
6789 d3d_device3_DrawPrimitiveStrided
,
6790 d3d_device3_DrawIndexedPrimitiveStrided
,
6791 d3d_device3_DrawPrimitiveVB
,
6792 d3d_device3_DrawIndexedPrimitiveVB
,
6793 d3d_device3_ComputeSphereVisibility
,
6794 d3d_device3_GetTexture
,
6795 d3d_device3_SetTexture
,
6796 d3d_device3_GetTextureStageState
,
6797 d3d_device3_SetTextureStageState
,
6798 d3d_device3_ValidateDevice
6801 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl
=
6803 /*** IUnknown Methods ***/
6804 d3d_device2_QueryInterface
,
6806 d3d_device2_Release
,
6807 /*** IDirect3DDevice2 ***/
6808 d3d_device2_GetCaps
,
6809 d3d_device2_SwapTextureHandles
,
6810 d3d_device2_GetStats
,
6811 d3d_device2_AddViewport
,
6812 d3d_device2_DeleteViewport
,
6813 d3d_device2_NextViewport
,
6814 d3d_device2_EnumTextureFormats
,
6815 d3d_device2_BeginScene
,
6816 d3d_device2_EndScene
,
6817 d3d_device2_GetDirect3D
,
6818 d3d_device2_SetCurrentViewport
,
6819 d3d_device2_GetCurrentViewport
,
6820 d3d_device2_SetRenderTarget
,
6821 d3d_device2_GetRenderTarget
,
6823 d3d_device2_BeginIndexed
,
6827 d3d_device2_GetRenderState
,
6828 d3d_device2_SetRenderState
,
6829 d3d_device2_GetLightState
,
6830 d3d_device2_SetLightState
,
6831 d3d_device2_SetTransform
,
6832 d3d_device2_GetTransform
,
6833 d3d_device2_MultiplyTransform
,
6834 d3d_device2_DrawPrimitive
,
6835 d3d_device2_DrawIndexedPrimitive
,
6836 d3d_device2_SetClipStatus
,
6837 d3d_device2_GetClipStatus
6840 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl
=
6842 /*** IUnknown Methods ***/
6843 d3d_device1_QueryInterface
,
6845 d3d_device1_Release
,
6846 /*** IDirect3DDevice1 ***/
6847 d3d_device1_Initialize
,
6848 d3d_device1_GetCaps
,
6849 d3d_device1_SwapTextureHandles
,
6850 d3d_device1_CreateExecuteBuffer
,
6851 d3d_device1_GetStats
,
6852 d3d_device1_Execute
,
6853 d3d_device1_AddViewport
,
6854 d3d_device1_DeleteViewport
,
6855 d3d_device1_NextViewport
,
6857 d3d_device1_GetPickRecords
,
6858 d3d_device1_EnumTextureFormats
,
6859 d3d_device1_CreateMatrix
,
6860 d3d_device1_SetMatrix
,
6861 d3d_device1_GetMatrix
,
6862 d3d_device1_DeleteMatrix
,
6863 d3d_device1_BeginScene
,
6864 d3d_device1_EndScene
,
6865 d3d_device1_GetDirect3D
6868 static const struct IUnknownVtbl d3d_device_inner_vtbl
=
6870 d3d_device_inner_QueryInterface
,
6871 d3d_device_inner_AddRef
,
6872 d3d_device_inner_Release
,
6875 struct d3d_device
*unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7
*iface
)
6877 if (!iface
) return NULL
;
6878 assert((iface
->lpVtbl
== &d3d_device7_fpu_preserve_vtbl
) || (iface
->lpVtbl
== &d3d_device7_fpu_setup_vtbl
));
6879 return CONTAINING_RECORD(iface
, struct d3d_device
, IDirect3DDevice7_iface
);
6882 struct d3d_device
*unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3
*iface
)
6884 if (!iface
) return NULL
;
6885 assert(iface
->lpVtbl
== &d3d_device3_vtbl
);
6886 return CONTAINING_RECORD(iface
, struct d3d_device
, IDirect3DDevice3_iface
);
6889 struct d3d_device
*unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2
*iface
)
6891 if (!iface
) return NULL
;
6892 assert(iface
->lpVtbl
== &d3d_device2_vtbl
);
6893 return CONTAINING_RECORD(iface
, struct d3d_device
, IDirect3DDevice2_iface
);
6896 struct d3d_device
*unsafe_impl_from_IDirect3DDevice(IDirect3DDevice
*iface
)
6898 if (!iface
) return NULL
;
6899 assert(iface
->lpVtbl
== &d3d_device1_vtbl
);
6900 return CONTAINING_RECORD(iface
, struct d3d_device
, IDirect3DDevice_iface
);
6903 enum wined3d_depth_buffer_type
d3d_device_update_depth_stencil(struct d3d_device
*device
)
6905 IDirectDrawSurface7
*depthStencil
= NULL
;
6906 IDirectDrawSurface7
*render_target
;
6907 static DDSCAPS2 depthcaps
= { DDSCAPS_ZBUFFER
, 0, 0, {0} };
6908 struct ddraw_surface
*dsi
;
6910 if (device
->rt_iface
&& SUCCEEDED(IUnknown_QueryInterface(device
->rt_iface
,
6911 &IID_IDirectDrawSurface7
, (void **)&render_target
)))
6913 IDirectDrawSurface7_GetAttachedSurface(render_target
, &depthcaps
, &depthStencil
);
6914 IDirectDrawSurface7_Release(render_target
);
6918 TRACE("Setting wined3d depth stencil to NULL\n");
6919 wined3d_device_set_depth_stencil_view(device
->wined3d_device
, NULL
);
6920 return WINED3D_ZB_FALSE
;
6923 dsi
= impl_from_IDirectDrawSurface7(depthStencil
);
6924 wined3d_device_set_depth_stencil_view(device
->wined3d_device
,
6925 ddraw_surface_get_rendertarget_view(dsi
));
6927 IDirectDrawSurface7_Release(depthStencil
);
6928 return WINED3D_ZB_TRUE
;
6931 static HRESULT
d3d_device_init(struct d3d_device
*device
, struct ddraw
*ddraw
,
6932 struct ddraw_surface
*target
, IUnknown
*rt_iface
, UINT version
, IUnknown
*outer_unknown
)
6934 static const D3DMATRIX ident
=
6936 1.0f
, 0.0f
, 0.0f
, 0.0f
,
6937 0.0f
, 1.0f
, 0.0f
, 0.0f
,
6938 0.0f
, 0.0f
, 1.0f
, 0.0f
,
6939 0.0f
, 0.0f
, 0.0f
, 1.0f
,
6943 if (ddraw
->cooperative_level
& DDSCL_FPUPRESERVE
)
6944 device
->IDirect3DDevice7_iface
.lpVtbl
= &d3d_device7_fpu_preserve_vtbl
;
6946 device
->IDirect3DDevice7_iface
.lpVtbl
= &d3d_device7_fpu_setup_vtbl
;
6948 device
->IDirect3DDevice3_iface
.lpVtbl
= &d3d_device3_vtbl
;
6949 device
->IDirect3DDevice2_iface
.lpVtbl
= &d3d_device2_vtbl
;
6950 device
->IDirect3DDevice_iface
.lpVtbl
= &d3d_device1_vtbl
;
6951 device
->IUnknown_inner
.lpVtbl
= &d3d_device_inner_vtbl
;
6953 device
->version
= version
;
6956 device
->outer_unknown
= outer_unknown
;
6958 device
->outer_unknown
= &device
->IUnknown_inner
;
6960 device
->ddraw
= ddraw
;
6961 list_init(&device
->viewport_list
);
6963 if (!ddraw_handle_table_init(&device
->handle_table
, 64))
6965 ERR("Failed to initialize handle table.\n");
6966 return DDERR_OUTOFMEMORY
;
6969 device
->legacyTextureBlending
= FALSE
;
6970 device
->legacy_projection
= ident
;
6971 device
->legacy_clipspace
= ident
;
6973 /* This is for convenience. */
6974 device
->wined3d_device
= ddraw
->wined3d_device
;
6975 wined3d_device_incref(ddraw
->wined3d_device
);
6977 /* Render to the back buffer */
6978 if (FAILED(hr
= wined3d_device_set_rendertarget_view(ddraw
->wined3d_device
,
6979 0, ddraw_surface_get_rendertarget_view(target
), TRUE
)))
6981 ERR("Failed to set render target, hr %#x.\n", hr
);
6982 ddraw_handle_table_destroy(&device
->handle_table
);
6986 device
->rt_iface
= rt_iface
;
6988 IUnknown_AddRef(device
->rt_iface
);
6990 ddraw
->d3ddevice
= device
;
6992 wined3d_device_set_render_state(ddraw
->wined3d_device
, WINED3D_RS_ZENABLE
,
6993 d3d_device_update_depth_stencil(device
));
6994 if (version
== 1) /* Color keying is initially enabled for version 1 devices. */
6995 wined3d_device_set_render_state(ddraw
->wined3d_device
, WINED3D_RS_COLORKEYENABLE
, TRUE
);
6996 else if (version
== 2)
6997 wined3d_device_set_render_state(ddraw
->wined3d_device
, WINED3D_RS_SPECULARENABLE
, TRUE
);
7000 wined3d_device_set_render_state(ddraw
->wined3d_device
, WINED3D_RS_NORMALIZENORMALS
, TRUE
);
7001 IDirect3DDevice3_SetRenderState(&device
->IDirect3DDevice3_iface
,
7002 D3DRENDERSTATE_TEXTUREMAPBLEND
, D3DTBLEND_MODULATE
);
7007 HRESULT
d3d_device_create(struct ddraw
*ddraw
, struct ddraw_surface
*target
, IUnknown
*rt_iface
,
7008 UINT version
, struct d3d_device
**device
, IUnknown
*outer_unknown
)
7010 struct d3d_device
*object
;
7013 TRACE("ddraw %p, target %p, version %u, device %p, outer_unknown %p.\n",
7014 ddraw
, target
, version
, device
, outer_unknown
);
7016 if (!(target
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_3DDEVICE
)
7017 || (target
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_ZBUFFER
))
7019 WARN("Surface %p is not a render target.\n", target
);
7020 return DDERR_INVALIDCAPS
;
7023 if (!validate_surface_palette(target
))
7025 WARN("Surface %p has an indexed pixel format, but no palette.\n", target
);
7026 return DDERR_NOPALETTEATTACHED
;
7029 if (ddraw
->flags
& DDRAW_NO3D
)
7031 ERR_(winediag
)("The application wants to create a Direct3D device, "
7032 "but the current DirectDrawRenderer does not support this.\n");
7034 return DDERR_OUTOFMEMORY
;
7037 if (!(target
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_VIDEOMEMORY
))
7039 WARN("Surface %p is not in video memory.\n", target
);
7040 return D3DERR_SURFACENOTINVIDMEM
;
7043 if (ddraw
->d3ddevice
)
7045 FIXME("Only one Direct3D device per DirectDraw object supported.\n");
7046 return DDERR_INVALIDPARAMS
;
7049 if (!(object
= heap_alloc_zero(sizeof(*object
))))
7051 ERR("Failed to allocate device memory.\n");
7052 return DDERR_OUTOFMEMORY
;
7055 if (FAILED(hr
= d3d_device_init(object
, ddraw
, target
, rt_iface
, version
, outer_unknown
)))
7057 WARN("Failed to initialize device, hr %#x.\n", hr
);
7062 TRACE("Created device %p.\n", object
);