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 enum wined3d_render_state
wined3d_render_state_from_ddraw(D3DRENDERSTATETYPE state
)
79 case D3DRENDERSTATE_ZBIAS
:
80 return WINED3D_RS_DEPTHBIAS
;
81 case D3DRENDERSTATE_EDGEANTIALIAS
:
82 return WINED3D_RS_ANTIALIASEDLINEENABLE
;
84 return (enum wined3d_render_state
)state
;
88 static enum wined3d_transform_state
wined3d_transform_state_from_ddraw(D3DTRANSFORMSTATETYPE state
)
92 case D3DTRANSFORMSTATE_WORLD
:
93 return WINED3D_TS_WORLD_MATRIX(0);
94 case D3DTRANSFORMSTATE_WORLD1
:
95 return WINED3D_TS_WORLD_MATRIX(1);
96 case D3DTRANSFORMSTATE_WORLD2
:
97 return WINED3D_TS_WORLD_MATRIX(2);
98 case D3DTRANSFORMSTATE_WORLD3
:
99 return WINED3D_TS_WORLD_MATRIX(3);
101 return (enum wined3d_transform_state
)state
;
105 static enum wined3d_primitive_type
wined3d_primitive_type_from_ddraw(D3DPRIMITIVETYPE type
)
107 return (enum wined3d_primitive_type
)type
;
110 static enum wined3d_stateblock_type
wined3d_stateblock_type_from_ddraw(D3DSTATEBLOCKTYPE type
)
112 return (enum wined3d_stateblock_type
)type
;
115 static inline struct d3d_device
*impl_from_IUnknown(IUnknown
*iface
)
117 return CONTAINING_RECORD(iface
, struct d3d_device
, IUnknown_inner
);
120 static HRESULT WINAPI
d3d_device_inner_QueryInterface(IUnknown
*iface
, REFIID riid
, void **out
)
122 struct d3d_device
*device
= impl_from_IUnknown(iface
);
124 TRACE("iface %p, riid %s, out %p.\n", iface
, debugstr_guid(riid
), out
);
129 return DDERR_INVALIDPARAMS
;
132 if (IsEqualGUID(&IID_IUnknown
, riid
))
134 IDirect3DDevice7_AddRef(&device
->IDirect3DDevice7_iface
);
135 *out
= &device
->IDirect3DDevice7_iface
;
139 if (device
->version
== 7)
141 if (IsEqualGUID(&IID_IDirect3DDevice7
, riid
))
143 IDirect3DDevice7_AddRef(&device
->IDirect3DDevice7_iface
);
144 *out
= &device
->IDirect3DDevice7_iface
;
150 if (IsEqualGUID(&IID_IDirect3DDevice3
, riid
) && device
->version
== 3)
152 IDirect3DDevice3_AddRef(&device
->IDirect3DDevice3_iface
);
153 *out
= &device
->IDirect3DDevice3_iface
;
157 if (IsEqualGUID(&IID_IDirect3DDevice2
, riid
) && device
->version
>= 2)
159 IDirect3DDevice2_AddRef(&device
->IDirect3DDevice2_iface
);
160 *out
= &device
->IDirect3DDevice2_iface
;
164 if (IsEqualGUID(&IID_IDirect3DDevice
, riid
))
166 IDirect3DDevice_AddRef(&device
->IDirect3DDevice_iface
);
167 *out
= &device
->IDirect3DDevice_iface
;
172 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid
));
175 return E_NOINTERFACE
;
178 static HRESULT WINAPI
d3d_device7_QueryInterface(IDirect3DDevice7
*iface
, REFIID riid
, void **out
)
180 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
182 TRACE("iface %p, riid %s, out %p.\n", iface
, debugstr_guid(riid
), out
);
184 return IUnknown_QueryInterface(device
->outer_unknown
, riid
, out
);
187 static HRESULT WINAPI
d3d_device3_QueryInterface(IDirect3DDevice3
*iface
, REFIID riid
, void **out
)
189 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
191 TRACE("iface %p, riid %s, out %p.\n", iface
, debugstr_guid(riid
), out
);
193 return IUnknown_QueryInterface(device
->outer_unknown
, riid
, out
);
196 static HRESULT WINAPI
d3d_device2_QueryInterface(IDirect3DDevice2
*iface
, REFIID riid
, void **out
)
198 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
200 TRACE("iface %p, riid %s, out %p.\n", iface
, debugstr_guid(riid
), out
);
202 return IUnknown_QueryInterface(device
->outer_unknown
, riid
, out
);
205 static HRESULT WINAPI
d3d_device1_QueryInterface(IDirect3DDevice
*iface
, REFIID riid
, void **out
)
207 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
209 TRACE("iface %p, riid %s, out %p.\n", iface
, debugstr_guid(riid
), out
);
211 return IUnknown_QueryInterface(device
->outer_unknown
, riid
, out
);
214 static ULONG WINAPI
d3d_device_inner_AddRef(IUnknown
*iface
)
216 struct d3d_device
*device
= impl_from_IUnknown(iface
);
217 ULONG ref
= InterlockedIncrement(&device
->ref
);
219 TRACE("%p increasing refcount to %u.\n", device
, ref
);
224 static ULONG WINAPI
d3d_device7_AddRef(IDirect3DDevice7
*iface
)
226 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
228 TRACE("iface %p.\n", iface
);
230 return IUnknown_AddRef(device
->outer_unknown
);
233 static ULONG WINAPI
d3d_device3_AddRef(IDirect3DDevice3
*iface
)
235 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
237 TRACE("iface %p.\n", iface
);
239 return IUnknown_AddRef(device
->outer_unknown
);
242 static ULONG WINAPI
d3d_device2_AddRef(IDirect3DDevice2
*iface
)
244 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
246 TRACE("iface %p.\n", iface
);
248 return IUnknown_AddRef(device
->outer_unknown
);
251 static ULONG WINAPI
d3d_device1_AddRef(IDirect3DDevice
*iface
)
253 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
255 TRACE("iface %p.\n", iface
);
257 return IUnknown_AddRef(device
->outer_unknown
);
260 static ULONG WINAPI
d3d_device_inner_Release(IUnknown
*iface
)
262 struct d3d_device
*This
= impl_from_IUnknown(iface
);
263 ULONG ref
= InterlockedDecrement(&This
->ref
);
266 TRACE("%p decreasing refcount to %u.\n", This
, ref
);
268 /* This method doesn't destroy the wined3d device, because it's still in
269 * use for 2D rendering. IDirectDrawSurface7::Release will destroy the
270 * wined3d device when the render target is released. */
274 struct list
*vp_entry
, *vp_entry2
;
276 wined3d_mutex_lock();
278 /* There is no need to unset any resources here, wined3d will take
279 * care of that on uninit_3d(). */
281 if (This
->index_buffer
)
282 wined3d_buffer_decref(This
->index_buffer
);
283 if (This
->vertex_buffer
)
284 wined3d_buffer_decref(This
->vertex_buffer
);
286 wined3d_device_set_rendertarget_view(This
->wined3d_device
, 0, NULL
, FALSE
);
288 wined3d_stateblock_decref(This
->state
);
290 wined3d_stateblock_decref(This
->recording
);
292 /* Release the wined3d device. This won't destroy it. */
293 if (!wined3d_device_decref(This
->wined3d_device
))
294 ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This
->wined3d_device
);
296 /* The texture handles should be unset by now, but there might be some bits
297 * missing in our reference counting(needs test). Do a sanity check. */
298 for (i
= 0; i
< This
->handle_table
.entry_count
; ++i
)
300 struct ddraw_handle_entry
*entry
= &This
->handle_table
.entries
[i
];
304 case DDRAW_HANDLE_FREE
:
307 case DDRAW_HANDLE_MATERIAL
:
309 struct d3d_material
*m
= entry
->object
;
310 FIXME("Material handle %#x (%p) not unset properly.\n", i
+ 1, m
);
315 case DDRAW_HANDLE_MATRIX
:
317 /* No FIXME here because this might happen because of sloppy applications. */
318 WARN("Leftover matrix handle %#x (%p), deleting.\n", i
+ 1, entry
->object
);
319 IDirect3DDevice_DeleteMatrix(&This
->IDirect3DDevice_iface
, i
+ 1);
323 case DDRAW_HANDLE_STATEBLOCK
:
325 /* No FIXME here because this might happen because of sloppy applications. */
326 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i
+ 1, entry
->object
);
327 IDirect3DDevice7_DeleteStateBlock(&This
->IDirect3DDevice7_iface
, i
+ 1);
331 case DDRAW_HANDLE_SURFACE
:
333 struct ddraw_surface
*surf
= entry
->object
;
334 FIXME("Texture handle %#x (%p) not unset properly.\n", i
+ 1, surf
);
340 FIXME("Handle %#x (%p) has unknown type %#x.\n", i
+ 1, entry
->object
, entry
->type
);
345 ddraw_handle_table_destroy(&This
->handle_table
);
347 LIST_FOR_EACH_SAFE(vp_entry
, vp_entry2
, &This
->viewport_list
)
349 struct d3d_viewport
*vp
= LIST_ENTRY(vp_entry
, struct d3d_viewport
, entry
);
350 IDirect3DDevice3_DeleteViewport(&This
->IDirect3DDevice3_iface
, &vp
->IDirect3DViewport3_iface
);
353 TRACE("Releasing render target %p.\n", This
->rt_iface
);
354 rt_iface
= This
->rt_iface
;
355 This
->rt_iface
= NULL
;
356 if (This
->version
!= 1)
357 IUnknown_Release(rt_iface
);
358 TRACE("Render target release done.\n");
360 /* Releasing the render target above may have released the last
361 * reference to the ddraw object. */
363 This
->ddraw
->d3ddevice
= NULL
;
365 /* Now free the structure */
367 wined3d_mutex_unlock();
374 static ULONG WINAPI
d3d_device7_Release(IDirect3DDevice7
*iface
)
376 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
378 TRACE("iface %p.\n", iface
);
380 return IUnknown_Release(device
->outer_unknown
);
383 static ULONG WINAPI
d3d_device3_Release(IDirect3DDevice3
*iface
)
385 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
387 TRACE("iface %p.\n", iface
);
389 return IUnknown_Release(device
->outer_unknown
);
392 static ULONG WINAPI
d3d_device2_Release(IDirect3DDevice2
*iface
)
394 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
396 TRACE("iface %p.\n", iface
);
398 return IUnknown_Release(device
->outer_unknown
);
401 static ULONG WINAPI
d3d_device1_Release(IDirect3DDevice
*iface
)
403 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
405 TRACE("iface %p.\n", iface
);
407 return IUnknown_Release(device
->outer_unknown
);
410 /*****************************************************************************
411 * IDirect3DDevice Methods
412 *****************************************************************************/
414 /*****************************************************************************
415 * IDirect3DDevice::Initialize
417 * Initializes a Direct3DDevice. This implementation is a no-op, as all
418 * initialization is done at create time.
420 * Exists in Version 1
423 * No idea what they mean, as the MSDN page is gone
427 *****************************************************************************/
428 static HRESULT WINAPI
d3d_device1_Initialize(IDirect3DDevice
*iface
,
429 IDirect3D
*d3d
, GUID
*guid
, D3DDEVICEDESC
*device_desc
)
431 /* It shouldn't be crucial, but print a FIXME, I'm interested if
432 * any game calls it and when. */
433 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
434 iface
, d3d
, debugstr_guid(guid
), device_desc
);
439 static HRESULT
d3d_device7_GetCaps(IDirect3DDevice7
*iface
, D3DDEVICEDESC7
*device_desc
)
441 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
443 TRACE("iface %p, device_desc %p.\n", iface
, device_desc
);
447 WARN("device_desc is NULL, returning DDERR_INVALIDPARAMS.\n");
448 return DDERR_INVALIDPARAMS
;
451 /* Call the same function used by IDirect3D, this saves code */
452 return ddraw_get_d3dcaps(device
->ddraw
, device_desc
);
455 static HRESULT WINAPI
d3d_device7_GetCaps_FPUSetup(IDirect3DDevice7
*iface
, D3DDEVICEDESC7
*desc
)
457 return d3d_device7_GetCaps(iface
, desc
);
460 static HRESULT WINAPI
d3d_device7_GetCaps_FPUPreserve(IDirect3DDevice7
*iface
, D3DDEVICEDESC7
*desc
)
465 old_fpucw
= d3d_fpu_setup();
466 hr
= d3d_device7_GetCaps(iface
, desc
);
467 set_fpu_control_word(old_fpucw
);
471 /*****************************************************************************
472 * IDirect3DDevice3::GetCaps
474 * Retrieves the capabilities of the hardware device and the emulation
475 * device. For Wine, hardware and emulation are the same (it's all HW).
477 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
480 * HWDesc: Structure to fill with the HW caps
481 * HelDesc: Structure to fill with the hardware emulation caps
485 * D3DERR_* if a problem occurs. See WineD3D
487 *****************************************************************************/
489 /* There are 3 versions of D3DDEVICEDESC. All 3 share the same name because
490 * Microsoft just expanded the existing structure without naming them
491 * D3DDEVICEDESC2 and D3DDEVICEDESC3. Which version is used have depends
492 * on the version of the DirectX SDK. DirectX 6+ and Wine use the latest
493 * one with 252 bytes.
495 * All 3 versions are allowed as parameters and only the specified amount of
498 * Note that Direct3D7 and earlier are not available in native Win64
499 * ddraw.dll builds, so possible size differences between 32 bit and
500 * 64 bit are a non-issue.
502 static inline BOOL
check_d3ddevicedesc_size(DWORD size
)
504 if (size
== FIELD_OFFSET(D3DDEVICEDESC
, dwMinTextureWidth
) /* 172 */
505 || size
== FIELD_OFFSET(D3DDEVICEDESC
, dwMaxTextureRepeat
) /* 204 */
506 || size
== sizeof(D3DDEVICEDESC
) /* 252 */) return TRUE
;
510 static HRESULT WINAPI
d3d_device3_GetCaps(IDirect3DDevice3
*iface
,
511 D3DDEVICEDESC
*HWDesc
, D3DDEVICEDESC
*HelDesc
)
513 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
514 D3DDEVICEDESC7 desc7
;
518 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface
, HWDesc
, HelDesc
);
522 WARN("HWDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
523 return DDERR_INVALIDPARAMS
;
525 if (!check_d3ddevicedesc_size(HWDesc
->dwSize
))
527 WARN("HWDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HWDesc
->dwSize
);
528 return DDERR_INVALIDPARAMS
;
532 WARN("HelDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
533 return DDERR_INVALIDPARAMS
;
535 if (!check_d3ddevicedesc_size(HelDesc
->dwSize
))
537 WARN("HelDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HelDesc
->dwSize
);
538 return DDERR_INVALIDPARAMS
;
541 if (FAILED(hr
= ddraw_get_d3dcaps(device
->ddraw
, &desc7
)))
544 ddraw_d3dcaps1_from_7(&desc1
, &desc7
);
545 DD_STRUCT_COPY_BYSIZE(HWDesc
, &desc1
);
546 DD_STRUCT_COPY_BYSIZE(HelDesc
, &desc1
);
550 static HRESULT WINAPI
d3d_device2_GetCaps(IDirect3DDevice2
*iface
,
551 D3DDEVICEDESC
*hw_desc
, D3DDEVICEDESC
*hel_desc
)
553 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
555 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface
, hw_desc
, hel_desc
);
557 return d3d_device3_GetCaps(&device
->IDirect3DDevice3_iface
, hw_desc
, hel_desc
);
560 static HRESULT WINAPI
d3d_device1_GetCaps(IDirect3DDevice
*iface
,
561 D3DDEVICEDESC
*hw_desc
, D3DDEVICEDESC
*hel_desc
)
563 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
565 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface
, hw_desc
, hel_desc
);
567 return d3d_device3_GetCaps(&device
->IDirect3DDevice3_iface
, hw_desc
, hel_desc
);
570 /*****************************************************************************
571 * IDirect3DDevice2::SwapTextureHandles
573 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
576 * Tex1, Tex2: The 2 Textures to swap
581 *****************************************************************************/
582 static HRESULT WINAPI
d3d_device2_SwapTextureHandles(IDirect3DDevice2
*iface
,
583 IDirect3DTexture2
*tex1
, IDirect3DTexture2
*tex2
)
585 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
586 struct ddraw_surface
*surf1
= unsafe_impl_from_IDirect3DTexture2(tex1
);
587 struct ddraw_surface
*surf2
= unsafe_impl_from_IDirect3DTexture2(tex2
);
590 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface
, tex1
, tex2
);
592 wined3d_mutex_lock();
594 h1
= surf1
->Handle
- 1;
595 h2
= surf2
->Handle
- 1;
596 device
->handle_table
.entries
[h1
].object
= surf2
;
597 device
->handle_table
.entries
[h2
].object
= surf1
;
598 surf2
->Handle
= h1
+ 1;
599 surf1
->Handle
= h2
+ 1;
601 wined3d_mutex_unlock();
606 static HRESULT WINAPI
d3d_device1_SwapTextureHandles(IDirect3DDevice
*iface
,
607 IDirect3DTexture
*tex1
, IDirect3DTexture
*tex2
)
609 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
610 struct ddraw_surface
*surf1
= unsafe_impl_from_IDirect3DTexture(tex1
);
611 struct ddraw_surface
*surf2
= unsafe_impl_from_IDirect3DTexture(tex2
);
612 IDirect3DTexture2
*t1
= surf1
? &surf1
->IDirect3DTexture2_iface
: NULL
;
613 IDirect3DTexture2
*t2
= surf2
? &surf2
->IDirect3DTexture2_iface
: NULL
;
615 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface
, tex1
, tex2
);
617 return d3d_device2_SwapTextureHandles(&device
->IDirect3DDevice2_iface
, t1
, t2
);
620 /*****************************************************************************
621 * IDirect3DDevice3::GetStats
623 * This method seems to retrieve some stats from the device.
624 * The MSDN documentation doesn't exist any more, but the D3DSTATS
625 * structure suggests that the amount of drawn primitives and processed
626 * vertices is returned.
628 * Exists in Version 1, 2 and 3
631 * Stats: Pointer to a D3DSTATS structure to be filled
635 * DDERR_INVALIDPARAMS if Stats == NULL
637 *****************************************************************************/
638 static HRESULT WINAPI
d3d_device3_GetStats(IDirect3DDevice3
*iface
, D3DSTATS
*Stats
)
640 FIXME("iface %p, stats %p stub!\n", iface
, Stats
);
643 return DDERR_INVALIDPARAMS
;
645 /* Fill the Stats with 0 */
646 Stats
->dwTrianglesDrawn
= 0;
647 Stats
->dwLinesDrawn
= 0;
648 Stats
->dwPointsDrawn
= 0;
649 Stats
->dwSpansDrawn
= 0;
650 Stats
->dwVerticesProcessed
= 0;
655 static HRESULT WINAPI
d3d_device2_GetStats(IDirect3DDevice2
*iface
, D3DSTATS
*stats
)
657 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
659 TRACE("iface %p, stats %p.\n", iface
, stats
);
661 return d3d_device3_GetStats(&device
->IDirect3DDevice3_iface
, stats
);
664 static HRESULT WINAPI
d3d_device1_GetStats(IDirect3DDevice
*iface
, D3DSTATS
*stats
)
666 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
668 TRACE("iface %p, stats %p.\n", iface
, stats
);
670 return d3d_device3_GetStats(&device
->IDirect3DDevice3_iface
, stats
);
673 /*****************************************************************************
674 * IDirect3DDevice::CreateExecuteBuffer
676 * Creates an IDirect3DExecuteBuffer, used for rendering with a
682 * Desc: Buffer description
683 * ExecuteBuffer: Address to return the Interface pointer at
684 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
688 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
689 * DDERR_OUTOFMEMORY if we ran out of memory
692 *****************************************************************************/
693 static HRESULT WINAPI
d3d_device1_CreateExecuteBuffer(IDirect3DDevice
*iface
,
694 D3DEXECUTEBUFFERDESC
*buffer_desc
, IDirect3DExecuteBuffer
**ExecuteBuffer
, IUnknown
*outer_unknown
)
696 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
697 struct d3d_execute_buffer
*object
;
700 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
701 iface
, buffer_desc
, ExecuteBuffer
, outer_unknown
);
704 return CLASS_E_NOAGGREGATION
;
706 /* Allocate the new Execute Buffer */
707 if (!(object
= heap_alloc_zero(sizeof(*object
))))
709 ERR("Failed to allocate execute buffer memory.\n");
710 return DDERR_OUTOFMEMORY
;
713 hr
= d3d_execute_buffer_init(object
, device
, buffer_desc
);
716 WARN("Failed to initialize execute buffer, hr %#x.\n", hr
);
721 *ExecuteBuffer
= &object
->IDirect3DExecuteBuffer_iface
;
723 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer
, object
);
728 /*****************************************************************************
729 * IDirect3DDevice::Execute
731 * Executes all the stuff in an execute buffer.
734 * ExecuteBuffer: The buffer to execute
735 * Viewport: The viewport used for rendering
739 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
742 *****************************************************************************/
743 static HRESULT WINAPI
d3d_device1_Execute(IDirect3DDevice
*iface
,
744 IDirect3DExecuteBuffer
*ExecuteBuffer
, IDirect3DViewport
*viewport
, DWORD flags
)
746 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
747 struct d3d_execute_buffer
*buffer
= unsafe_impl_from_IDirect3DExecuteBuffer(ExecuteBuffer
);
748 struct d3d_viewport
*viewport_impl
= unsafe_impl_from_IDirect3DViewport(viewport
);
751 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface
, ExecuteBuffer
, viewport
, flags
);
754 return DDERR_INVALIDPARAMS
;
756 if (FAILED(hr
= IDirect3DDevice3_SetCurrentViewport
757 (&device
->IDirect3DDevice3_iface
, &viewport_impl
->IDirect3DViewport3_iface
)))
761 wined3d_mutex_lock();
762 hr
= d3d_execute_buffer_execute(buffer
, device
);
763 wined3d_mutex_unlock();
768 /*****************************************************************************
769 * IDirect3DDevice3::AddViewport
771 * Add a Direct3DViewport to the device's viewport list. These viewports
772 * are wrapped to IDirect3DDevice7 viewports in viewport.c
774 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
775 * are the same interfaces.
778 * Viewport: The viewport to add
781 * DDERR_INVALIDPARAMS if Viewport == NULL
784 *****************************************************************************/
785 static HRESULT WINAPI
d3d_device3_AddViewport(IDirect3DDevice3
*iface
, IDirect3DViewport3
*viewport
)
787 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
788 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport3(viewport
);
790 TRACE("iface %p, viewport %p.\n", iface
, viewport
);
794 return DDERR_INVALIDPARAMS
;
796 wined3d_mutex_lock();
797 IDirect3DViewport3_AddRef(viewport
);
798 list_add_head(&device
->viewport_list
, &vp
->entry
);
799 /* Viewport must be usable for Clear() after AddViewport, so set active_device here. */
800 vp
->active_device
= device
;
801 wined3d_mutex_unlock();
806 static HRESULT WINAPI
d3d_device2_AddViewport(IDirect3DDevice2
*iface
,
807 IDirect3DViewport2
*viewport
)
809 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
810 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport2(viewport
);
812 TRACE("iface %p, viewport %p.\n", iface
, viewport
);
814 return d3d_device3_AddViewport(&device
->IDirect3DDevice3_iface
, &vp
->IDirect3DViewport3_iface
);
817 static HRESULT WINAPI
d3d_device1_AddViewport(IDirect3DDevice
*iface
, IDirect3DViewport
*viewport
)
819 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
820 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport(viewport
);
822 TRACE("iface %p, viewport %p.\n", iface
, viewport
);
824 return d3d_device3_AddViewport(&device
->IDirect3DDevice3_iface
, &vp
->IDirect3DViewport3_iface
);
827 /*****************************************************************************
828 * IDirect3DDevice3::DeleteViewport
830 * Deletes a Direct3DViewport from the device's viewport list.
832 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
836 * Viewport: The viewport to delete
840 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
842 *****************************************************************************/
843 static HRESULT WINAPI
d3d_device3_DeleteViewport(IDirect3DDevice3
*iface
, IDirect3DViewport3
*viewport
)
845 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
846 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport3(viewport
);
848 TRACE("iface %p, viewport %p.\n", iface
, viewport
);
852 WARN("NULL viewport, returning DDERR_INVALIDPARAMS\n");
853 return DDERR_INVALIDPARAMS
;
856 wined3d_mutex_lock();
858 if (vp
->active_device
!= device
)
860 WARN("Viewport %p active device is %p.\n", vp
, vp
->active_device
);
861 wined3d_mutex_unlock();
862 return DDERR_INVALIDPARAMS
;
865 if (device
->current_viewport
== vp
)
867 TRACE("Deleting current viewport, unsetting and releasing.\n");
869 viewport_deactivate(vp
);
870 IDirect3DViewport3_Release(viewport
);
871 device
->current_viewport
= NULL
;
874 vp
->active_device
= NULL
;
875 list_remove(&vp
->entry
);
877 IDirect3DViewport3_Release(viewport
);
879 wined3d_mutex_unlock();
884 static HRESULT WINAPI
d3d_device2_DeleteViewport(IDirect3DDevice2
*iface
, IDirect3DViewport2
*viewport
)
886 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
887 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport2(viewport
);
889 TRACE("iface %p, viewport %p.\n", iface
, viewport
);
891 return d3d_device3_DeleteViewport(&device
->IDirect3DDevice3_iface
,
892 vp
? &vp
->IDirect3DViewport3_iface
: NULL
);
895 static HRESULT WINAPI
d3d_device1_DeleteViewport(IDirect3DDevice
*iface
, IDirect3DViewport
*viewport
)
897 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
898 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport(viewport
);
900 TRACE("iface %p, viewport %p.\n", iface
, viewport
);
902 return d3d_device3_DeleteViewport(&device
->IDirect3DDevice3_iface
,
903 vp
? &vp
->IDirect3DViewport3_iface
: NULL
);
906 /*****************************************************************************
907 * IDirect3DDevice3::NextViewport
909 * Returns a viewport from the viewport list, depending on the
910 * passed viewport and the flags.
912 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
916 * Viewport: Viewport to use for beginning the search
917 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
921 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
923 *****************************************************************************/
924 static HRESULT WINAPI
d3d_device3_NextViewport(IDirect3DDevice3
*iface
,
925 IDirect3DViewport3
*Viewport3
, IDirect3DViewport3
**lplpDirect3DViewport3
, DWORD flags
)
927 struct d3d_device
*This
= impl_from_IDirect3DDevice3(iface
);
928 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport3(Viewport3
);
929 struct d3d_viewport
*next
;
932 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
933 iface
, Viewport3
, lplpDirect3DViewport3
, flags
);
937 *lplpDirect3DViewport3
= NULL
;
938 return DDERR_INVALIDPARAMS
;
942 wined3d_mutex_lock();
946 entry
= list_next(&This
->viewport_list
, &vp
->entry
);
950 entry
= list_head(&This
->viewport_list
);
954 entry
= list_tail(&This
->viewport_list
);
958 WARN("Invalid flags %#x.\n", flags
);
959 *lplpDirect3DViewport3
= NULL
;
960 wined3d_mutex_unlock();
961 return DDERR_INVALIDPARAMS
;
966 next
= LIST_ENTRY(entry
, struct d3d_viewport
, entry
);
967 *lplpDirect3DViewport3
= &next
->IDirect3DViewport3_iface
;
970 *lplpDirect3DViewport3
= NULL
;
972 wined3d_mutex_unlock();
977 static HRESULT WINAPI
d3d_device2_NextViewport(IDirect3DDevice2
*iface
,
978 IDirect3DViewport2
*viewport
, IDirect3DViewport2
**next
, DWORD flags
)
980 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
981 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport2(viewport
);
982 IDirect3DViewport3
*res
;
985 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
986 iface
, viewport
, next
, flags
);
988 hr
= d3d_device3_NextViewport(&device
->IDirect3DDevice3_iface
,
989 &vp
->IDirect3DViewport3_iface
, &res
, flags
);
990 *next
= (IDirect3DViewport2
*)res
;
994 static HRESULT WINAPI
d3d_device1_NextViewport(IDirect3DDevice
*iface
,
995 IDirect3DViewport
*viewport
, IDirect3DViewport
**next
, DWORD flags
)
997 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
998 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport(viewport
);
999 IDirect3DViewport3
*res
;
1002 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
1003 iface
, viewport
, next
, flags
);
1005 hr
= d3d_device3_NextViewport(&device
->IDirect3DDevice3_iface
,
1006 &vp
->IDirect3DViewport3_iface
, &res
, flags
);
1007 *next
= (IDirect3DViewport
*)res
;
1011 /*****************************************************************************
1012 * IDirect3DDevice::Pick
1014 * Executes an execute buffer without performing rendering. Instead, a
1015 * list of primitives that intersect with (x1,y1) of the passed rectangle
1016 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
1022 * ExecuteBuffer: Buffer to execute
1023 * Viewport: Viewport to use for execution
1024 * Flags: None are defined, according to the SDK
1025 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
1026 * x2 and y2 are ignored.
1029 * D3D_OK because it's a stub
1031 *****************************************************************************/
1032 static HRESULT WINAPI
d3d_device1_Pick(IDirect3DDevice
*iface
, IDirect3DExecuteBuffer
*buffer
,
1033 IDirect3DViewport
*viewport
, DWORD flags
, D3DRECT
*rect
)
1035 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
1036 iface
, buffer
, viewport
, flags
, wine_dbgstr_rect((RECT
*)rect
));
1041 /*****************************************************************************
1042 * IDirect3DDevice::GetPickRecords
1044 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1049 * Count: Pointer to a DWORD containing the numbers of pick records to
1051 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1054 * D3D_OK, because it's a stub
1056 *****************************************************************************/
1057 static HRESULT WINAPI
d3d_device1_GetPickRecords(IDirect3DDevice
*iface
,
1058 DWORD
*count
, D3DPICKRECORD
*records
)
1060 FIXME("iface %p, count %p, records %p stub!\n", iface
, count
, records
);
1065 /*****************************************************************************
1066 * IDirect3DDevice7::EnumTextureformats
1068 * Enumerates the supported texture formats. It checks against a list of all possible
1069 * formats to see if WineD3D supports it. If so, then it is passed to the app.
1071 * This is for Version 7 and 3, older versions have a different
1072 * callback function and their own implementation
1075 * Callback: Callback to call for each enumerated format
1076 * Arg: Argument to pass to the callback
1080 * DDERR_INVALIDPARAMS if Callback == NULL
1082 *****************************************************************************/
1083 static HRESULT
d3d_device7_EnumTextureFormats(IDirect3DDevice7
*iface
,
1084 LPD3DENUMPIXELFORMATSCALLBACK callback
, void *context
)
1086 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
1087 struct wined3d_display_mode mode
;
1091 static const enum wined3d_format_id FormatList
[] =
1094 WINED3DFMT_B5G5R5X1_UNORM
,
1095 WINED3DFMT_B5G5R5A1_UNORM
,
1096 WINED3DFMT_B4G4R4A4_UNORM
,
1097 WINED3DFMT_B5G6R5_UNORM
,
1099 WINED3DFMT_B8G8R8X8_UNORM
,
1100 WINED3DFMT_B8G8R8A8_UNORM
,
1102 WINED3DFMT_B2G3R3_UNORM
,
1112 static const enum wined3d_format_id BumpFormatList
[] =
1114 WINED3DFMT_R8G8_SNORM
,
1115 WINED3DFMT_R5G5_SNORM_L6_UNORM
,
1116 WINED3DFMT_R8G8_SNORM_L8X8_UNORM
,
1117 WINED3DFMT_R10G11B11_SNORM
,
1118 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1121 TRACE("iface %p, callback %p, context %p.\n", iface
, callback
, context
);
1124 return DDERR_INVALIDPARAMS
;
1126 wined3d_mutex_lock();
1128 memset(&mode
, 0, sizeof(mode
));
1129 if (FAILED(hr
= wined3d_output_get_display_mode(device
->ddraw
->wined3d_output
, &mode
, NULL
)))
1131 wined3d_mutex_unlock();
1132 WARN("Failed to get output display mode, hr %#x.\n", hr
);
1136 for (i
= 0; i
< ARRAY_SIZE(FormatList
); ++i
)
1138 if (wined3d_check_device_format(device
->ddraw
->wined3d
, device
->ddraw
->wined3d_adapter
,
1139 WINED3D_DEVICE_TYPE_HAL
, mode
.format_id
, 0, WINED3D_BIND_SHADER_RESOURCE
,
1140 WINED3D_RTYPE_TEXTURE_2D
, FormatList
[i
]) == D3D_OK
)
1142 DDPIXELFORMAT pformat
;
1144 memset(&pformat
, 0, sizeof(pformat
));
1145 pformat
.dwSize
= sizeof(pformat
);
1146 ddrawformat_from_wined3dformat(&pformat
, FormatList
[i
]);
1148 TRACE("Enumerating WineD3DFormat %d\n", FormatList
[i
]);
1149 hr
= callback(&pformat
, context
);
1150 if(hr
!= DDENUMRET_OK
)
1152 TRACE("Format enumeration cancelled by application\n");
1153 wined3d_mutex_unlock();
1159 for (i
= 0; i
< ARRAY_SIZE(BumpFormatList
); ++i
)
1161 if (wined3d_check_device_format(device
->ddraw
->wined3d
, device
->ddraw
->wined3d_adapter
,
1162 WINED3D_DEVICE_TYPE_HAL
, mode
.format_id
, WINED3DUSAGE_QUERY_LEGACYBUMPMAP
,
1163 WINED3D_BIND_SHADER_RESOURCE
, WINED3D_RTYPE_TEXTURE_2D
, BumpFormatList
[i
]) == D3D_OK
)
1165 DDPIXELFORMAT pformat
;
1167 memset(&pformat
, 0, sizeof(pformat
));
1168 pformat
.dwSize
= sizeof(pformat
);
1169 ddrawformat_from_wined3dformat(&pformat
, BumpFormatList
[i
]);
1171 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList
[i
]);
1172 hr
= callback(&pformat
, context
);
1173 if(hr
!= DDENUMRET_OK
)
1175 TRACE("Format enumeration cancelled by application\n");
1176 wined3d_mutex_unlock();
1181 TRACE("End of enumeration\n");
1182 wined3d_mutex_unlock();
1187 static HRESULT WINAPI
d3d_device7_EnumTextureFormats_FPUSetup(IDirect3DDevice7
*iface
,
1188 LPD3DENUMPIXELFORMATSCALLBACK callback
, void *context
)
1190 return d3d_device7_EnumTextureFormats(iface
, callback
, context
);
1193 static HRESULT WINAPI
d3d_device7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7
*iface
,
1194 LPD3DENUMPIXELFORMATSCALLBACK callback
, void *context
)
1199 old_fpucw
= d3d_fpu_setup();
1200 hr
= d3d_device7_EnumTextureFormats(iface
, callback
, context
);
1201 set_fpu_control_word(old_fpucw
);
1206 static HRESULT WINAPI
d3d_device3_EnumTextureFormats(IDirect3DDevice3
*iface
,
1207 LPD3DENUMPIXELFORMATSCALLBACK callback
, void *context
)
1209 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
1211 TRACE("iface %p, callback %p, context %p.\n", iface
, callback
, context
);
1213 return IDirect3DDevice7_EnumTextureFormats(&device
->IDirect3DDevice7_iface
, callback
, context
);
1216 /*****************************************************************************
1217 * IDirect3DDevice2::EnumTextureformats
1219 * EnumTextureFormats for Version 1 and 2, see
1220 * IDirect3DDevice7::EnumTextureFormats for a more detailed description.
1222 * This version has a different callback and does not enumerate FourCC
1225 *****************************************************************************/
1226 static HRESULT WINAPI
d3d_device2_EnumTextureFormats(IDirect3DDevice2
*iface
,
1227 LPD3DENUMTEXTUREFORMATSCALLBACK callback
, void *context
)
1229 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
1230 struct wined3d_display_mode mode
;
1234 static const enum wined3d_format_id FormatList
[] =
1237 WINED3DFMT_B5G5R5X1_UNORM
,
1238 WINED3DFMT_B5G5R5A1_UNORM
,
1239 WINED3DFMT_B4G4R4A4_UNORM
,
1240 WINED3DFMT_B5G6R5_UNORM
,
1242 WINED3DFMT_B8G8R8X8_UNORM
,
1243 WINED3DFMT_B8G8R8A8_UNORM
,
1245 WINED3DFMT_B2G3R3_UNORM
,
1247 /* FOURCC codes - Not in this version*/
1250 TRACE("iface %p, callback %p, context %p.\n", iface
, callback
, context
);
1253 return DDERR_INVALIDPARAMS
;
1255 wined3d_mutex_lock();
1257 memset(&mode
, 0, sizeof(mode
));
1258 if (FAILED(hr
= wined3d_output_get_display_mode(device
->ddraw
->wined3d_output
, &mode
, NULL
)))
1260 wined3d_mutex_unlock();
1261 WARN("Failed to get output display mode, hr %#x.\n", hr
);
1265 for (i
= 0; i
< ARRAY_SIZE(FormatList
); ++i
)
1267 if (wined3d_check_device_format(device
->ddraw
->wined3d
, device
->ddraw
->wined3d_adapter
,
1268 WINED3D_DEVICE_TYPE_HAL
, mode
.format_id
, 0, WINED3D_BIND_SHADER_RESOURCE
,
1269 WINED3D_RTYPE_TEXTURE_2D
, FormatList
[i
]) == D3D_OK
)
1271 DDSURFACEDESC sdesc
;
1273 memset(&sdesc
, 0, sizeof(sdesc
));
1274 sdesc
.dwSize
= sizeof(sdesc
);
1275 sdesc
.dwFlags
= DDSD_PIXELFORMAT
| DDSD_CAPS
;
1276 sdesc
.ddsCaps
.dwCaps
= DDSCAPS_TEXTURE
;
1277 sdesc
.ddpfPixelFormat
.dwSize
= sizeof(sdesc
.ddpfPixelFormat
);
1278 ddrawformat_from_wined3dformat(&sdesc
.ddpfPixelFormat
, FormatList
[i
]);
1280 TRACE("Enumerating WineD3DFormat %d\n", FormatList
[i
]);
1281 hr
= callback(&sdesc
, context
);
1282 if(hr
!= DDENUMRET_OK
)
1284 TRACE("Format enumeration cancelled by application\n");
1285 wined3d_mutex_unlock();
1290 TRACE("End of enumeration\n");
1291 wined3d_mutex_unlock();
1296 static HRESULT WINAPI
d3d_device1_EnumTextureFormats(IDirect3DDevice
*iface
,
1297 LPD3DENUMTEXTUREFORMATSCALLBACK callback
, void *context
)
1299 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
1301 TRACE("iface %p, callback %p, context %p.\n", iface
, callback
, context
);
1303 return d3d_device2_EnumTextureFormats(&device
->IDirect3DDevice2_iface
, callback
, context
);
1306 /*****************************************************************************
1307 * IDirect3DDevice::CreateMatrix
1309 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1310 * allocated for the handle.
1315 * D3DMatHandle: Address to return the handle at
1319 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1321 *****************************************************************************/
1322 static HRESULT WINAPI
d3d_device1_CreateMatrix(IDirect3DDevice
*iface
, D3DMATRIXHANDLE
*D3DMatHandle
)
1324 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
1328 TRACE("iface %p, matrix_handle %p.\n", iface
, D3DMatHandle
);
1331 return DDERR_INVALIDPARAMS
;
1333 if (!(matrix
= heap_alloc_zero(sizeof(*matrix
))))
1335 ERR("Out of memory when allocating a D3DMATRIX\n");
1336 return DDERR_OUTOFMEMORY
;
1339 wined3d_mutex_lock();
1341 h
= ddraw_allocate_handle(&device
->handle_table
, matrix
, DDRAW_HANDLE_MATRIX
);
1342 if (h
== DDRAW_INVALID_HANDLE
)
1344 ERR("Failed to allocate a matrix handle.\n");
1346 wined3d_mutex_unlock();
1347 return DDERR_OUTOFMEMORY
;
1350 *D3DMatHandle
= h
+ 1;
1352 TRACE(" returning matrix handle %d\n", *D3DMatHandle
);
1354 wined3d_mutex_unlock();
1359 /*****************************************************************************
1360 * IDirect3DDevice::SetMatrix
1362 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1363 * allocated for the handle
1368 * D3DMatHandle: Handle to set the matrix to
1369 * D3DMatrix: Matrix to set
1373 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1376 *****************************************************************************/
1377 static HRESULT WINAPI
d3d_device1_SetMatrix(IDirect3DDevice
*iface
,
1378 D3DMATRIXHANDLE matrix_handle
, D3DMATRIX
*matrix
)
1380 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
1383 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface
, matrix_handle
, matrix
);
1386 return DDERR_INVALIDPARAMS
;
1388 wined3d_mutex_lock();
1390 m
= ddraw_get_object(&device
->handle_table
, matrix_handle
- 1, DDRAW_HANDLE_MATRIX
);
1393 WARN("Invalid matrix handle.\n");
1394 wined3d_mutex_unlock();
1395 return DDERR_INVALIDPARAMS
;
1398 if (TRACE_ON(ddraw
))
1399 dump_D3DMATRIX(matrix
);
1403 if (matrix_handle
== device
->world
)
1404 wined3d_stateblock_set_transform(device
->state
,
1405 WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix
*)matrix
);
1407 if (matrix_handle
== device
->view
)
1408 wined3d_stateblock_set_transform(device
->state
,
1409 WINED3D_TS_VIEW
, (struct wined3d_matrix
*)matrix
);
1411 if (matrix_handle
== device
->proj
)
1412 wined3d_stateblock_set_transform(device
->state
,
1413 WINED3D_TS_PROJECTION
, (struct wined3d_matrix
*)matrix
);
1415 wined3d_mutex_unlock();
1420 /*****************************************************************************
1421 * IDirect3DDevice::GetMatrix
1423 * Returns the content of a D3DMATRIX handle
1428 * D3DMatHandle: Matrix handle to read the content from
1429 * D3DMatrix: Address to store the content at
1433 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1435 *****************************************************************************/
1436 static HRESULT WINAPI
d3d_device1_GetMatrix(IDirect3DDevice
*iface
,
1437 D3DMATRIXHANDLE D3DMatHandle
, D3DMATRIX
*D3DMatrix
)
1439 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
1442 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface
, D3DMatHandle
, D3DMatrix
);
1444 if (!D3DMatrix
) return DDERR_INVALIDPARAMS
;
1446 wined3d_mutex_lock();
1448 m
= ddraw_get_object(&device
->handle_table
, D3DMatHandle
- 1, DDRAW_HANDLE_MATRIX
);
1451 WARN("Invalid matrix handle.\n");
1452 wined3d_mutex_unlock();
1453 return DDERR_INVALIDPARAMS
;
1458 wined3d_mutex_unlock();
1463 /*****************************************************************************
1464 * IDirect3DDevice::DeleteMatrix
1466 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1471 * D3DMatHandle: Handle to destroy
1475 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1477 *****************************************************************************/
1478 static HRESULT WINAPI
d3d_device1_DeleteMatrix(IDirect3DDevice
*iface
, D3DMATRIXHANDLE D3DMatHandle
)
1480 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
1483 TRACE("iface %p, matrix_handle %#x.\n", iface
, D3DMatHandle
);
1485 wined3d_mutex_lock();
1487 m
= ddraw_free_handle(&device
->handle_table
, D3DMatHandle
- 1, DDRAW_HANDLE_MATRIX
);
1490 WARN("Invalid matrix handle.\n");
1491 wined3d_mutex_unlock();
1492 return DDERR_INVALIDPARAMS
;
1495 wined3d_mutex_unlock();
1502 /*****************************************************************************
1503 * IDirect3DDevice7::BeginScene
1505 * This method must be called before any rendering is performed.
1506 * IDirect3DDevice::EndScene has to be called after the scene is complete
1508 * Version 1, 2, 3 and 7
1511 * D3D_OK on success,
1512 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1515 *****************************************************************************/
1516 static HRESULT
d3d_device7_BeginScene(IDirect3DDevice7
*iface
)
1518 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
1521 TRACE("iface %p.\n", iface
);
1523 wined3d_mutex_lock();
1524 hr
= wined3d_device_begin_scene(device
->wined3d_device
);
1525 wined3d_mutex_unlock();
1527 if(hr
== WINED3D_OK
) return D3D_OK
;
1528 else return D3DERR_SCENE_IN_SCENE
; /* TODO: Other possible causes of failure */
1531 static HRESULT WINAPI
d3d_device7_BeginScene_FPUSetup(IDirect3DDevice7
*iface
)
1533 return d3d_device7_BeginScene(iface
);
1536 static HRESULT WINAPI
d3d_device7_BeginScene_FPUPreserve(IDirect3DDevice7
*iface
)
1541 old_fpucw
= d3d_fpu_setup();
1542 hr
= d3d_device7_BeginScene(iface
);
1543 set_fpu_control_word(old_fpucw
);
1548 static HRESULT WINAPI
d3d_device3_BeginScene(IDirect3DDevice3
*iface
)
1550 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
1552 TRACE("iface %p.\n", iface
);
1554 return IDirect3DDevice7_BeginScene(&device
->IDirect3DDevice7_iface
);
1557 static HRESULT WINAPI
d3d_device2_BeginScene(IDirect3DDevice2
*iface
)
1559 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
1561 TRACE("iface %p.\n", iface
);
1563 return IDirect3DDevice7_BeginScene(&device
->IDirect3DDevice7_iface
);
1566 static HRESULT WINAPI
d3d_device1_BeginScene(IDirect3DDevice
*iface
)
1568 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
1570 TRACE("iface %p.\n", iface
);
1572 return IDirect3DDevice7_BeginScene(&device
->IDirect3DDevice7_iface
);
1575 /*****************************************************************************
1576 * IDirect3DDevice7::EndScene
1578 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1579 * This method must be called after rendering is finished.
1581 * Version 1, 2, 3 and 7
1584 * D3D_OK on success,
1585 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1586 * that only if the scene was already ended.
1588 *****************************************************************************/
1589 static HRESULT
d3d_device7_EndScene(IDirect3DDevice7
*iface
)
1591 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
1594 TRACE("iface %p.\n", iface
);
1596 wined3d_mutex_lock();
1597 hr
= wined3d_device_end_scene(device
->wined3d_device
);
1598 wined3d_mutex_unlock();
1600 if(hr
== WINED3D_OK
) return D3D_OK
;
1601 else return D3DERR_SCENE_NOT_IN_SCENE
;
1604 static HRESULT WINAPI DECLSPEC_HOTPATCH
d3d_device7_EndScene_FPUSetup(IDirect3DDevice7
*iface
)
1606 return d3d_device7_EndScene(iface
);
1609 static HRESULT WINAPI DECLSPEC_HOTPATCH
d3d_device7_EndScene_FPUPreserve(IDirect3DDevice7
*iface
)
1614 old_fpucw
= d3d_fpu_setup();
1615 hr
= d3d_device7_EndScene(iface
);
1616 set_fpu_control_word(old_fpucw
);
1621 static HRESULT WINAPI DECLSPEC_HOTPATCH
d3d_device3_EndScene(IDirect3DDevice3
*iface
)
1623 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
1625 TRACE("iface %p.\n", iface
);
1627 return IDirect3DDevice7_EndScene(&device
->IDirect3DDevice7_iface
);
1630 static HRESULT WINAPI DECLSPEC_HOTPATCH
d3d_device2_EndScene(IDirect3DDevice2
*iface
)
1632 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
1634 TRACE("iface %p.\n", iface
);
1636 return IDirect3DDevice7_EndScene(&device
->IDirect3DDevice7_iface
);
1639 static HRESULT WINAPI DECLSPEC_HOTPATCH
d3d_device1_EndScene(IDirect3DDevice
*iface
)
1641 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
1643 TRACE("iface %p.\n", iface
);
1645 return IDirect3DDevice7_EndScene(&device
->IDirect3DDevice7_iface
);
1648 /*****************************************************************************
1649 * IDirect3DDevice7::GetDirect3D
1651 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1655 * Direct3D7: Address to store the interface pointer at
1659 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1661 *****************************************************************************/
1662 static HRESULT WINAPI
d3d_device7_GetDirect3D(IDirect3DDevice7
*iface
, IDirect3D7
**d3d
)
1664 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
1666 TRACE("iface %p, d3d %p.\n", iface
, d3d
);
1669 return DDERR_INVALIDPARAMS
;
1671 *d3d
= &device
->ddraw
->IDirect3D7_iface
;
1672 IDirect3D7_AddRef(*d3d
);
1674 TRACE("Returning interface %p.\n", *d3d
);
1678 static HRESULT WINAPI
d3d_device3_GetDirect3D(IDirect3DDevice3
*iface
, IDirect3D3
**d3d
)
1680 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
1682 TRACE("iface %p, d3d %p.\n", iface
, d3d
);
1685 return DDERR_INVALIDPARAMS
;
1687 *d3d
= &device
->ddraw
->IDirect3D3_iface
;
1688 IDirect3D3_AddRef(*d3d
);
1690 TRACE("Returning interface %p.\n", *d3d
);
1694 static HRESULT WINAPI
d3d_device2_GetDirect3D(IDirect3DDevice2
*iface
, IDirect3D2
**d3d
)
1696 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
1698 TRACE("iface %p, d3d %p.\n", iface
, d3d
);
1701 return DDERR_INVALIDPARAMS
;
1703 *d3d
= &device
->ddraw
->IDirect3D2_iface
;
1704 IDirect3D2_AddRef(*d3d
);
1706 TRACE("Returning interface %p.\n", *d3d
);
1710 static HRESULT WINAPI
d3d_device1_GetDirect3D(IDirect3DDevice
*iface
, IDirect3D
**d3d
)
1712 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
1714 TRACE("iface %p, d3d %p.\n", iface
, d3d
);
1717 return DDERR_INVALIDPARAMS
;
1719 *d3d
= &device
->ddraw
->IDirect3D_iface
;
1720 IDirect3D_AddRef(*d3d
);
1722 TRACE("Returning interface %p.\n", *d3d
);
1726 /*****************************************************************************
1727 * IDirect3DDevice3::SetCurrentViewport
1729 * Sets a Direct3DViewport as the current viewport.
1730 * For the thunks note that all viewport interface versions are equal
1733 * Direct3DViewport3: The viewport to set
1739 * (Is a NULL viewport valid?)
1741 *****************************************************************************/
1742 static HRESULT WINAPI
d3d_device3_SetCurrentViewport(IDirect3DDevice3
*iface
, IDirect3DViewport3
*viewport
)
1744 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport3(viewport
);
1745 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
1747 TRACE("iface %p, viewport %p, current_viewport %p.\n", iface
, viewport
, device
->current_viewport
);
1751 WARN("Direct3DViewport3 is NULL.\n");
1752 return DDERR_INVALIDPARAMS
;
1755 wined3d_mutex_lock();
1756 /* Do nothing if the specified viewport is the same as the current one */
1757 if (device
->current_viewport
== vp
)
1759 wined3d_mutex_unlock();
1763 if (vp
->active_device
!= device
)
1765 WARN("Viewport %p, active device %p.\n", vp
, vp
->active_device
);
1766 wined3d_mutex_unlock();
1767 return DDERR_INVALIDPARAMS
;
1770 IDirect3DViewport3_AddRef(viewport
);
1771 if (device
->current_viewport
)
1773 viewport_deactivate(device
->current_viewport
);
1774 IDirect3DViewport3_Release(&device
->current_viewport
->IDirect3DViewport3_iface
);
1776 device
->current_viewport
= vp
;
1777 viewport_activate(device
->current_viewport
, FALSE
);
1779 wined3d_mutex_unlock();
1784 static HRESULT WINAPI
d3d_device2_SetCurrentViewport(IDirect3DDevice2
*iface
, IDirect3DViewport2
*viewport
)
1786 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
1787 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport2(viewport
);
1789 TRACE("iface %p, viewport %p.\n", iface
, viewport
);
1791 return d3d_device3_SetCurrentViewport(&device
->IDirect3DDevice3_iface
,
1792 vp
? &vp
->IDirect3DViewport3_iface
: NULL
);
1795 /*****************************************************************************
1796 * IDirect3DDevice3::GetCurrentViewport
1798 * Returns the currently active viewport.
1803 * Direct3DViewport3: Address to return the interface pointer at
1807 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1809 *****************************************************************************/
1810 static HRESULT WINAPI
d3d_device3_GetCurrentViewport(IDirect3DDevice3
*iface
, IDirect3DViewport3
**viewport
)
1812 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
1814 TRACE("iface %p, viewport %p.\n", iface
, viewport
);
1816 wined3d_mutex_lock();
1817 if (!device
->current_viewport
)
1819 wined3d_mutex_unlock();
1820 WARN("No current viewport, returning D3DERR_NOCURRENTVIEWPORT\n");
1821 return D3DERR_NOCURRENTVIEWPORT
;
1824 *viewport
= &device
->current_viewport
->IDirect3DViewport3_iface
;
1825 IDirect3DViewport3_AddRef(*viewport
);
1827 TRACE("Returning interface %p.\n", *viewport
);
1828 wined3d_mutex_unlock();
1832 static HRESULT WINAPI
d3d_device2_GetCurrentViewport(IDirect3DDevice2
*iface
, IDirect3DViewport2
**viewport
)
1834 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
1836 TRACE("iface %p, viewport %p.\n", iface
, viewport
);
1838 return d3d_device3_GetCurrentViewport(&device
->IDirect3DDevice3_iface
,
1839 (IDirect3DViewport3
**)viewport
);
1842 static BOOL
validate_surface_palette(struct ddraw_surface
*surface
)
1844 return !format_is_paletteindexed(&surface
->surface_desc
.u4
.ddpfPixelFormat
)
1845 || surface
->palette
;
1848 static HRESULT
d3d_device_set_render_target(struct d3d_device
*device
,
1849 struct ddraw_surface
*target
, IUnknown
*rt_iface
)
1853 if (device
->rt_iface
== rt_iface
)
1855 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1860 WARN("Trying to set render target to NULL.\n");
1861 return DDERR_INVALIDPARAMS
;
1864 if (FAILED(hr
= wined3d_device_set_rendertarget_view(device
->wined3d_device
,
1865 0, ddraw_surface_get_rendertarget_view(target
), FALSE
)))
1868 IUnknown_AddRef(rt_iface
);
1869 IUnknown_Release(device
->rt_iface
);
1870 device
->rt_iface
= rt_iface
;
1871 d3d_device_update_depth_stencil(device
);
1876 static HRESULT
d3d_device7_SetRenderTarget(IDirect3DDevice7
*iface
,
1877 IDirectDrawSurface7
*target
, DWORD flags
)
1879 struct ddraw_surface
*target_impl
= unsafe_impl_from_IDirectDrawSurface7(target
);
1880 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
1883 TRACE("iface %p, target %p, flags %#x.\n", iface
, target
, flags
);
1885 wined3d_mutex_lock();
1887 if (!validate_surface_palette(target_impl
))
1889 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl
);
1890 wined3d_mutex_unlock();
1891 return DDERR_INVALIDCAPS
;
1894 if (!(target_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_3DDEVICE
))
1896 WARN("Surface %p is not a render target.\n", target_impl
);
1897 wined3d_mutex_unlock();
1898 return DDERR_INVALIDCAPS
;
1901 if (!(target_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_VIDEOMEMORY
))
1903 WARN("Surface %p is not in video memory.\n", target_impl
);
1904 wined3d_mutex_unlock();
1905 return DDERR_INVALIDPARAMS
;
1908 if (target_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_ZBUFFER
)
1910 WARN("Surface %p is a depth buffer.\n", target_impl
);
1911 IDirectDrawSurface7_AddRef(target
);
1912 IUnknown_Release(device
->rt_iface
);
1913 device
->rt_iface
= (IUnknown
*)target
;
1914 wined3d_mutex_unlock();
1915 return DDERR_INVALIDPIXELFORMAT
;
1918 hr
= d3d_device_set_render_target(device
, target_impl
, (IUnknown
*)target
);
1919 wined3d_mutex_unlock();
1923 static HRESULT WINAPI
d3d_device7_SetRenderTarget_FPUSetup(IDirect3DDevice7
*iface
,
1924 IDirectDrawSurface7
*NewTarget
, DWORD flags
)
1926 return d3d_device7_SetRenderTarget(iface
, NewTarget
, flags
);
1929 static HRESULT WINAPI
d3d_device7_SetRenderTarget_FPUPreserve(IDirect3DDevice7
*iface
,
1930 IDirectDrawSurface7
*NewTarget
, DWORD flags
)
1935 old_fpucw
= d3d_fpu_setup();
1936 hr
= d3d_device7_SetRenderTarget(iface
, NewTarget
, flags
);
1937 set_fpu_control_word(old_fpucw
);
1942 static HRESULT WINAPI
d3d_device3_SetRenderTarget(IDirect3DDevice3
*iface
,
1943 IDirectDrawSurface4
*target
, DWORD flags
)
1945 struct ddraw_surface
*target_impl
= unsafe_impl_from_IDirectDrawSurface4(target
);
1946 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
1949 TRACE("iface %p, target %p, flags %#x.\n", iface
, target
, flags
);
1951 wined3d_mutex_lock();
1953 if (!validate_surface_palette(target_impl
))
1955 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl
);
1956 wined3d_mutex_unlock();
1957 return DDERR_INVALIDCAPS
;
1960 if (!(target_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_3DDEVICE
))
1962 WARN("Surface %p is not a render target.\n", target_impl
);
1963 wined3d_mutex_unlock();
1964 return DDERR_INVALIDCAPS
;
1967 if (target_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_ZBUFFER
)
1969 WARN("Surface %p is a depth buffer.\n", target_impl
);
1970 IDirectDrawSurface4_AddRef(target
);
1971 IUnknown_Release(device
->rt_iface
);
1972 device
->rt_iface
= (IUnknown
*)target
;
1973 wined3d_mutex_unlock();
1974 return DDERR_INVALIDPIXELFORMAT
;
1977 if (!(target_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_VIDEOMEMORY
))
1979 WARN("Surface %p is not in video memory.\n", target_impl
);
1980 IDirectDrawSurface4_AddRef(target
);
1981 IUnknown_Release(device
->rt_iface
);
1982 device
->rt_iface
= (IUnknown
*)target
;
1983 wined3d_mutex_unlock();
1987 hr
= d3d_device_set_render_target(device
, target_impl
, (IUnknown
*)target
);
1988 wined3d_mutex_unlock();
1992 static HRESULT WINAPI
d3d_device2_SetRenderTarget(IDirect3DDevice2
*iface
,
1993 IDirectDrawSurface
*target
, DWORD flags
)
1995 struct ddraw_surface
*target_impl
= unsafe_impl_from_IDirectDrawSurface(target
);
1996 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
1999 TRACE("iface %p, target %p, flags %#x.\n", iface
, target
, flags
);
2001 wined3d_mutex_lock();
2003 if (!validate_surface_palette(target_impl
))
2005 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl
);
2006 wined3d_mutex_unlock();
2007 return DDERR_INVALIDCAPS
;
2010 if (!(target_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_3DDEVICE
))
2012 WARN("Surface %p is not a render target.\n", target_impl
);
2013 wined3d_mutex_unlock();
2014 return DDERR_INVALIDCAPS
;
2017 if (target_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_ZBUFFER
)
2019 WARN("Surface %p is a depth buffer.\n", target_impl
);
2020 IUnknown_Release(device
->rt_iface
);
2021 device
->rt_iface
= (IUnknown
*)target
;
2022 wined3d_mutex_unlock();
2023 return DDERR_INVALIDPIXELFORMAT
;
2026 if (!(target_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_VIDEOMEMORY
))
2028 WARN("Surface %p is not in video memory.\n", target_impl
);
2029 IDirectDrawSurface_AddRef(target
);
2030 IUnknown_Release(device
->rt_iface
);
2031 device
->rt_iface
= (IUnknown
*)target
;
2032 wined3d_mutex_unlock();
2036 hr
= d3d_device_set_render_target(device
, target_impl
, (IUnknown
*)target
);
2037 wined3d_mutex_unlock();
2041 /*****************************************************************************
2042 * IDirect3DDevice7::GetRenderTarget
2044 * Returns the current render target.
2045 * This is handled locally, because the WineD3D render target's parent
2048 * Version 2, 3 and 7
2051 * RenderTarget: Address to store the surface interface pointer
2055 * DDERR_INVALIDPARAMS if RenderTarget == NULL
2057 *****************************************************************************/
2058 static HRESULT WINAPI
d3d_device7_GetRenderTarget(IDirect3DDevice7
*iface
, IDirectDrawSurface7
**RenderTarget
)
2060 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
2063 TRACE("iface %p, target %p.\n", iface
, RenderTarget
);
2066 return DDERR_INVALIDPARAMS
;
2068 wined3d_mutex_lock();
2069 hr
= IUnknown_QueryInterface(device
->rt_iface
, &IID_IDirectDrawSurface7
, (void **)RenderTarget
);
2070 wined3d_mutex_unlock();
2075 static HRESULT WINAPI
d3d_device3_GetRenderTarget(IDirect3DDevice3
*iface
, IDirectDrawSurface4
**RenderTarget
)
2077 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
2078 IDirectDrawSurface7
*RenderTarget7
;
2079 struct ddraw_surface
*RenderTargetImpl
;
2082 TRACE("iface %p, target %p.\n", iface
, RenderTarget
);
2085 return DDERR_INVALIDPARAMS
;
2087 hr
= d3d_device7_GetRenderTarget(&device
->IDirect3DDevice7_iface
, &RenderTarget7
);
2088 if(hr
!= D3D_OK
) return hr
;
2089 RenderTargetImpl
= impl_from_IDirectDrawSurface7(RenderTarget7
);
2090 *RenderTarget
= &RenderTargetImpl
->IDirectDrawSurface4_iface
;
2091 IDirectDrawSurface4_AddRef(*RenderTarget
);
2092 IDirectDrawSurface7_Release(RenderTarget7
);
2096 static HRESULT WINAPI
d3d_device2_GetRenderTarget(IDirect3DDevice2
*iface
, IDirectDrawSurface
**RenderTarget
)
2098 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
2099 IDirectDrawSurface7
*RenderTarget7
;
2100 struct ddraw_surface
*RenderTargetImpl
;
2103 TRACE("iface %p, target %p.\n", iface
, RenderTarget
);
2106 return DDERR_INVALIDPARAMS
;
2108 hr
= d3d_device7_GetRenderTarget(&device
->IDirect3DDevice7_iface
, &RenderTarget7
);
2109 if(hr
!= D3D_OK
) return hr
;
2110 RenderTargetImpl
= impl_from_IDirectDrawSurface7(RenderTarget7
);
2111 *RenderTarget
= &RenderTargetImpl
->IDirectDrawSurface_iface
;
2112 IDirectDrawSurface_AddRef(*RenderTarget
);
2113 IDirectDrawSurface7_Release(RenderTarget7
);
2117 /*****************************************************************************
2118 * IDirect3DDevice3::Begin
2120 * Begins a description block of vertices. This is similar to glBegin()
2121 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2122 * described with IDirect3DDevice::Vertex are drawn.
2127 * PrimitiveType: The type of primitives to draw
2128 * VertexTypeDesc: A flexible vertex format description of the vertices
2129 * Flags: Some flags..
2134 *****************************************************************************/
2135 static HRESULT WINAPI
d3d_device3_Begin(IDirect3DDevice3
*iface
,
2136 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
, DWORD flags
)
2138 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
2140 TRACE("iface %p, primitive_type %#x, fvf %#x, flags %#x.\n",
2141 iface
, primitive_type
, fvf
, flags
);
2143 wined3d_mutex_lock();
2144 device
->primitive_type
= primitive_type
;
2145 device
->vertex_type
= fvf
;
2146 device
->render_flags
= flags
;
2147 device
->vertex_size
= get_flexible_vertex_size(device
->vertex_type
);
2148 device
->nb_vertices
= 0;
2149 wined3d_mutex_unlock();
2154 static HRESULT WINAPI
d3d_device2_Begin(IDirect3DDevice2
*iface
,
2155 D3DPRIMITIVETYPE primitive_type
, D3DVERTEXTYPE vertex_type
, DWORD flags
)
2157 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
2160 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2161 iface
, primitive_type
, vertex_type
, flags
);
2163 switch (vertex_type
)
2165 case D3DVT_VERTEX
: fvf
= D3DFVF_VERTEX
; break;
2166 case D3DVT_LVERTEX
: fvf
= D3DFVF_LVERTEX
; break;
2167 case D3DVT_TLVERTEX
: fvf
= D3DFVF_TLVERTEX
; break;
2169 ERR("Unexpected vertex type %#x.\n", vertex_type
);
2170 return DDERR_INVALIDPARAMS
; /* Should never happen */
2173 return d3d_device3_Begin(&device
->IDirect3DDevice3_iface
, primitive_type
, fvf
, flags
);
2176 /*****************************************************************************
2177 * IDirect3DDevice3::BeginIndexed
2179 * Draws primitives based on vertices in a vertex array which are specified
2185 * PrimitiveType: Primitive type to draw
2186 * VertexType: A FVF description of the vertex format
2187 * Vertices: pointer to an array containing the vertices
2188 * NumVertices: The number of vertices in the vertex array
2189 * Flags: Some flags ...
2192 * D3D_OK, because it's a stub
2194 *****************************************************************************/
2195 static HRESULT WINAPI
d3d_device3_BeginIndexed(IDirect3DDevice3
*iface
,
2196 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
,
2197 void *vertices
, DWORD vertex_count
, DWORD flags
)
2199 FIXME("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2200 iface
, primitive_type
, fvf
, vertices
, vertex_count
, flags
);
2206 static HRESULT WINAPI
d3d_device2_BeginIndexed(IDirect3DDevice2
*iface
,
2207 D3DPRIMITIVETYPE primitive_type
, D3DVERTEXTYPE vertex_type
,
2208 void *vertices
, DWORD vertex_count
, DWORD flags
)
2210 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
2213 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2214 iface
, primitive_type
, vertex_type
, vertices
, vertex_count
, flags
);
2216 switch (vertex_type
)
2218 case D3DVT_VERTEX
: fvf
= D3DFVF_VERTEX
; break;
2219 case D3DVT_LVERTEX
: fvf
= D3DFVF_LVERTEX
; break;
2220 case D3DVT_TLVERTEX
: fvf
= D3DFVF_TLVERTEX
; break;
2222 ERR("Unexpected vertex type %#x.\n", vertex_type
);
2223 return DDERR_INVALIDPARAMS
; /* Should never happen */
2226 return d3d_device3_BeginIndexed(&device
->IDirect3DDevice3_iface
,
2227 primitive_type
, fvf
, vertices
, vertex_count
, flags
);
2230 /*****************************************************************************
2231 * IDirect3DDevice3::Vertex
2233 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2234 * drawn vertices in a vertex buffer. If the buffer is too small, its
2235 * size is increased.
2240 * Vertex: Pointer to the vertex
2243 * D3D_OK, on success
2244 * DDERR_INVALIDPARAMS if Vertex is NULL
2246 *****************************************************************************/
2247 static HRESULT WINAPI
d3d_device3_Vertex(IDirect3DDevice3
*iface
, void *vertex
)
2249 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
2251 TRACE("iface %p, vertex %p.\n", iface
, vertex
);
2254 return DDERR_INVALIDPARAMS
;
2256 wined3d_mutex_lock();
2257 if ((device
->nb_vertices
+ 1) * device
->vertex_size
> device
->buffer_size
)
2261 device
->buffer_size
= device
->buffer_size
? device
->buffer_size
* 2 : device
->vertex_size
* 3;
2262 old_buffer
= device
->sysmem_vertex_buffer
;
2263 device
->sysmem_vertex_buffer
= heap_alloc(device
->buffer_size
);
2266 memcpy(device
->sysmem_vertex_buffer
, old_buffer
, device
->nb_vertices
* device
->vertex_size
);
2267 heap_free(old_buffer
);
2271 memcpy(device
->sysmem_vertex_buffer
+ device
->nb_vertices
++ * device
->vertex_size
, vertex
, device
->vertex_size
);
2272 wined3d_mutex_unlock();
2277 static HRESULT WINAPI
d3d_device2_Vertex(IDirect3DDevice2
*iface
, void *vertex
)
2279 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
2281 TRACE("iface %p, vertex %p.\n", iface
, vertex
);
2283 return d3d_device3_Vertex(&device
->IDirect3DDevice3_iface
, vertex
);
2286 /*****************************************************************************
2287 * IDirect3DDevice3::Index
2289 * Specifies an index to a vertex to be drawn. The vertex array has to
2290 * be specified with BeginIndexed first.
2293 * VertexIndex: The index of the vertex to draw
2296 * D3D_OK because it's a stub
2298 *****************************************************************************/
2299 static HRESULT WINAPI
d3d_device3_Index(IDirect3DDevice3
*iface
, WORD index
)
2301 FIXME("iface %p, index %#x stub!\n", iface
, index
);
2306 static HRESULT WINAPI
d3d_device2_Index(IDirect3DDevice2
*iface
, WORD index
)
2308 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
2310 TRACE("iface %p, index %#x.\n", iface
, index
);
2312 return d3d_device3_Index(&device
->IDirect3DDevice3_iface
, index
);
2315 /*****************************************************************************
2316 * IDirect3DDevice7::GetRenderState
2318 * Returns the value of a render state. The possible render states are
2319 * defined in include/d3dtypes.h
2321 * Version 2, 3 and 7
2324 * RenderStateType: Render state to return the current setting of
2325 * Value: Address to store the value at
2328 * D3D_OK on success,
2329 * DDERR_INVALIDPARAMS if Value == NULL
2331 *****************************************************************************/
2332 static HRESULT
d3d_device7_GetRenderState(IDirect3DDevice7
*iface
,
2333 D3DRENDERSTATETYPE state
, DWORD
*value
)
2335 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
2336 const struct wined3d_stateblock_state
*device_state
;
2337 HRESULT hr
= D3D_OK
;
2339 TRACE("iface %p, state %#x, value %p.\n", iface
, state
, value
);
2342 return DDERR_INVALIDPARAMS
;
2344 wined3d_mutex_lock();
2345 device_state
= device
->stateblock_state
;
2348 case D3DRENDERSTATE_TEXTUREMAG
:
2350 enum wined3d_texture_filter_type tex_mag
= device_state
->sampler_states
[0][WINED3D_SAMP_MAG_FILTER
];
2354 case WINED3D_TEXF_POINT
:
2355 *value
= D3DFILTER_NEAREST
;
2357 case WINED3D_TEXF_LINEAR
:
2358 *value
= D3DFILTER_LINEAR
;
2361 ERR("Unhandled texture mag %d !\n",tex_mag
);
2367 case D3DRENDERSTATE_TEXTUREMIN
:
2369 enum wined3d_texture_filter_type tex_min
;
2370 enum wined3d_texture_filter_type tex_mip
;
2372 tex_min
= device_state
->sampler_states
[0][WINED3D_SAMP_MIN_FILTER
];
2373 tex_mip
= device_state
->sampler_states
[0][WINED3D_SAMP_MIP_FILTER
];
2376 case WINED3D_TEXF_POINT
:
2379 case WINED3D_TEXF_NONE
:
2380 *value
= D3DFILTER_NEAREST
;
2382 case WINED3D_TEXF_POINT
:
2383 *value
= D3DFILTER_MIPNEAREST
;
2385 case WINED3D_TEXF_LINEAR
:
2386 *value
= D3DFILTER_LINEARMIPNEAREST
;
2389 ERR("Unhandled mip filter %#x.\n", tex_mip
);
2390 *value
= D3DFILTER_NEAREST
;
2394 case WINED3D_TEXF_LINEAR
:
2397 case WINED3D_TEXF_NONE
:
2398 *value
= D3DFILTER_LINEAR
;
2400 case WINED3D_TEXF_POINT
:
2401 *value
= D3DFILTER_MIPLINEAR
;
2403 case WINED3D_TEXF_LINEAR
:
2404 *value
= D3DFILTER_LINEARMIPLINEAR
;
2407 ERR("Unhandled mip filter %#x.\n", tex_mip
);
2408 *value
= D3DFILTER_LINEAR
;
2413 ERR("Unhandled texture min filter %#x.\n",tex_min
);
2414 *value
= D3DFILTER_NEAREST
;
2420 case D3DRENDERSTATE_TEXTUREADDRESS
:
2421 case D3DRENDERSTATE_TEXTUREADDRESSU
:
2422 *value
= device_state
->sampler_states
[0][WINED3D_SAMP_ADDRESS_U
];
2424 case D3DRENDERSTATE_TEXTUREADDRESSV
:
2425 *value
= device_state
->sampler_states
[0][WINED3D_SAMP_ADDRESS_V
];
2428 case D3DRENDERSTATE_BORDERCOLOR
:
2429 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2433 case D3DRENDERSTATE_TEXTUREHANDLE
:
2434 case D3DRENDERSTATE_TEXTUREMAPBLEND
:
2435 WARN("Render state %#x is invalid in d3d7.\n", state
);
2436 hr
= DDERR_INVALIDPARAMS
;
2440 if (state
>= D3DRENDERSTATE_STIPPLEPATTERN00
2441 && state
<= D3DRENDERSTATE_STIPPLEPATTERN31
)
2443 FIXME("Unhandled stipple pattern render state (%#x).\n", state
);
2447 *value
= device_state
->rs
[wined3d_render_state_from_ddraw(state
)];
2449 wined3d_mutex_unlock();
2454 static HRESULT WINAPI
d3d_device7_GetRenderState_FPUSetup(IDirect3DDevice7
*iface
,
2455 D3DRENDERSTATETYPE state
, DWORD
*value
)
2457 return d3d_device7_GetRenderState(iface
, state
, value
);
2460 static HRESULT WINAPI
d3d_device7_GetRenderState_FPUPreserve(IDirect3DDevice7
*iface
,
2461 D3DRENDERSTATETYPE state
, DWORD
*value
)
2466 old_fpucw
= d3d_fpu_setup();
2467 hr
= d3d_device7_GetRenderState(iface
, state
, value
);
2468 set_fpu_control_word(old_fpucw
);
2473 static HRESULT WINAPI
d3d_device3_GetRenderState(IDirect3DDevice3
*iface
,
2474 D3DRENDERSTATETYPE state
, DWORD
*value
)
2476 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
2478 TRACE("iface %p, state %#x, value %p.\n", iface
, state
, value
);
2482 case D3DRENDERSTATE_TEXTUREHANDLE
:
2484 /* This state is wrapped to SetTexture in SetRenderState, so
2485 * it has to be wrapped to GetTexture here. */
2486 struct wined3d_texture
*tex
= NULL
;
2489 wined3d_mutex_lock();
2490 if ((tex
= device
->stateblock_state
->textures
[0]))
2492 /* The parent of the texture is the IDirectDrawSurface7
2493 * interface of the ddraw surface. */
2494 struct ddraw_texture
*parent
= wined3d_texture_get_parent(tex
);
2496 *value
= parent
->root
->Handle
;
2498 wined3d_mutex_unlock();
2503 case D3DRENDERSTATE_TEXTUREMAPBLEND
:
2505 *value
= device
->texture_map_blend
;
2509 case D3DRENDERSTATE_LIGHTING
:
2510 case D3DRENDERSTATE_NORMALIZENORMALS
:
2511 case D3DRENDERSTATE_LOCALVIEWER
:
2512 *value
= 0xffffffff;
2516 return IDirect3DDevice7_GetRenderState(&device
->IDirect3DDevice7_iface
, state
, value
);
2520 static HRESULT WINAPI
d3d_device2_GetRenderState(IDirect3DDevice2
*iface
,
2521 D3DRENDERSTATETYPE state
, DWORD
*value
)
2523 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
2525 TRACE("iface %p, state %#x, value %p.\n", iface
, state
, value
);
2527 return IDirect3DDevice3_GetRenderState(&device
->IDirect3DDevice3_iface
, state
, value
);
2530 /*****************************************************************************
2531 * IDirect3DDevice7::SetRenderState
2533 * Sets a render state. The possible render states are defined in
2534 * include/d3dtypes.h
2536 * Version 2, 3 and 7
2539 * RenderStateType: State to set
2540 * Value: Value to assign to that state
2542 *****************************************************************************/
2543 static HRESULT
d3d_device7_SetRenderState(IDirect3DDevice7
*iface
,
2544 D3DRENDERSTATETYPE state
, DWORD value
)
2546 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
2547 HRESULT hr
= D3D_OK
;
2549 TRACE("iface %p, state %#x, value %#x.\n", iface
, state
, value
);
2551 wined3d_mutex_lock();
2552 /* Some render states need special care */
2556 * The ddraw texture filter mapping works like this:
2557 * D3DFILTER_NEAREST Point min/mag, no mip
2558 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2559 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2561 * D3DFILTER_LINEAR Linear min/mag, no mip
2562 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2563 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2565 * This is the opposite of the GL naming convention,
2566 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2568 case D3DRENDERSTATE_TEXTUREMAG
:
2570 enum wined3d_texture_filter_type tex_mag
;
2574 case D3DFILTER_NEAREST
:
2575 case D3DFILTER_MIPNEAREST
:
2576 case D3DFILTER_LINEARMIPNEAREST
:
2577 tex_mag
= WINED3D_TEXF_POINT
;
2579 case D3DFILTER_LINEAR
:
2580 case D3DFILTER_MIPLINEAR
:
2581 case D3DFILTER_LINEARMIPLINEAR
:
2582 tex_mag
= WINED3D_TEXF_LINEAR
;
2585 tex_mag
= WINED3D_TEXF_POINT
;
2586 FIXME("Unhandled texture mag %#x.\n", value
);
2590 wined3d_stateblock_set_sampler_state(device
->state
, 0, WINED3D_SAMP_MAG_FILTER
, tex_mag
);
2594 case D3DRENDERSTATE_TEXTUREMIN
:
2596 enum wined3d_texture_filter_type tex_min
;
2597 enum wined3d_texture_filter_type tex_mip
;
2601 case D3DFILTER_NEAREST
:
2602 tex_min
= WINED3D_TEXF_POINT
;
2603 tex_mip
= WINED3D_TEXF_NONE
;
2605 case D3DFILTER_LINEAR
:
2606 tex_min
= WINED3D_TEXF_LINEAR
;
2607 tex_mip
= WINED3D_TEXF_NONE
;
2609 case D3DFILTER_MIPNEAREST
:
2610 tex_min
= WINED3D_TEXF_POINT
;
2611 tex_mip
= WINED3D_TEXF_POINT
;
2613 case D3DFILTER_MIPLINEAR
:
2614 tex_min
= WINED3D_TEXF_LINEAR
;
2615 tex_mip
= WINED3D_TEXF_POINT
;
2617 case D3DFILTER_LINEARMIPNEAREST
:
2618 tex_min
= WINED3D_TEXF_POINT
;
2619 tex_mip
= WINED3D_TEXF_LINEAR
;
2621 case D3DFILTER_LINEARMIPLINEAR
:
2622 tex_min
= WINED3D_TEXF_LINEAR
;
2623 tex_mip
= WINED3D_TEXF_LINEAR
;
2627 FIXME("Unhandled texture min %#x.\n",value
);
2628 tex_min
= WINED3D_TEXF_POINT
;
2629 tex_mip
= WINED3D_TEXF_NONE
;
2633 wined3d_stateblock_set_sampler_state(device
->state
, 0, WINED3D_SAMP_MIP_FILTER
, tex_mip
);
2634 wined3d_stateblock_set_sampler_state(device
->state
, 0, WINED3D_SAMP_MIN_FILTER
, tex_min
);
2638 case D3DRENDERSTATE_TEXTUREADDRESS
:
2639 wined3d_stateblock_set_sampler_state(device
->state
, 0, WINED3D_SAMP_ADDRESS_V
, value
);
2641 case D3DRENDERSTATE_TEXTUREADDRESSU
:
2642 wined3d_stateblock_set_sampler_state(device
->state
, 0, WINED3D_SAMP_ADDRESS_U
, value
);
2644 case D3DRENDERSTATE_TEXTUREADDRESSV
:
2645 wined3d_stateblock_set_sampler_state(device
->state
, 0, WINED3D_SAMP_ADDRESS_V
, value
);
2648 case D3DRENDERSTATE_BORDERCOLOR
:
2649 /* This should probably just forward to the corresponding sampler
2650 * state. Needs tests. */
2651 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2655 case D3DRENDERSTATE_TEXTUREHANDLE
:
2656 case D3DRENDERSTATE_TEXTUREMAPBLEND
:
2657 WARN("Render state %#x is invalid in d3d7.\n", state
);
2658 hr
= DDERR_INVALIDPARAMS
;
2662 if (state
>= D3DRENDERSTATE_STIPPLEPATTERN00
2663 && state
<= D3DRENDERSTATE_STIPPLEPATTERN31
)
2665 FIXME("Unhandled stipple pattern render state (%#x).\n", state
);
2670 wined3d_stateblock_set_render_state(device
->update_state
, wined3d_render_state_from_ddraw(state
), value
);
2673 wined3d_mutex_unlock();
2678 static HRESULT WINAPI
d3d_device7_SetRenderState_FPUSetup(IDirect3DDevice7
*iface
,
2679 D3DRENDERSTATETYPE state
, DWORD value
)
2681 return d3d_device7_SetRenderState(iface
, state
, value
);
2684 static HRESULT WINAPI
d3d_device7_SetRenderState_FPUPreserve(IDirect3DDevice7
*iface
,
2685 D3DRENDERSTATETYPE state
, DWORD value
)
2690 old_fpucw
= d3d_fpu_setup();
2691 hr
= d3d_device7_SetRenderState(iface
, state
, value
);
2692 set_fpu_control_word(old_fpucw
);
2697 static void fixup_texture_alpha_op(struct d3d_device
*device
)
2699 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
2700 See d3d_device3_SetRenderState() for details. */
2701 struct wined3d_texture
*tex
;
2702 BOOL tex_alpha
= TRUE
;
2703 DDPIXELFORMAT ddfmt
;
2705 if (!(device
->legacyTextureBlending
&& device
->texture_map_blend
== D3DTBLEND_MODULATE
))
2708 if ((tex
= device
->stateblock_state
->textures
[0]))
2710 struct wined3d_resource_desc desc
;
2712 wined3d_resource_get_desc(wined3d_texture_get_resource(tex
), &desc
);
2713 ddfmt
.dwSize
= sizeof(ddfmt
);
2714 ddrawformat_from_wined3dformat(&ddfmt
, desc
.format
);
2715 if (!ddfmt
.u5
.dwRGBAlphaBitMask
)
2719 /* Args 1 and 2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
2720 wined3d_stateblock_set_texture_stage_state(device
->state
,
2721 0, WINED3D_TSS_ALPHA_OP
, tex_alpha
? WINED3D_TOP_SELECT_ARG1
: WINED3D_TOP_SELECT_ARG2
);
2724 static HRESULT WINAPI
d3d_device3_SetRenderState(IDirect3DDevice3
*iface
,
2725 D3DRENDERSTATETYPE state
, DWORD value
)
2727 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2728 for this state can be directly mapped to texture stage colorop and alphaop, but
2729 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2730 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2731 alphaarg when needed.
2733 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2735 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2736 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2737 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2738 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2739 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2740 in device - TRUE if the app is using TEXTUREMAPBLEND.
2742 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2743 GetTextureStageState and vice versa. */
2745 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
2748 TRACE("iface %p, state %#x, value %#x.\n", iface
, state
, value
);
2750 if (state
>= D3DSTATE_OVERRIDE_BIAS
)
2752 WARN("Unhandled state %#x.\n", state
);
2753 return DDERR_INVALIDPARAMS
;
2756 wined3d_mutex_lock();
2760 case D3DRENDERSTATE_TEXTUREHANDLE
:
2762 struct ddraw_surface
*surf
;
2766 wined3d_stateblock_set_texture(device
->state
, 0, NULL
);
2771 surf
= ddraw_get_object(&device
->handle_table
, value
- 1, DDRAW_HANDLE_SURFACE
);
2774 WARN("Invalid texture handle.\n");
2775 hr
= DDERR_INVALIDPARAMS
;
2779 hr
= IDirect3DDevice3_SetTexture(iface
, 0, &surf
->IDirect3DTexture2_iface
);
2783 case D3DRENDERSTATE_TEXTUREMAPBLEND
:
2785 if (value
== device
->texture_map_blend
)
2787 TRACE("Application is setting the same value over, nothing to do.\n");
2793 device
->legacyTextureBlending
= TRUE
;
2794 device
->texture_map_blend
= value
;
2798 case D3DTBLEND_MODULATE
:
2800 fixup_texture_alpha_op(device
);
2802 wined3d_stateblock_set_texture_stage_state(device
->state
,
2803 0, WINED3D_TSS_ALPHA_ARG1
, WINED3DTA_TEXTURE
);
2804 wined3d_stateblock_set_texture_stage_state(device
->state
,
2805 0, WINED3D_TSS_ALPHA_ARG2
, WINED3DTA_CURRENT
);
2806 wined3d_stateblock_set_texture_stage_state(device
->state
,
2807 0, WINED3D_TSS_COLOR_ARG1
, WINED3DTA_TEXTURE
);
2808 wined3d_stateblock_set_texture_stage_state(device
->state
,
2809 0, WINED3D_TSS_COLOR_ARG2
, WINED3DTA_CURRENT
);
2810 wined3d_stateblock_set_texture_stage_state(device
->state
,
2811 0, WINED3D_TSS_COLOR_OP
, WINED3D_TOP_MODULATE
);
2816 wined3d_stateblock_set_texture_stage_state(device
->state
,
2817 0, WINED3D_TSS_COLOR_OP
, WINED3D_TOP_ADD
);
2818 wined3d_stateblock_set_texture_stage_state(device
->state
,
2819 0, WINED3D_TSS_COLOR_ARG1
, WINED3DTA_TEXTURE
);
2820 wined3d_stateblock_set_texture_stage_state(device
->state
,
2821 0, WINED3D_TSS_COLOR_ARG2
, WINED3DTA_CURRENT
);
2822 wined3d_stateblock_set_texture_stage_state(device
->state
,
2823 0, WINED3D_TSS_ALPHA_OP
, WINED3D_TOP_SELECT_ARG2
);
2824 wined3d_stateblock_set_texture_stage_state(device
->state
,
2825 0, WINED3D_TSS_ALPHA_ARG2
, WINED3DTA_CURRENT
);
2828 case D3DTBLEND_MODULATEALPHA
:
2829 wined3d_stateblock_set_texture_stage_state(device
->state
,
2830 0, WINED3D_TSS_COLOR_ARG1
, WINED3DTA_TEXTURE
);
2831 wined3d_stateblock_set_texture_stage_state(device
->state
,
2832 0, WINED3D_TSS_ALPHA_ARG1
, WINED3DTA_TEXTURE
);
2833 wined3d_stateblock_set_texture_stage_state(device
->state
,
2834 0, WINED3D_TSS_COLOR_ARG2
, WINED3DTA_CURRENT
);
2835 wined3d_stateblock_set_texture_stage_state(device
->state
,
2836 0, WINED3D_TSS_ALPHA_ARG2
, WINED3DTA_CURRENT
);
2837 wined3d_stateblock_set_texture_stage_state(device
->state
,
2838 0, WINED3D_TSS_COLOR_OP
, WINED3D_TOP_MODULATE
);
2839 wined3d_stateblock_set_texture_stage_state(device
->state
,
2840 0, WINED3D_TSS_ALPHA_OP
, WINED3D_TOP_MODULATE
);
2843 case D3DTBLEND_COPY
:
2844 case D3DTBLEND_DECAL
:
2845 wined3d_stateblock_set_texture_stage_state(device
->state
,
2846 0, WINED3D_TSS_COLOR_ARG1
, WINED3DTA_TEXTURE
);
2847 wined3d_stateblock_set_texture_stage_state(device
->state
,
2848 0, WINED3D_TSS_ALPHA_ARG1
, WINED3DTA_TEXTURE
);
2849 wined3d_stateblock_set_texture_stage_state(device
->state
,
2850 0, WINED3D_TSS_COLOR_OP
, WINED3D_TOP_SELECT_ARG1
);
2851 wined3d_stateblock_set_texture_stage_state(device
->state
,
2852 0, WINED3D_TSS_ALPHA_OP
, WINED3D_TOP_SELECT_ARG1
);
2855 case D3DTBLEND_DECALALPHA
:
2856 wined3d_stateblock_set_texture_stage_state(device
->state
,
2857 0, WINED3D_TSS_COLOR_OP
, WINED3D_TOP_BLEND_TEXTURE_ALPHA
);
2858 wined3d_stateblock_set_texture_stage_state(device
->state
,
2859 0, WINED3D_TSS_COLOR_ARG1
, WINED3DTA_TEXTURE
);
2860 wined3d_stateblock_set_texture_stage_state(device
->state
,
2861 0, WINED3D_TSS_COLOR_ARG2
, WINED3DTA_CURRENT
);
2862 wined3d_stateblock_set_texture_stage_state(device
->state
,
2863 0, WINED3D_TSS_ALPHA_OP
, WINED3D_TOP_SELECT_ARG2
);
2864 wined3d_stateblock_set_texture_stage_state(device
->state
,
2865 0, WINED3D_TSS_ALPHA_ARG2
, WINED3DTA_CURRENT
);
2869 FIXME("Unhandled texture environment %#x.\n", value
);
2875 case D3DRENDERSTATE_LIGHTING
:
2876 case D3DRENDERSTATE_NORMALIZENORMALS
:
2877 case D3DRENDERSTATE_LOCALVIEWER
:
2882 hr
= IDirect3DDevice7_SetRenderState(&device
->IDirect3DDevice7_iface
, state
, value
);
2885 wined3d_mutex_unlock();
2890 static HRESULT WINAPI
d3d_device2_SetRenderState(IDirect3DDevice2
*iface
,
2891 D3DRENDERSTATETYPE state
, DWORD value
)
2893 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
2895 TRACE("iface %p, state %#x, value %#x.\n", iface
, state
, value
);
2897 return IDirect3DDevice3_SetRenderState(&device
->IDirect3DDevice3_iface
, state
, value
);
2900 /*****************************************************************************
2901 * Direct3DDevice3::SetLightState
2903 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2904 * light states are forwarded to Direct3DDevice7 render states
2909 * LightStateType: The light state to change
2910 * Value: The value to assign to that light state
2914 * DDERR_INVALIDPARAMS if the parameters were incorrect
2915 * Also check IDirect3DDevice7::SetRenderState
2917 *****************************************************************************/
2918 static HRESULT WINAPI
d3d_device3_SetLightState(IDirect3DDevice3
*iface
,
2919 D3DLIGHTSTATETYPE state
, DWORD value
)
2921 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
2924 TRACE("iface %p, state %#x, value %#x.\n", iface
, state
, value
);
2926 if (!state
|| (state
> D3DLIGHTSTATE_COLORVERTEX
))
2928 TRACE("Unexpected Light State Type\n");
2929 return DDERR_INVALIDPARAMS
;
2932 wined3d_mutex_lock();
2933 if (state
== D3DLIGHTSTATE_MATERIAL
)
2937 struct d3d_material
*m
;
2939 if (!(m
= ddraw_get_object(&device
->handle_table
, value
- 1, DDRAW_HANDLE_MATERIAL
)))
2941 WARN("Invalid material handle.\n");
2942 wined3d_mutex_unlock();
2943 return DDERR_INVALIDPARAMS
;
2946 material_activate(m
);
2949 device
->material
= value
;
2951 else if (state
== D3DLIGHTSTATE_COLORMODEL
)
2956 ERR("DDCOLOR_MONO should not happen!\n");
2959 /* We are already in this mode */
2960 TRACE("Setting color model to RGB (no-op).\n");
2963 ERR("Unknown color model!\n");
2964 wined3d_mutex_unlock();
2965 return DDERR_INVALIDPARAMS
;
2970 D3DRENDERSTATETYPE rs
;
2973 case D3DLIGHTSTATE_AMBIENT
: /* 2 */
2974 rs
= D3DRENDERSTATE_AMBIENT
;
2976 case D3DLIGHTSTATE_FOGMODE
: /* 4 */
2977 rs
= D3DRENDERSTATE_FOGVERTEXMODE
;
2979 case D3DLIGHTSTATE_FOGSTART
: /* 5 */
2980 rs
= D3DRENDERSTATE_FOGSTART
;
2982 case D3DLIGHTSTATE_FOGEND
: /* 6 */
2983 rs
= D3DRENDERSTATE_FOGEND
;
2985 case D3DLIGHTSTATE_FOGDENSITY
: /* 7 */
2986 rs
= D3DRENDERSTATE_FOGDENSITY
;
2988 case D3DLIGHTSTATE_COLORVERTEX
: /* 8 */
2989 rs
= D3DRENDERSTATE_COLORVERTEX
;
2992 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state
);
2993 wined3d_mutex_unlock();
2994 return DDERR_INVALIDPARAMS
;
2997 hr
= IDirect3DDevice7_SetRenderState(&device
->IDirect3DDevice7_iface
, rs
, value
);
2998 wined3d_mutex_unlock();
3001 wined3d_mutex_unlock();
3006 static HRESULT WINAPI
d3d_device2_SetLightState(IDirect3DDevice2
*iface
,
3007 D3DLIGHTSTATETYPE state
, DWORD value
)
3009 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
3011 TRACE("iface %p, state %#x, value %#x.\n", iface
, state
, value
);
3013 return d3d_device3_SetLightState(&device
->IDirect3DDevice3_iface
, state
, value
);
3016 /*****************************************************************************
3017 * IDirect3DDevice3::GetLightState
3019 * Returns the current setting of a light state. The state is read from
3020 * the Direct3DDevice7 render state.
3025 * LightStateType: The light state to return
3026 * Value: The address to store the light state setting at
3030 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3031 * Also see IDirect3DDevice7::GetRenderState
3033 *****************************************************************************/
3034 static HRESULT WINAPI
d3d_device3_GetLightState(IDirect3DDevice3
*iface
,
3035 D3DLIGHTSTATETYPE state
, DWORD
*value
)
3037 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
3040 TRACE("iface %p, state %#x, value %p.\n", iface
, state
, value
);
3042 if (!state
|| (state
> D3DLIGHTSTATE_COLORVERTEX
))
3044 TRACE("Unexpected Light State Type\n");
3045 return DDERR_INVALIDPARAMS
;
3049 return DDERR_INVALIDPARAMS
;
3051 wined3d_mutex_lock();
3052 if (state
== D3DLIGHTSTATE_MATERIAL
)
3054 *value
= device
->material
;
3056 else if (state
== D3DLIGHTSTATE_COLORMODEL
)
3058 *value
= D3DCOLOR_RGB
;
3062 D3DRENDERSTATETYPE rs
;
3065 case D3DLIGHTSTATE_AMBIENT
: /* 2 */
3066 rs
= D3DRENDERSTATE_AMBIENT
;
3068 case D3DLIGHTSTATE_FOGMODE
: /* 4 */
3069 rs
= D3DRENDERSTATE_FOGVERTEXMODE
;
3071 case D3DLIGHTSTATE_FOGSTART
: /* 5 */
3072 rs
= D3DRENDERSTATE_FOGSTART
;
3074 case D3DLIGHTSTATE_FOGEND
: /* 6 */
3075 rs
= D3DRENDERSTATE_FOGEND
;
3077 case D3DLIGHTSTATE_FOGDENSITY
: /* 7 */
3078 rs
= D3DRENDERSTATE_FOGDENSITY
;
3080 case D3DLIGHTSTATE_COLORVERTEX
: /* 8 */
3081 rs
= D3DRENDERSTATE_COLORVERTEX
;
3084 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state
);
3085 wined3d_mutex_unlock();
3086 return DDERR_INVALIDPARAMS
;
3089 hr
= IDirect3DDevice7_GetRenderState(&device
->IDirect3DDevice7_iface
, rs
, value
);
3090 wined3d_mutex_unlock();
3093 wined3d_mutex_unlock();
3098 static HRESULT WINAPI
d3d_device2_GetLightState(IDirect3DDevice2
*iface
,
3099 D3DLIGHTSTATETYPE state
, DWORD
*value
)
3101 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
3103 TRACE("iface %p, state %#x, value %p.\n", iface
, state
, value
);
3105 return d3d_device3_GetLightState(&device
->IDirect3DDevice3_iface
, state
, value
);
3108 /*****************************************************************************
3109 * IDirect3DDevice7::SetTransform
3111 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3112 * in include/d3dtypes.h.
3113 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3114 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3115 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3117 * Version 2, 3 and 7
3120 * TransformStateType: transform state to set
3121 * Matrix: Matrix to assign to the state
3125 * DDERR_INVALIDPARAMS if Matrix == NULL
3127 *****************************************************************************/
3128 static HRESULT
d3d_device7_SetTransform(IDirect3DDevice7
*iface
,
3129 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3131 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
3133 TRACE("iface %p, state %#x, matrix %p.\n", iface
, state
, matrix
);
3136 return DDERR_INVALIDPARAMS
;
3138 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3139 wined3d_mutex_lock();
3140 wined3d_stateblock_set_transform(device
->update_state
,
3141 wined3d_transform_state_from_ddraw(state
), (const struct wined3d_matrix
*)matrix
);
3142 wined3d_mutex_unlock();
3147 static HRESULT WINAPI
d3d_device7_SetTransform_FPUSetup(IDirect3DDevice7
*iface
,
3148 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3150 return d3d_device7_SetTransform(iface
, state
, matrix
);
3153 static HRESULT WINAPI
d3d_device7_SetTransform_FPUPreserve(IDirect3DDevice7
*iface
,
3154 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3159 old_fpucw
= d3d_fpu_setup();
3160 hr
= d3d_device7_SetTransform(iface
, state
, matrix
);
3161 set_fpu_control_word(old_fpucw
);
3166 static HRESULT WINAPI
d3d_device3_SetTransform(IDirect3DDevice3
*iface
,
3167 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3169 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
3171 TRACE("iface %p, state %#x, matrix %p.\n", iface
, state
, matrix
);
3174 return DDERR_INVALIDPARAMS
;
3176 if (state
== D3DTRANSFORMSTATE_PROJECTION
)
3178 struct wined3d_matrix projection
;
3180 wined3d_mutex_lock();
3181 multiply_matrix(&projection
, &device
->legacy_clipspace
, (struct wined3d_matrix
*)matrix
);
3182 wined3d_stateblock_set_transform(device
->state
,
3183 WINED3D_TS_PROJECTION
, (struct wined3d_matrix
*)&projection
);
3184 memcpy(&device
->legacy_projection
, matrix
, sizeof(*matrix
));
3185 wined3d_mutex_unlock();
3190 return IDirect3DDevice7_SetTransform(&device
->IDirect3DDevice7_iface
, state
, matrix
);
3193 static HRESULT WINAPI
d3d_device2_SetTransform(IDirect3DDevice2
*iface
,
3194 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3196 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
3198 TRACE("iface %p, state %#x, matrix %p.\n", iface
, state
, matrix
);
3200 return IDirect3DDevice3_SetTransform(&device
->IDirect3DDevice3_iface
, state
, matrix
);
3203 /*****************************************************************************
3204 * IDirect3DDevice7::GetTransform
3206 * Returns the matrix assigned to a transform state
3207 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3211 * TransformStateType: State to read the matrix from
3212 * Matrix: Address to store the matrix at
3216 * DDERR_INVALIDPARAMS if Matrix == NULL
3218 *****************************************************************************/
3219 static HRESULT
d3d_device7_GetTransform(IDirect3DDevice7
*iface
,
3220 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3222 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
3224 TRACE("iface %p, state %#x, matrix %p.\n", iface
, state
, matrix
);
3227 return DDERR_INVALIDPARAMS
;
3229 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3230 wined3d_mutex_lock();
3231 memcpy(matrix
, &device
->stateblock_state
->transforms
[wined3d_transform_state_from_ddraw(state
)], sizeof(*matrix
));
3232 wined3d_mutex_unlock();
3237 static HRESULT WINAPI
d3d_device7_GetTransform_FPUSetup(IDirect3DDevice7
*iface
,
3238 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3240 return d3d_device7_GetTransform(iface
, state
, matrix
);
3243 static HRESULT WINAPI
d3d_device7_GetTransform_FPUPreserve(IDirect3DDevice7
*iface
,
3244 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3249 old_fpucw
= d3d_fpu_setup();
3250 hr
= d3d_device7_GetTransform(iface
, state
, matrix
);
3251 set_fpu_control_word(old_fpucw
);
3256 static HRESULT WINAPI
d3d_device3_GetTransform(IDirect3DDevice3
*iface
,
3257 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3259 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
3261 TRACE("iface %p, state %#x, matrix %p.\n", iface
, state
, matrix
);
3264 return DDERR_INVALIDPARAMS
;
3266 if (state
== D3DTRANSFORMSTATE_PROJECTION
)
3268 wined3d_mutex_lock();
3269 memcpy(matrix
, &device
->legacy_projection
, sizeof(*matrix
));
3270 wined3d_mutex_unlock();
3274 return IDirect3DDevice7_GetTransform(&device
->IDirect3DDevice7_iface
, state
, matrix
);
3277 static HRESULT WINAPI
d3d_device2_GetTransform(IDirect3DDevice2
*iface
,
3278 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3280 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
3282 TRACE("iface %p, state %#x, matrix %p.\n", iface
, state
, matrix
);
3284 return IDirect3DDevice3_GetTransform(&device
->IDirect3DDevice3_iface
, state
, matrix
);
3287 /*****************************************************************************
3288 * IDirect3DDevice7::MultiplyTransform
3290 * Multiplies the already-set transform matrix of a transform state
3291 * with another matrix. For the world matrix, see SetTransform
3293 * Version 2, 3 and 7
3296 * TransformStateType: Transform state to multiply
3297 * D3DMatrix Matrix to multiply with.
3301 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3303 *****************************************************************************/
3304 static HRESULT
d3d_device7_MultiplyTransform(IDirect3DDevice7
*iface
,
3305 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3307 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
3309 TRACE("iface %p, state %#x, matrix %p.\n", iface
, state
, matrix
);
3311 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3312 wined3d_mutex_lock();
3313 wined3d_stateblock_multiply_transform(device
->state
,
3314 wined3d_transform_state_from_ddraw(state
), (struct wined3d_matrix
*)matrix
);
3315 wined3d_mutex_unlock();
3320 static HRESULT WINAPI
d3d_device7_MultiplyTransform_FPUSetup(IDirect3DDevice7
*iface
,
3321 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3323 return d3d_device7_MultiplyTransform(iface
, state
, matrix
);
3326 static HRESULT WINAPI
d3d_device7_MultiplyTransform_FPUPreserve(IDirect3DDevice7
*iface
,
3327 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3332 old_fpucw
= d3d_fpu_setup();
3333 hr
= d3d_device7_MultiplyTransform(iface
, state
, matrix
);
3334 set_fpu_control_word(old_fpucw
);
3339 static HRESULT WINAPI
d3d_device3_MultiplyTransform(IDirect3DDevice3
*iface
,
3340 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3342 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
3344 TRACE("iface %p, state %#x, matrix %p.\n", iface
, state
, matrix
);
3346 if (state
== D3DTRANSFORMSTATE_PROJECTION
)
3348 struct wined3d_matrix projection
, tmp
;
3350 wined3d_mutex_lock();
3351 multiply_matrix(&tmp
, &device
->legacy_projection
, (struct wined3d_matrix
*)matrix
);
3352 multiply_matrix(&projection
, &device
->legacy_clipspace
, &tmp
);
3353 wined3d_stateblock_set_transform(device
->state
, WINED3D_TS_PROJECTION
, &projection
);
3354 device
->legacy_projection
= tmp
;
3355 wined3d_mutex_unlock();
3360 return IDirect3DDevice7_MultiplyTransform(&device
->IDirect3DDevice7_iface
, state
, matrix
);
3363 static HRESULT WINAPI
d3d_device2_MultiplyTransform(IDirect3DDevice2
*iface
,
3364 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3366 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
3368 TRACE("iface %p, state %#x, matrix %p.\n", iface
, state
, matrix
);
3370 return IDirect3DDevice3_MultiplyTransform(&device
->IDirect3DDevice3_iface
, state
, matrix
);
3373 /*****************************************************************************
3374 * IDirect3DDevice7::DrawPrimitive
3376 * Draws primitives based on vertices in an application-provided pointer
3378 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3379 * an FVF format for D3D7
3382 * PrimitiveType: The type of the primitives to draw
3383 * Vertex type: Flexible vertex format vertex description
3384 * Vertices: Pointer to the vertex array
3385 * VertexCount: The number of vertices to draw
3386 * Flags: As usual a few flags
3390 * DDERR_INVALIDPARAMS if Vertices is NULL
3392 *****************************************************************************/
3394 /* The caller is responsible for wined3d locking */
3395 static HRESULT
d3d_device_prepare_vertex_buffer(struct d3d_device
*device
, UINT min_size
)
3399 if (device
->vertex_buffer_size
< min_size
|| !device
->vertex_buffer
)
3401 UINT size
= max(device
->vertex_buffer_size
* 2, min_size
);
3402 struct wined3d_buffer_desc desc
;
3403 struct wined3d_buffer
*buffer
;
3405 TRACE("Growing vertex buffer to %u bytes\n", size
);
3407 desc
.byte_width
= size
;
3408 desc
.usage
= WINED3DUSAGE_DYNAMIC
;
3409 desc
.bind_flags
= WINED3D_BIND_VERTEX_BUFFER
;
3410 desc
.access
= WINED3D_RESOURCE_ACCESS_GPU
| WINED3D_RESOURCE_ACCESS_MAP_W
;
3411 desc
.misc_flags
= 0;
3412 desc
.structure_byte_stride
= 0;
3414 if (FAILED(hr
= wined3d_buffer_create(device
->wined3d_device
, &desc
,
3415 NULL
, NULL
, &ddraw_null_wined3d_parent_ops
, &buffer
)))
3417 ERR("Failed to create vertex buffer, hr %#x.\n", hr
);
3421 if (device
->vertex_buffer
)
3422 wined3d_buffer_decref(device
->vertex_buffer
);
3424 device
->vertex_buffer
= buffer
;
3425 device
->vertex_buffer_size
= size
;
3426 device
->vertex_buffer_pos
= 0;
3431 static HRESULT
d3d_device7_DrawPrimitive(IDirect3DDevice7
*iface
,
3432 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
, void *vertices
,
3433 DWORD vertex_count
, DWORD flags
)
3435 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
3436 struct wined3d_map_desc wined3d_map_desc
;
3437 struct wined3d_box wined3d_box
= {0};
3438 UINT stride
, vb_pos
, size
, align
;
3439 struct wined3d_resource
*vb
;
3442 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3443 iface
, primitive_type
, fvf
, vertices
, vertex_count
, flags
);
3447 WARN("0 vertex count.\n");
3451 /* Get the stride */
3452 stride
= get_flexible_vertex_size(fvf
);
3453 size
= vertex_count
* stride
;
3455 wined3d_mutex_lock();
3456 hr
= d3d_device_prepare_vertex_buffer(device
, size
);
3460 vb_pos
= device
->vertex_buffer_pos
;
3461 align
= vb_pos
% stride
;
3462 if (align
) align
= stride
- align
;
3463 if (vb_pos
+ size
+ align
> device
->vertex_buffer_size
)
3468 wined3d_box
.left
= vb_pos
;
3469 wined3d_box
.right
= vb_pos
+ size
;
3470 vb
= wined3d_buffer_get_resource(device
->vertex_buffer
);
3471 if (FAILED(hr
= wined3d_resource_map(vb
, 0, &wined3d_map_desc
, &wined3d_box
,
3472 WINED3D_MAP_WRITE
| (vb_pos
? WINED3D_MAP_NOOVERWRITE
: WINED3D_MAP_DISCARD
))))
3474 memcpy(wined3d_map_desc
.data
, vertices
, size
);
3475 wined3d_resource_unmap(vb
, 0);
3476 device
->vertex_buffer_pos
= vb_pos
+ size
;
3478 hr
= wined3d_stateblock_set_stream_source(device
->state
, 0, device
->vertex_buffer
, 0, stride
);
3482 wined3d_stateblock_set_vertex_declaration(device
->state
, ddraw_find_decl(device
->ddraw
, fvf
));
3483 wined3d_device_set_primitive_type(device
->wined3d_device
, wined3d_primitive_type_from_ddraw(primitive_type
), 0);
3484 wined3d_device_apply_stateblock(device
->wined3d_device
, device
->state
);
3485 hr
= wined3d_device_draw_primitive(device
->wined3d_device
, vb_pos
/ stride
, vertex_count
);
3488 wined3d_mutex_unlock();
3492 static HRESULT WINAPI
d3d_device7_DrawPrimitive_FPUSetup(IDirect3DDevice7
*iface
,
3493 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
, void *vertices
,
3494 DWORD vertex_count
, DWORD flags
)
3496 return d3d_device7_DrawPrimitive(iface
, primitive_type
, fvf
, vertices
, vertex_count
, flags
);
3499 static HRESULT WINAPI
d3d_device7_DrawPrimitive_FPUPreserve(IDirect3DDevice7
*iface
,
3500 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
, void *vertices
,
3501 DWORD vertex_count
, DWORD flags
)
3506 old_fpucw
= d3d_fpu_setup();
3507 hr
= d3d_device7_DrawPrimitive(iface
, primitive_type
, fvf
, vertices
, vertex_count
, flags
);
3508 set_fpu_control_word(old_fpucw
);
3513 static void setup_lighting(const struct d3d_device
*device
, DWORD fvf
, DWORD flags
)
3517 /* Ignore the D3DFVF_XYZRHW case here, wined3d takes care of that */
3518 if (!device
->material
|| !(fvf
& D3DFVF_NORMAL
) || (flags
& D3DDP_DONOTLIGHT
))
3521 wined3d_stateblock_set_render_state(device
->state
, WINED3D_RS_LIGHTING
, enable
);
3525 static HRESULT WINAPI
d3d_device3_DrawPrimitive(IDirect3DDevice3
*iface
,
3526 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
, void *vertices
, DWORD vertex_count
,
3529 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
3531 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3532 iface
, primitive_type
, fvf
, vertices
, vertex_count
, flags
);
3534 setup_lighting(device
, fvf
, flags
);
3536 return IDirect3DDevice7_DrawPrimitive(&device
->IDirect3DDevice7_iface
,
3537 primitive_type
, fvf
, vertices
, vertex_count
, flags
);
3540 static HRESULT WINAPI
d3d_device2_DrawPrimitive(IDirect3DDevice2
*iface
,
3541 D3DPRIMITIVETYPE primitive_type
, D3DVERTEXTYPE vertex_type
, void *vertices
,
3542 DWORD vertex_count
, DWORD flags
)
3544 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
3547 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3548 iface
, primitive_type
, vertex_type
, vertices
, vertex_count
, flags
);
3550 switch (vertex_type
)
3552 case D3DVT_VERTEX
: fvf
= D3DFVF_VERTEX
; break;
3553 case D3DVT_LVERTEX
: fvf
= D3DFVF_LVERTEX
; break;
3554 case D3DVT_TLVERTEX
: fvf
= D3DFVF_TLVERTEX
; break;
3556 FIXME("Unhandled vertex type %#x.\n", vertex_type
);
3557 return DDERR_INVALIDPARAMS
; /* Should never happen */
3560 return d3d_device3_DrawPrimitive(&device
->IDirect3DDevice3_iface
,
3561 primitive_type
, fvf
, vertices
, vertex_count
, flags
);
3564 /*****************************************************************************
3565 * IDirect3DDevice7::DrawIndexedPrimitive
3567 * Draws vertices from an application-provided pointer, based on the index
3568 * numbers in a WORD array.
3570 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3571 * an FVF format for D3D7
3574 * PrimitiveType: The primitive type to draw
3575 * VertexType: The FVF vertex description
3576 * Vertices: Pointer to the vertex array
3578 * Indices: Pointer to the index array
3579 * IndexCount: Number of indices = Number of vertices to draw
3580 * Flags: As usual, some flags
3584 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3586 *****************************************************************************/
3587 /* The caller is responsible for wined3d locking */
3588 static HRESULT
d3d_device_prepare_index_buffer(struct d3d_device
*device
, UINT min_size
)
3592 if (device
->index_buffer_size
< min_size
|| !device
->index_buffer
)
3594 UINT size
= max(device
->index_buffer_size
* 2, min_size
);
3595 struct wined3d_buffer_desc desc
;
3596 struct wined3d_buffer
*buffer
;
3598 TRACE("Growing index buffer to %u bytes\n", size
);
3600 desc
.byte_width
= size
;
3601 desc
.usage
= WINED3DUSAGE_DYNAMIC
| WINED3DUSAGE_STATICDECL
;
3602 desc
.bind_flags
= WINED3D_BIND_INDEX_BUFFER
;
3603 desc
.access
= WINED3D_RESOURCE_ACCESS_GPU
| WINED3D_RESOURCE_ACCESS_MAP_W
;
3604 desc
.misc_flags
= 0;
3605 desc
.structure_byte_stride
= 0;
3607 if (FAILED(hr
= wined3d_buffer_create(device
->wined3d_device
, &desc
,
3608 NULL
, NULL
, &ddraw_null_wined3d_parent_ops
, &buffer
)))
3610 ERR("Failed to create index buffer, hr %#x.\n", hr
);
3614 if (device
->index_buffer
)
3615 wined3d_buffer_decref(device
->index_buffer
);
3616 device
->index_buffer
= buffer
;
3617 device
->index_buffer_size
= size
;
3618 device
->index_buffer_pos
= 0;
3623 static HRESULT
d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7
*iface
,
3624 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
, void *vertices
, DWORD vertex_count
,
3625 WORD
*indices
, DWORD index_count
, DWORD flags
)
3627 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
3629 UINT stride
= get_flexible_vertex_size(fvf
);
3630 UINT vtx_size
= stride
* vertex_count
, idx_size
= index_count
* sizeof(*indices
);
3631 struct wined3d_map_desc wined3d_map_desc
;
3632 struct wined3d_box wined3d_box
= {0};
3633 struct wined3d_resource
*ib
, *vb
;
3634 UINT vb_pos
, ib_pos
, align
;
3636 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3637 "indices %p, index_count %u, flags %#x.\n",
3638 iface
, primitive_type
, fvf
, vertices
, vertex_count
, indices
, index_count
, flags
);
3640 if (!vertex_count
|| !index_count
)
3642 WARN("0 vertex or index count.\n");
3646 /* Set the D3DDevice's FVF */
3647 wined3d_mutex_lock();
3649 hr
= d3d_device_prepare_vertex_buffer(device
, vtx_size
);
3653 vb_pos
= device
->vertex_buffer_pos
;
3654 align
= vb_pos
% stride
;
3655 if (align
) align
= stride
- align
;
3656 if (vb_pos
+ vtx_size
+ align
> device
->vertex_buffer_size
)
3661 wined3d_box
.left
= vb_pos
;
3662 wined3d_box
.right
= vb_pos
+ vtx_size
;
3663 vb
= wined3d_buffer_get_resource(device
->vertex_buffer
);
3664 if (FAILED(hr
= wined3d_resource_map(vb
, 0, &wined3d_map_desc
, &wined3d_box
,
3665 WINED3D_MAP_WRITE
| (vb_pos
? WINED3D_MAP_NOOVERWRITE
: WINED3D_MAP_DISCARD
))))
3667 memcpy(wined3d_map_desc
.data
, vertices
, vtx_size
);
3668 wined3d_resource_unmap(vb
, 0);
3669 device
->vertex_buffer_pos
= vb_pos
+ vtx_size
;
3671 hr
= d3d_device_prepare_index_buffer(device
, idx_size
);
3674 ib_pos
= device
->index_buffer_pos
;
3675 if (device
->index_buffer_size
- idx_size
< ib_pos
)
3678 wined3d_box
.left
= ib_pos
;
3679 wined3d_box
.right
= ib_pos
+ idx_size
;
3680 ib
= wined3d_buffer_get_resource(device
->index_buffer
);
3681 if (FAILED(hr
= wined3d_resource_map(ib
, 0, &wined3d_map_desc
, &wined3d_box
,
3682 WINED3D_MAP_WRITE
| (ib_pos
? WINED3D_MAP_NOOVERWRITE
: WINED3D_MAP_DISCARD
))))
3684 memcpy(wined3d_map_desc
.data
, indices
, idx_size
);
3685 wined3d_resource_unmap(ib
, 0);
3686 device
->index_buffer_pos
= ib_pos
+ idx_size
;
3688 hr
= wined3d_stateblock_set_stream_source(device
->state
, 0, device
->vertex_buffer
, 0, stride
);
3691 wined3d_stateblock_set_index_buffer(device
->state
, device
->index_buffer
, WINED3DFMT_R16_UINT
);
3693 wined3d_stateblock_set_vertex_declaration(device
->state
, ddraw_find_decl(device
->ddraw
, fvf
));
3694 wined3d_device_set_primitive_type(device
->wined3d_device
, wined3d_primitive_type_from_ddraw(primitive_type
), 0);
3695 wined3d_stateblock_set_base_vertex_index(device
->state
, vb_pos
/ stride
);
3696 wined3d_device_apply_stateblock(device
->wined3d_device
, device
->state
);
3697 hr
= wined3d_device_draw_indexed_primitive(device
->wined3d_device
, ib_pos
/ sizeof(*indices
), index_count
);
3700 wined3d_mutex_unlock();
3704 static HRESULT WINAPI
d3d_device7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7
*iface
,
3705 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
, void *vertices
, DWORD vertex_count
,
3706 WORD
*indices
, DWORD index_count
, DWORD flags
)
3708 return d3d_device7_DrawIndexedPrimitive(iface
, primitive_type
, fvf
,
3709 vertices
, vertex_count
, indices
, index_count
, flags
);
3712 static HRESULT WINAPI
d3d_device7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7
*iface
,
3713 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
, void *vertices
, DWORD vertex_count
,
3714 WORD
*indices
, DWORD index_count
, DWORD flags
)
3719 old_fpucw
= d3d_fpu_setup();
3720 hr
= d3d_device7_DrawIndexedPrimitive(iface
, primitive_type
, fvf
,
3721 vertices
, vertex_count
, indices
, index_count
, flags
);
3722 set_fpu_control_word(old_fpucw
);
3727 static HRESULT WINAPI
d3d_device3_DrawIndexedPrimitive(IDirect3DDevice3
*iface
,
3728 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
, void *vertices
, DWORD vertex_count
,
3729 WORD
*indices
, DWORD index_count
, DWORD flags
)
3731 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
3733 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3734 "indices %p, index_count %u, flags %#x.\n",
3735 iface
, primitive_type
, fvf
, vertices
, vertex_count
, indices
, index_count
, flags
);
3737 setup_lighting(device
, fvf
, flags
);
3739 return IDirect3DDevice7_DrawIndexedPrimitive(&device
->IDirect3DDevice7_iface
,
3740 primitive_type
, fvf
, vertices
, vertex_count
, indices
, index_count
, flags
);
3743 static HRESULT WINAPI
d3d_device2_DrawIndexedPrimitive(IDirect3DDevice2
*iface
,
3744 D3DPRIMITIVETYPE primitive_type
, D3DVERTEXTYPE vertex_type
, void *vertices
,
3745 DWORD vertex_count
, WORD
*indices
, DWORD index_count
, DWORD flags
)
3747 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
3750 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, "
3751 "indices %p, index_count %u, flags %#x.\n",
3752 iface
, primitive_type
, vertex_type
, vertices
, vertex_count
, indices
, index_count
, flags
);
3754 switch (vertex_type
)
3756 case D3DVT_VERTEX
: fvf
= D3DFVF_VERTEX
; break;
3757 case D3DVT_LVERTEX
: fvf
= D3DFVF_LVERTEX
; break;
3758 case D3DVT_TLVERTEX
: fvf
= D3DFVF_TLVERTEX
; break;
3760 ERR("Unhandled vertex type %#x.\n", vertex_type
);
3761 return DDERR_INVALIDPARAMS
; /* Should never happen */
3764 return d3d_device3_DrawIndexedPrimitive(&device
->IDirect3DDevice3_iface
,
3765 primitive_type
, fvf
, vertices
, vertex_count
, indices
, index_count
, flags
);
3768 /*****************************************************************************
3769 * IDirect3DDevice3::End
3771 * Ends a draw begun with IDirect3DDevice3::Begin or
3772 * IDirect3DDevice::BeginIndexed. The vertices specified with
3773 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
3774 * the IDirect3DDevice3::DrawPrimitive method. So far only
3775 * non-indexed mode is supported
3780 * Flags: Some flags, as usual. Don't know which are defined
3783 * The return value of IDirect3DDevice3::DrawPrimitive
3785 *****************************************************************************/
3786 static HRESULT WINAPI
d3d_device3_End(IDirect3DDevice3
*iface
, DWORD flags
)
3788 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
3790 TRACE("iface %p, flags %#x.\n", iface
, flags
);
3792 return d3d_device3_DrawPrimitive(&device
->IDirect3DDevice3_iface
, device
->primitive_type
,
3793 device
->vertex_type
, device
->sysmem_vertex_buffer
, device
->nb_vertices
, device
->render_flags
);
3796 static HRESULT WINAPI
d3d_device2_End(IDirect3DDevice2
*iface
, DWORD flags
)
3798 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
3800 TRACE("iface %p, flags %#x.\n", iface
, flags
);
3802 return d3d_device3_End(&device
->IDirect3DDevice3_iface
, flags
);
3805 /*****************************************************************************
3806 * IDirect3DDevice7::SetClipStatus
3808 * Sets the clip status. This defines things as clipping conditions and
3809 * the extents of the clipping region.
3811 * Version 2, 3 and 7
3817 * D3D_OK because it's a stub
3818 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3820 *****************************************************************************/
3821 static HRESULT WINAPI
d3d_device7_SetClipStatus(IDirect3DDevice7
*iface
, D3DCLIPSTATUS
*clip_status
)
3823 FIXME("iface %p, clip_status %p stub!\n", iface
, clip_status
);
3828 static HRESULT WINAPI
d3d_device3_SetClipStatus(IDirect3DDevice3
*iface
, D3DCLIPSTATUS
*clip_status
)
3830 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
3832 TRACE("iface %p, clip_status %p.\n", iface
, clip_status
);
3834 return IDirect3DDevice7_SetClipStatus(&device
->IDirect3DDevice7_iface
, clip_status
);
3837 static HRESULT WINAPI
d3d_device2_SetClipStatus(IDirect3DDevice2
*iface
, D3DCLIPSTATUS
*clip_status
)
3839 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
3841 TRACE("iface %p, clip_status %p.\n", iface
, clip_status
);
3843 return IDirect3DDevice7_SetClipStatus(&device
->IDirect3DDevice7_iface
, clip_status
);
3846 /*****************************************************************************
3847 * IDirect3DDevice7::GetClipStatus
3849 * Returns the clip status
3852 * ClipStatus: Address to write the clip status to
3855 * D3D_OK because it's a stub
3857 *****************************************************************************/
3858 static HRESULT WINAPI
d3d_device7_GetClipStatus(IDirect3DDevice7
*iface
, D3DCLIPSTATUS
*clip_status
)
3860 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
3861 struct wined3d_viewport vp
;
3863 FIXME("iface %p, clip_status %p stub.\n", iface
, clip_status
);
3865 vp
= device
->stateblock_state
->viewport
;
3866 clip_status
->minx
= vp
.x
;
3867 clip_status
->maxx
= vp
.x
+ vp
.width
;
3868 clip_status
->miny
= vp
.y
;
3869 clip_status
->maxy
= vp
.y
+ vp
.height
;
3870 clip_status
->minz
= 0.0f
;
3871 clip_status
->maxz
= 0.0f
;
3872 clip_status
->dwFlags
= D3DCLIPSTATUS_EXTENTS2
;
3873 clip_status
->dwStatus
= 0;
3878 static HRESULT WINAPI
d3d_device3_GetClipStatus(IDirect3DDevice3
*iface
, D3DCLIPSTATUS
*clip_status
)
3880 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
3882 TRACE("iface %p, clip_status %p.\n", iface
, clip_status
);
3884 return IDirect3DDevice7_GetClipStatus(&device
->IDirect3DDevice7_iface
, clip_status
);
3887 static HRESULT WINAPI
d3d_device2_GetClipStatus(IDirect3DDevice2
*iface
, D3DCLIPSTATUS
*clip_status
)
3889 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
3891 TRACE("iface %p, clip_status %p.\n", iface
, clip_status
);
3893 return IDirect3DDevice7_GetClipStatus(&device
->IDirect3DDevice7_iface
, clip_status
);
3896 /*****************************************************************************
3897 * IDirect3DDevice::DrawPrimitiveStrided
3899 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3904 * PrimitiveType: The primitive type to draw
3905 * VertexType: The FVF description of the vertices to draw (for the stride??)
3906 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3907 * the vertex data locations
3908 * VertexCount: The number of vertices to draw
3912 * D3D_OK, because it's a stub
3913 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3915 *****************************************************************************/
3916 static void pack_strided_data(BYTE
*dst
, DWORD count
, const D3DDRAWPRIMITIVESTRIDEDDATA
*src
, DWORD fvf
)
3918 DWORD i
, tex
, offset
;
3920 for (i
= 0; i
< count
; i
++)
3922 /* The contents of the strided data are determined by the fvf,
3923 * not by the members set in src. So it's valid
3924 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3925 * not set in the fvf. */
3926 if (fvf
& D3DFVF_POSITION_MASK
)
3928 offset
= i
* src
->position
.dwStride
;
3929 if (fvf
& D3DFVF_XYZRHW
)
3931 memcpy(dst
, ((BYTE
*)src
->position
.lpvData
) + offset
, 4 * sizeof(float));
3932 dst
+= 4 * sizeof(float);
3936 memcpy(dst
, ((BYTE
*)src
->position
.lpvData
) + offset
, 3 * sizeof(float));
3937 dst
+= 3 * sizeof(float);
3941 if (fvf
& D3DFVF_NORMAL
)
3943 offset
= i
* src
->normal
.dwStride
;
3944 memcpy(dst
, ((BYTE
*)src
->normal
.lpvData
) + offset
, 3 * sizeof(float));
3945 dst
+= 3 * sizeof(float);
3948 if (fvf
& D3DFVF_DIFFUSE
)
3950 offset
= i
* src
->diffuse
.dwStride
;
3951 memcpy(dst
, ((BYTE
*)src
->diffuse
.lpvData
) + offset
, sizeof(DWORD
));
3952 dst
+= sizeof(DWORD
);
3955 if (fvf
& D3DFVF_SPECULAR
)
3957 offset
= i
* src
->specular
.dwStride
;
3958 memcpy(dst
, ((BYTE
*)src
->specular
.lpvData
) + offset
, sizeof(DWORD
));
3959 dst
+= sizeof(DWORD
);
3962 for (tex
= 0; tex
< GET_TEXCOUNT_FROM_FVF(fvf
); ++tex
)
3964 DWORD attrib_count
= GET_TEXCOORD_SIZE_FROM_FVF(fvf
, tex
);
3965 offset
= i
* src
->textureCoords
[tex
].dwStride
;
3966 memcpy(dst
, ((BYTE
*)src
->textureCoords
[tex
].lpvData
) + offset
, attrib_count
* sizeof(float));
3967 dst
+= attrib_count
* sizeof(float);
3972 static HRESULT
d3d_device7_DrawPrimitiveStrided(IDirect3DDevice7
*iface
, D3DPRIMITIVETYPE primitive_type
,
3973 DWORD fvf
, D3DDRAWPRIMITIVESTRIDEDDATA
*strided_data
, DWORD vertex_count
, DWORD flags
)
3975 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
3977 UINT dst_stride
= get_flexible_vertex_size(fvf
);
3978 UINT dst_size
= dst_stride
* vertex_count
;
3979 struct wined3d_map_desc wined3d_map_desc
;
3980 struct wined3d_box wined3d_box
= {0};
3981 struct wined3d_resource
*vb
;
3984 TRACE("iface %p, primitive_type %#x, fvf %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3985 iface
, primitive_type
, fvf
, strided_data
, vertex_count
, flags
);
3989 WARN("0 vertex count.\n");
3993 wined3d_mutex_lock();
3994 hr
= d3d_device_prepare_vertex_buffer(device
, dst_size
);
3998 vb_pos
= device
->vertex_buffer_pos
;
3999 align
= vb_pos
% dst_stride
;
4000 if (align
) align
= dst_stride
- align
;
4001 if (vb_pos
+ dst_size
+ align
> device
->vertex_buffer_size
)
4006 wined3d_box
.left
= vb_pos
;
4007 wined3d_box
.right
= vb_pos
+ dst_size
;
4008 vb
= wined3d_buffer_get_resource(device
->vertex_buffer
);
4009 if (FAILED(hr
= wined3d_resource_map(vb
, 0, &wined3d_map_desc
, &wined3d_box
,
4010 WINED3D_MAP_WRITE
| (vb_pos
? WINED3D_MAP_NOOVERWRITE
: WINED3D_MAP_DISCARD
))))
4012 pack_strided_data(wined3d_map_desc
.data
, vertex_count
, strided_data
, fvf
);
4013 wined3d_resource_unmap(vb
, 0);
4014 device
->vertex_buffer_pos
= vb_pos
+ dst_size
;
4016 hr
= wined3d_stateblock_set_stream_source(device
->state
, 0, device
->vertex_buffer
, 0, dst_stride
);
4019 wined3d_stateblock_set_vertex_declaration(device
->state
, ddraw_find_decl(device
->ddraw
, fvf
));
4021 wined3d_device_set_primitive_type(device
->wined3d_device
, wined3d_primitive_type_from_ddraw(primitive_type
), 0);
4022 wined3d_device_apply_stateblock(device
->wined3d_device
, device
->state
);
4023 hr
= wined3d_device_draw_primitive(device
->wined3d_device
, vb_pos
/ dst_stride
, vertex_count
);
4026 wined3d_mutex_unlock();
4030 static HRESULT WINAPI
d3d_device7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7
*iface
,
4031 D3DPRIMITIVETYPE PrimitiveType
, DWORD VertexType
,
4032 D3DDRAWPRIMITIVESTRIDEDDATA
*D3DDrawPrimStrideData
, DWORD VertexCount
, DWORD Flags
)
4034 return d3d_device7_DrawPrimitiveStrided(iface
, PrimitiveType
,
4035 VertexType
, D3DDrawPrimStrideData
, VertexCount
, Flags
);
4038 static HRESULT WINAPI
d3d_device7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7
*iface
,
4039 D3DPRIMITIVETYPE PrimitiveType
, DWORD VertexType
,
4040 D3DDRAWPRIMITIVESTRIDEDDATA
*D3DDrawPrimStrideData
, DWORD VertexCount
, DWORD Flags
)
4045 old_fpucw
= d3d_fpu_setup();
4046 hr
= d3d_device7_DrawPrimitiveStrided(iface
, PrimitiveType
,
4047 VertexType
, D3DDrawPrimStrideData
, VertexCount
, Flags
);
4048 set_fpu_control_word(old_fpucw
);
4053 static HRESULT WINAPI
d3d_device3_DrawPrimitiveStrided(IDirect3DDevice3
*iface
,
4054 D3DPRIMITIVETYPE PrimitiveType
, DWORD VertexType
,
4055 D3DDRAWPRIMITIVESTRIDEDDATA
*D3DDrawPrimStrideData
, DWORD VertexCount
, DWORD Flags
)
4057 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
4059 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
4060 iface
, PrimitiveType
, VertexType
, D3DDrawPrimStrideData
, VertexCount
, Flags
);
4062 setup_lighting(device
, VertexType
, Flags
);
4064 return IDirect3DDevice7_DrawPrimitiveStrided(&device
->IDirect3DDevice7_iface
,
4065 PrimitiveType
, VertexType
, D3DDrawPrimStrideData
, VertexCount
, Flags
);
4068 /*****************************************************************************
4069 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
4071 * Draws primitives specified by strided data locations based on indices
4079 * D3D_OK, because it's a stub
4080 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
4081 * (DDERR_INVALIDPARAMS if Indices is NULL)
4083 *****************************************************************************/
4084 static HRESULT
d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7
*iface
,
4085 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
, D3DDRAWPRIMITIVESTRIDEDDATA
*strided_data
,
4086 DWORD vertex_count
, WORD
*indices
, DWORD index_count
, DWORD flags
)
4088 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
4089 UINT vtx_dst_stride
= get_flexible_vertex_size(fvf
);
4090 UINT vtx_dst_size
= vertex_count
* vtx_dst_stride
;
4091 UINT idx_size
= index_count
* sizeof(WORD
);
4092 struct wined3d_map_desc wined3d_map_desc
;
4093 struct wined3d_box wined3d_box
= {0};
4094 struct wined3d_resource
*ib
, *vb
;
4099 TRACE("iface %p, primitive_type %#x, fvf %#x, strided_data %p, "
4100 "vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4101 iface
, primitive_type
, fvf
, strided_data
, vertex_count
, indices
, index_count
, flags
);
4103 if (!vertex_count
|| !index_count
)
4105 WARN("0 vertex or index count.\n");
4109 wined3d_mutex_lock();
4111 hr
= d3d_device_prepare_vertex_buffer(device
, vtx_dst_size
);
4115 vb_pos
= device
->vertex_buffer_pos
;
4116 align
= vb_pos
% vtx_dst_stride
;
4117 if (align
) align
= vtx_dst_stride
- align
;
4118 if (vb_pos
+ vtx_dst_size
+ align
> device
->vertex_buffer_size
)
4123 wined3d_box
.left
= vb_pos
;
4124 wined3d_box
.right
= vb_pos
+ vtx_dst_size
;
4125 vb
= wined3d_buffer_get_resource(device
->vertex_buffer
);
4126 if (FAILED(hr
= wined3d_resource_map(vb
, 0, &wined3d_map_desc
, &wined3d_box
,
4127 WINED3D_MAP_WRITE
| (vb_pos
? WINED3D_MAP_NOOVERWRITE
: WINED3D_MAP_DISCARD
))))
4129 pack_strided_data(wined3d_map_desc
.data
, vertex_count
, strided_data
, fvf
);
4130 wined3d_resource_unmap(vb
, 0);
4131 device
->vertex_buffer_pos
= vb_pos
+ vtx_dst_size
;
4133 hr
= d3d_device_prepare_index_buffer(device
, idx_size
);
4136 ib_pos
= device
->index_buffer_pos
;
4137 if (device
->index_buffer_size
- idx_size
< ib_pos
)
4140 wined3d_box
.left
= ib_pos
;
4141 wined3d_box
.right
= ib_pos
+ idx_size
;
4142 ib
= wined3d_buffer_get_resource(device
->index_buffer
);
4143 if (FAILED(hr
= wined3d_resource_map(ib
, 0, &wined3d_map_desc
, &wined3d_box
,
4144 WINED3D_MAP_WRITE
| (ib_pos
? WINED3D_MAP_NOOVERWRITE
: WINED3D_MAP_DISCARD
))))
4146 memcpy(wined3d_map_desc
.data
, indices
, idx_size
);
4147 wined3d_resource_unmap(ib
, 0);
4148 device
->index_buffer_pos
= ib_pos
+ idx_size
;
4150 hr
= wined3d_stateblock_set_stream_source(device
->state
, 0, device
->vertex_buffer
, 0, vtx_dst_stride
);
4153 wined3d_stateblock_set_index_buffer(device
->state
, device
->index_buffer
, WINED3DFMT_R16_UINT
);
4154 wined3d_stateblock_set_base_vertex_index(device
->state
, vb_pos
/ vtx_dst_stride
);
4156 wined3d_stateblock_set_vertex_declaration(device
->state
, ddraw_find_decl(device
->ddraw
, fvf
));
4157 wined3d_device_set_primitive_type(device
->wined3d_device
, wined3d_primitive_type_from_ddraw(primitive_type
), 0);
4158 wined3d_device_apply_stateblock(device
->wined3d_device
, device
->state
);
4159 hr
= wined3d_device_draw_indexed_primitive(device
->wined3d_device
, ib_pos
/ sizeof(WORD
), index_count
);
4162 wined3d_mutex_unlock();
4166 static HRESULT WINAPI
d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7
*iface
,
4167 D3DPRIMITIVETYPE PrimitiveType
, DWORD VertexType
,
4168 D3DDRAWPRIMITIVESTRIDEDDATA
*D3DDrawPrimStrideData
, DWORD VertexCount
,
4169 WORD
*Indices
, DWORD IndexCount
, DWORD Flags
)
4171 return d3d_device7_DrawIndexedPrimitiveStrided(iface
, PrimitiveType
, VertexType
,
4172 D3DDrawPrimStrideData
, VertexCount
, Indices
, IndexCount
, Flags
);
4175 static HRESULT WINAPI
d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7
*iface
,
4176 D3DPRIMITIVETYPE PrimitiveType
, DWORD VertexType
,
4177 D3DDRAWPRIMITIVESTRIDEDDATA
*D3DDrawPrimStrideData
, DWORD VertexCount
,
4178 WORD
*Indices
, DWORD IndexCount
, DWORD Flags
)
4183 old_fpucw
= d3d_fpu_setup();
4184 hr
= d3d_device7_DrawIndexedPrimitiveStrided(iface
, PrimitiveType
, VertexType
,
4185 D3DDrawPrimStrideData
, VertexCount
, Indices
, IndexCount
, Flags
);
4186 set_fpu_control_word(old_fpucw
);
4191 static HRESULT WINAPI
d3d_device3_DrawIndexedPrimitiveStrided(IDirect3DDevice3
*iface
,
4192 D3DPRIMITIVETYPE PrimitiveType
, DWORD VertexType
,
4193 D3DDRAWPRIMITIVESTRIDEDDATA
*D3DDrawPrimStrideData
, DWORD VertexCount
, WORD
*Indices
,
4194 DWORD IndexCount
, DWORD Flags
)
4196 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
4198 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4199 iface
, PrimitiveType
, VertexType
, D3DDrawPrimStrideData
, VertexCount
, Indices
, IndexCount
, Flags
);
4201 setup_lighting(device
, VertexType
, Flags
);
4203 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&device
->IDirect3DDevice7_iface
,
4204 PrimitiveType
, VertexType
, D3DDrawPrimStrideData
, VertexCount
, Indices
, IndexCount
, Flags
);
4207 /*****************************************************************************
4208 * IDirect3DDevice7::DrawPrimitiveVB
4210 * Draws primitives from a vertex buffer to the screen.
4215 * PrimitiveType: Type of primitive to be rendered.
4216 * D3DVertexBuf: Source Vertex Buffer
4217 * StartVertex: Index of the first vertex from the buffer to be rendered
4218 * NumVertices: Number of vertices to be rendered
4219 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4223 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4225 *****************************************************************************/
4226 static HRESULT
d3d_device7_DrawPrimitiveVB(IDirect3DDevice7
*iface
, D3DPRIMITIVETYPE primitive_type
,
4227 IDirect3DVertexBuffer7
*vb
, DWORD start_vertex
, DWORD vertex_count
, DWORD flags
)
4229 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
4230 struct d3d_vertex_buffer
*vb_impl
= unsafe_impl_from_IDirect3DVertexBuffer7(vb
);
4231 struct wined3d_resource
*wined3d_resource
;
4232 struct wined3d_map_desc wined3d_map_desc
;
4233 struct wined3d_box wined3d_box
= {0};
4237 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4238 iface
, primitive_type
, vb
, start_vertex
, vertex_count
, flags
);
4242 WARN("0 vertex count.\n");
4246 stride
= get_flexible_vertex_size(vb_impl
->fvf
);
4248 if (vb_impl
->Caps
& D3DVBCAPS_SYSTEMMEMORY
)
4250 TRACE("Drawing from D3DVBCAPS_SYSTEMMEMORY vertex buffer, forwarding to DrawPrimitive().\n");
4251 wined3d_mutex_lock();
4252 wined3d_resource
= wined3d_buffer_get_resource(vb_impl
->wined3d_buffer
);
4253 wined3d_box
.left
= start_vertex
* stride
;
4254 wined3d_box
.right
= wined3d_box
.left
+ vertex_count
* stride
;
4255 if (FAILED(hr
= wined3d_resource_map(wined3d_resource
, 0, &wined3d_map_desc
,
4256 &wined3d_box
, WINED3D_MAP_READ
)))
4258 wined3d_mutex_unlock();
4259 return D3DERR_VERTEXBUFFERLOCKED
;
4261 hr
= d3d_device7_DrawPrimitive(iface
, primitive_type
, vb_impl
->fvf
, wined3d_map_desc
.data
,
4262 vertex_count
, flags
);
4263 wined3d_resource_unmap(wined3d_resource
, 0);
4264 wined3d_mutex_unlock();
4268 wined3d_mutex_lock();
4269 wined3d_stateblock_set_vertex_declaration(device
->state
, vb_impl
->wined3d_declaration
);
4270 if (FAILED(hr
= wined3d_stateblock_set_stream_source(device
->state
,
4271 0, vb_impl
->wined3d_buffer
, 0, stride
)))
4273 WARN("Failed to set stream source, hr %#x.\n", hr
);
4274 wined3d_mutex_unlock();
4278 /* Now draw the primitives */
4279 wined3d_device_set_primitive_type(device
->wined3d_device
, wined3d_primitive_type_from_ddraw(primitive_type
), 0);
4280 wined3d_device_apply_stateblock(device
->wined3d_device
, device
->state
);
4281 hr
= wined3d_device_draw_primitive(device
->wined3d_device
, start_vertex
, vertex_count
);
4283 wined3d_mutex_unlock();
4288 static HRESULT WINAPI
d3d_device7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7
*iface
, D3DPRIMITIVETYPE PrimitiveType
,
4289 IDirect3DVertexBuffer7
*D3DVertexBuf
, DWORD StartVertex
, DWORD NumVertices
, DWORD Flags
)
4291 return d3d_device7_DrawPrimitiveVB(iface
, PrimitiveType
, D3DVertexBuf
, StartVertex
, NumVertices
, Flags
);
4294 static HRESULT WINAPI
d3d_device7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7
*iface
, D3DPRIMITIVETYPE PrimitiveType
,
4295 IDirect3DVertexBuffer7
*D3DVertexBuf
, DWORD StartVertex
, DWORD NumVertices
, DWORD Flags
)
4300 old_fpucw
= d3d_fpu_setup();
4301 hr
= d3d_device7_DrawPrimitiveVB(iface
, PrimitiveType
, D3DVertexBuf
, StartVertex
, NumVertices
, Flags
);
4302 set_fpu_control_word(old_fpucw
);
4307 static HRESULT WINAPI
d3d_device3_DrawPrimitiveVB(IDirect3DDevice3
*iface
, D3DPRIMITIVETYPE PrimitiveType
,
4308 IDirect3DVertexBuffer
*D3DVertexBuf
, DWORD StartVertex
, DWORD NumVertices
, DWORD Flags
)
4310 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
4311 struct d3d_vertex_buffer
*vb
= unsafe_impl_from_IDirect3DVertexBuffer7((IDirect3DVertexBuffer7
*)D3DVertexBuf
);
4313 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4314 iface
, PrimitiveType
, D3DVertexBuf
, StartVertex
, NumVertices
, Flags
);
4316 setup_lighting(device
, vb
->fvf
, Flags
);
4318 return IDirect3DDevice7_DrawPrimitiveVB(&device
->IDirect3DDevice7_iface
,
4319 PrimitiveType
, &vb
->IDirect3DVertexBuffer7_iface
, StartVertex
, NumVertices
, Flags
);
4322 /*****************************************************************************
4323 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4325 * Draws primitives from a vertex buffer to the screen
4328 * PrimitiveType: Type of primitive to be rendered.
4329 * D3DVertexBuf: Source Vertex Buffer
4330 * StartVertex: Index of the first vertex from the buffer to be rendered
4331 * NumVertices: Number of vertices to be rendered
4332 * Indices: Array of DWORDs used to index into the Vertices
4333 * IndexCount: Number of indices in Indices
4334 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4338 *****************************************************************************/
4339 static HRESULT
d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7
*iface
,
4340 D3DPRIMITIVETYPE primitive_type
, IDirect3DVertexBuffer7
*vb
,
4341 DWORD start_vertex
, DWORD vertex_count
, WORD
*indices
, DWORD index_count
, DWORD flags
)
4343 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
4344 struct d3d_vertex_buffer
*vb_impl
= unsafe_impl_from_IDirect3DVertexBuffer7(vb
);
4345 DWORD stride
= get_flexible_vertex_size(vb_impl
->fvf
);
4346 struct wined3d_resource
*wined3d_resource
;
4347 struct wined3d_map_desc wined3d_map_desc
;
4348 struct wined3d_box wined3d_box
= {0};
4349 struct wined3d_resource
*ib
;
4353 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, "
4354 "vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4355 iface
, primitive_type
, vb
, start_vertex
, vertex_count
, indices
, index_count
, flags
);
4357 if (!vertex_count
|| !index_count
)
4359 WARN("0 vertex or index count.\n");
4363 if (vb_impl
->Caps
& D3DVBCAPS_SYSTEMMEMORY
)
4365 TRACE("Drawing from D3DVBCAPS_SYSTEMMEMORY vertex buffer, forwarding to DrawIndexedPrimitive().\n");
4366 wined3d_mutex_lock();
4367 wined3d_box
.left
= start_vertex
* stride
;
4368 wined3d_box
.right
= wined3d_box
.left
+ vertex_count
* stride
;
4369 wined3d_resource
= wined3d_buffer_get_resource(vb_impl
->wined3d_buffer
);
4370 if (FAILED(hr
= wined3d_resource_map(wined3d_resource
, 0, &wined3d_map_desc
,
4371 &wined3d_box
, WINED3D_MAP_READ
)))
4373 wined3d_mutex_unlock();
4374 return D3DERR_VERTEXBUFFERLOCKED
;
4376 hr
= d3d_device7_DrawIndexedPrimitive(iface
, primitive_type
, vb_impl
->fvf
,
4377 wined3d_map_desc
.data
, vertex_count
, indices
, index_count
, flags
);
4378 wined3d_resource_unmap(wined3d_resource
, 0);
4379 wined3d_mutex_unlock();
4384 * 1) Upload the indices to the index buffer
4385 * 2) Set the index source
4386 * 3) Set the Vertex Buffer as the Stream source
4387 * 4) Call wined3d_device_draw_indexed_primitive()
4390 wined3d_mutex_lock();
4392 wined3d_stateblock_set_vertex_declaration(device
->state
, vb_impl
->wined3d_declaration
);
4394 hr
= d3d_device_prepare_index_buffer(device
, index_count
* sizeof(WORD
));
4397 wined3d_mutex_unlock();
4400 ib_pos
= device
->index_buffer_pos
;
4402 if (device
->index_buffer_size
- index_count
* sizeof(WORD
) < ib_pos
)
4405 /* Copy the index stream into the index buffer. */
4406 wined3d_box
.left
= ib_pos
;
4407 wined3d_box
.right
= ib_pos
+ index_count
* sizeof(WORD
);
4408 ib
= wined3d_buffer_get_resource(device
->index_buffer
);
4409 if (FAILED(hr
= wined3d_resource_map(ib
, 0, &wined3d_map_desc
, &wined3d_box
,
4410 WINED3D_MAP_WRITE
| (ib_pos
? WINED3D_MAP_NOOVERWRITE
: WINED3D_MAP_DISCARD
))))
4412 ERR("Failed to map buffer, hr %#x.\n", hr
);
4413 wined3d_mutex_unlock();
4416 memcpy(wined3d_map_desc
.data
, indices
, index_count
* sizeof(WORD
));
4417 wined3d_resource_unmap(ib
, 0);
4418 device
->index_buffer_pos
= ib_pos
+ index_count
* sizeof(WORD
);
4420 /* Set the index stream */
4421 wined3d_stateblock_set_base_vertex_index(device
->state
, start_vertex
);
4422 wined3d_stateblock_set_index_buffer(device
->state
, device
->index_buffer
, WINED3DFMT_R16_UINT
);
4424 /* Set the vertex stream source */
4425 if (FAILED(hr
= wined3d_stateblock_set_stream_source(device
->state
,
4426 0, vb_impl
->wined3d_buffer
, 0, stride
)))
4428 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", device
, hr
);
4429 wined3d_mutex_unlock();
4433 wined3d_device_set_primitive_type(device
->wined3d_device
, wined3d_primitive_type_from_ddraw(primitive_type
), 0);
4434 wined3d_device_apply_stateblock(device
->wined3d_device
, device
->state
);
4435 hr
= wined3d_device_draw_indexed_primitive(device
->wined3d_device
, ib_pos
/ sizeof(WORD
), index_count
);
4437 wined3d_mutex_unlock();
4442 static HRESULT WINAPI
d3d_device7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7
*iface
,
4443 D3DPRIMITIVETYPE PrimitiveType
, IDirect3DVertexBuffer7
*D3DVertexBuf
,
4444 DWORD StartVertex
, DWORD NumVertices
, WORD
*Indices
, DWORD IndexCount
, DWORD Flags
)
4446 return d3d_device7_DrawIndexedPrimitiveVB(iface
, PrimitiveType
,
4447 D3DVertexBuf
, StartVertex
, NumVertices
, Indices
, IndexCount
, Flags
);
4450 static HRESULT WINAPI
d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7
*iface
,
4451 D3DPRIMITIVETYPE PrimitiveType
, IDirect3DVertexBuffer7
*D3DVertexBuf
,
4452 DWORD StartVertex
, DWORD NumVertices
, WORD
*Indices
, DWORD IndexCount
, DWORD Flags
)
4457 old_fpucw
= d3d_fpu_setup();
4458 hr
= d3d_device7_DrawIndexedPrimitiveVB(iface
, PrimitiveType
,
4459 D3DVertexBuf
, StartVertex
, NumVertices
, Indices
, IndexCount
, Flags
);
4460 set_fpu_control_word(old_fpucw
);
4465 static HRESULT WINAPI
d3d_device3_DrawIndexedPrimitiveVB(IDirect3DDevice3
*iface
,
4466 D3DPRIMITIVETYPE primitive_type
, IDirect3DVertexBuffer
*vertex_buffer
,
4467 WORD
*indices
, DWORD index_count
, DWORD flags
)
4469 struct d3d_vertex_buffer
*vb
=
4470 unsafe_impl_from_IDirect3DVertexBuffer7((IDirect3DVertexBuffer7
*)vertex_buffer
);
4471 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
4474 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4475 iface
, primitive_type
, vertex_buffer
, indices
, index_count
, flags
);
4477 setup_lighting(device
, vb
->fvf
, flags
);
4479 if (!(stride
= get_flexible_vertex_size(vb
->fvf
)))
4482 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&device
->IDirect3DDevice7_iface
, primitive_type
,
4483 &vb
->IDirect3DVertexBuffer7_iface
, 0, vb
->size
/ stride
, indices
, index_count
, flags
);
4486 /*****************************************************************************
4487 * IDirect3DDevice7::ComputeSphereVisibility
4489 * Calculates the visibility of spheres in the current viewport. The spheres
4490 * are passed in the Centers and Radii arrays, the results are passed back
4491 * in the ReturnValues array. Return values are either completely visible,
4492 * partially visible or completely invisible.
4493 * The return value consists of a combination of D3DCLIP_* flags, or is
4494 * 0 if the sphere is completely visible (according to the SDK, not checked)
4499 * Centers: Array containing the sphere centers
4500 * Radii: Array containing the sphere radii
4501 * NumSpheres: The number of centers and radii in the arrays
4503 * ReturnValues: Array to write the results to
4507 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4508 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4511 *****************************************************************************/
4513 static DWORD
in_plane(UINT idx
, struct wined3d_vec4 p
, D3DVECTOR center
, D3DVALUE radius
, BOOL equality
)
4515 float distance
, norm
;
4517 norm
= sqrtf(p
.x
* p
.x
+ p
.y
* p
.y
+ p
.z
* p
.z
);
4518 distance
= (p
.x
* center
.u1
.x
+ p
.y
* center
.u2
.y
+ p
.z
* center
.u3
.z
+ p
.w
) / norm
;
4522 if (fabs(distance
) <= radius
)
4523 return D3DSTATUS_CLIPUNIONLEFT
<< idx
;
4524 if (distance
<= -radius
)
4525 return (D3DSTATUS_CLIPUNIONLEFT
| D3DSTATUS_CLIPINTERSECTIONLEFT
) << idx
;
4529 if (fabs(distance
) < radius
)
4530 return D3DSTATUS_CLIPUNIONLEFT
<< idx
;
4531 if (distance
< -radius
)
4532 return (D3DSTATUS_CLIPUNIONLEFT
| D3DSTATUS_CLIPINTERSECTIONLEFT
) << idx
;
4537 static void prepare_clip_space_planes(struct d3d_device
*device
, struct wined3d_vec4
*plane
)
4539 const struct wined3d_stateblock_state
*state
;
4540 struct wined3d_matrix m
;
4542 /* We want the wined3d matrices since those include the legacy viewport
4543 * transformation. */
4544 wined3d_mutex_lock();
4545 state
= device
->stateblock_state
;
4546 multiply_matrix(&m
, &state
->transforms
[WINED3D_TS_VIEW
], &state
->transforms
[WINED3D_TS_WORLD
]);
4547 multiply_matrix(&m
, &state
->transforms
[WINED3D_TS_PROJECTION
], &m
);
4548 wined3d_mutex_unlock();
4551 plane
[0].x
= m
._14
+ m
._11
;
4552 plane
[0].y
= m
._24
+ m
._21
;
4553 plane
[0].z
= m
._34
+ m
._31
;
4554 plane
[0].w
= m
._44
+ m
._41
;
4557 plane
[1].x
= m
._14
- m
._11
;
4558 plane
[1].y
= m
._24
- m
._21
;
4559 plane
[1].z
= m
._34
- m
._31
;
4560 plane
[1].w
= m
._44
- m
._41
;
4563 plane
[2].x
= m
._14
- m
._12
;
4564 plane
[2].y
= m
._24
- m
._22
;
4565 plane
[2].z
= m
._34
- m
._32
;
4566 plane
[2].w
= m
._44
- m
._42
;
4569 plane
[3].x
= m
._14
+ m
._12
;
4570 plane
[3].y
= m
._24
+ m
._22
;
4571 plane
[3].z
= m
._34
+ m
._32
;
4572 plane
[3].w
= m
._44
+ m
._42
;
4581 plane
[5].x
= m
._14
- m
._13
;
4582 plane
[5].y
= m
._24
- m
._23
;
4583 plane
[5].z
= m
._34
- m
._33
;
4584 plane
[5].w
= m
._44
- m
._43
;
4587 static void compute_sphere_visibility(struct wined3d_vec4 plane
[12], DWORD enabled_planes
, BOOL equality
,
4588 D3DVECTOR
*centers
, D3DVALUE
*radii
, DWORD sphere_count
, DWORD
*return_values
)
4592 for (i
= 0; i
< sphere_count
; ++i
)
4594 return_values
[i
] = 0;
4595 for (j
= 0; j
< 12; ++j
)
4596 if (enabled_planes
& 1u << j
)
4597 return_values
[i
] |= in_plane(j
, plane
[j
], centers
[i
], radii
[i
], equality
);
4601 static HRESULT WINAPI
d3d_device7_ComputeSphereVisibility(IDirect3DDevice7
*iface
,
4602 D3DVECTOR
*centers
, D3DVALUE
*radii
, DWORD sphere_count
, DWORD flags
, DWORD
*return_values
)
4604 struct wined3d_vec4 plane
[12];
4605 DWORD enabled_planes
= 0x3f;
4606 DWORD user_clip_planes
;
4609 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4610 iface
, centers
, radii
, sphere_count
, flags
, return_values
);
4612 prepare_clip_space_planes(impl_from_IDirect3DDevice7(iface
), plane
);
4614 IDirect3DDevice7_GetRenderState(iface
, D3DRENDERSTATE_CLIPPLANEENABLE
, &user_clip_planes
);
4615 enabled_planes
|= user_clip_planes
<< 6;
4616 for (j
= 6; j
< 12; ++j
)
4617 IDirect3DDevice7_GetClipPlane(iface
, j
- 6, (D3DVALUE
*)&plane
[j
]);
4619 compute_sphere_visibility(plane
, enabled_planes
, FALSE
, centers
, radii
, sphere_count
, return_values
);
4623 static HRESULT WINAPI
d3d_device3_ComputeSphereVisibility(IDirect3DDevice3
*iface
,
4624 D3DVECTOR
*centers
, D3DVALUE
*radii
, DWORD sphere_count
, DWORD flags
, DWORD
*return_values
)
4626 static const DWORD enabled_planes
= 0x3f;
4627 struct wined3d_vec4 plane
[6];
4630 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4631 iface
, centers
, radii
, sphere_count
, flags
, return_values
);
4633 prepare_clip_space_planes(impl_from_IDirect3DDevice3(iface
), plane
);
4635 compute_sphere_visibility(plane
, enabled_planes
, TRUE
, centers
, radii
, sphere_count
, return_values
);
4636 for (i
= 0; i
< sphere_count
; ++i
)
4638 BOOL intersect_frustum
= FALSE
, outside_frustum
= FALSE
;
4639 DWORD d3d7_result
= return_values
[i
];
4641 return_values
[i
] = 0;
4643 for (j
= 0; j
< 6; ++j
)
4645 DWORD clip
= (d3d7_result
>> j
) & (D3DSTATUS_CLIPUNIONLEFT
| D3DSTATUS_CLIPINTERSECTIONLEFT
);
4647 if (clip
== D3DSTATUS_CLIPUNIONLEFT
)
4649 return_values
[i
] |= D3DVIS_INTERSECT_LEFT
<< j
* 2;
4650 intersect_frustum
= TRUE
;
4654 return_values
[i
] |= D3DVIS_OUTSIDE_LEFT
<< j
* 2;
4655 outside_frustum
= TRUE
;
4658 if (outside_frustum
)
4659 return_values
[i
] |= D3DVIS_OUTSIDE_FRUSTUM
;
4660 else if (intersect_frustum
)
4661 return_values
[i
] |= D3DVIS_INTERSECT_FRUSTUM
;
4666 /*****************************************************************************
4667 * IDirect3DDevice7::GetTexture
4669 * Returns the texture interface handle assigned to a texture stage.
4670 * The returned texture is AddRefed. This is taken from old ddraw,
4671 * not checked in Windows.
4676 * Stage: Texture stage to read the texture from
4677 * Texture: Address to store the interface pointer at
4681 * DDERR_INVALIDPARAMS if Texture is NULL
4683 *****************************************************************************/
4684 static HRESULT
d3d_device7_GetTexture(IDirect3DDevice7
*iface
,
4685 DWORD stage
, IDirectDrawSurface7
**texture
)
4687 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
4688 struct wined3d_texture
*wined3d_texture
;
4689 struct ddraw_texture
*ddraw_texture
;
4691 TRACE("iface %p, stage %u, texture %p.\n", iface
, stage
, texture
);
4694 return DDERR_INVALIDPARAMS
;
4696 if (stage
>= DDRAW_MAX_TEXTURES
)
4698 WARN("Invalid stage %u.\n", stage
);
4703 wined3d_mutex_lock();
4704 if (!(wined3d_texture
= device
->stateblock_state
->textures
[stage
]))
4707 wined3d_mutex_unlock();
4711 ddraw_texture
= wined3d_texture_get_parent(wined3d_texture
);
4712 *texture
= &ddraw_texture
->root
->IDirectDrawSurface7_iface
;
4713 IDirectDrawSurface7_AddRef(*texture
);
4714 wined3d_mutex_unlock();
4719 static HRESULT WINAPI
d3d_device7_GetTexture_FPUSetup(IDirect3DDevice7
*iface
,
4720 DWORD stage
, IDirectDrawSurface7
**Texture
)
4722 return d3d_device7_GetTexture(iface
, stage
, Texture
);
4725 static HRESULT WINAPI
d3d_device7_GetTexture_FPUPreserve(IDirect3DDevice7
*iface
,
4726 DWORD stage
, IDirectDrawSurface7
**Texture
)
4731 old_fpucw
= d3d_fpu_setup();
4732 hr
= d3d_device7_GetTexture(iface
, stage
, Texture
);
4733 set_fpu_control_word(old_fpucw
);
4738 static HRESULT WINAPI
d3d_device3_GetTexture(IDirect3DDevice3
*iface
, DWORD stage
, IDirect3DTexture2
**Texture2
)
4740 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
4741 struct ddraw_surface
*ret_val_impl
;
4743 IDirectDrawSurface7
*ret_val
;
4745 TRACE("iface %p, stage %u, texture %p.\n", iface
, stage
, Texture2
);
4747 ret
= IDirect3DDevice7_GetTexture(&device
->IDirect3DDevice7_iface
, stage
, &ret_val
);
4749 ret_val_impl
= unsafe_impl_from_IDirectDrawSurface7(ret_val
);
4750 *Texture2
= ret_val_impl
? &ret_val_impl
->IDirect3DTexture2_iface
: NULL
;
4752 TRACE("Returning texture %p.\n", *Texture2
);
4757 /*****************************************************************************
4758 * IDirect3DDevice7::SetTexture
4760 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4765 * Stage: The stage to assign the texture to
4766 * Texture: Interface pointer to the texture surface
4771 *****************************************************************************/
4772 static HRESULT
d3d_device7_SetTexture(IDirect3DDevice7
*iface
,
4773 DWORD stage
, IDirectDrawSurface7
*texture
)
4775 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
4776 struct ddraw_surface
*surf
= unsafe_impl_from_IDirectDrawSurface7(texture
);
4777 struct wined3d_texture
*wined3d_texture
= NULL
;
4779 TRACE("iface %p, stage %u, texture %p.\n", iface
, stage
, texture
);
4781 if (surf
&& (surf
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_TEXTURE
))
4782 wined3d_texture
= surf
->wined3d_texture
;
4784 wined3d_mutex_lock();
4785 wined3d_stateblock_set_texture(device
->update_state
, stage
, wined3d_texture
);
4786 wined3d_mutex_unlock();
4791 static HRESULT WINAPI
d3d_device7_SetTexture_FPUSetup(IDirect3DDevice7
*iface
,
4792 DWORD stage
, IDirectDrawSurface7
*texture
)
4794 return d3d_device7_SetTexture(iface
, stage
, texture
);
4797 static HRESULT WINAPI
d3d_device7_SetTexture_FPUPreserve(IDirect3DDevice7
*iface
,
4798 DWORD stage
, IDirectDrawSurface7
*texture
)
4803 old_fpucw
= d3d_fpu_setup();
4804 hr
= d3d_device7_SetTexture(iface
, stage
, texture
);
4805 set_fpu_control_word(old_fpucw
);
4810 static HRESULT WINAPI
d3d_device3_SetTexture(IDirect3DDevice3
*iface
,
4811 DWORD stage
, IDirect3DTexture2
*texture
)
4813 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
4814 struct ddraw_surface
*tex
= unsafe_impl_from_IDirect3DTexture2(texture
);
4817 TRACE("iface %p, stage %u, texture %p.\n", iface
, stage
, texture
);
4819 wined3d_mutex_lock();
4821 hr
= IDirect3DDevice7_SetTexture(&device
->IDirect3DDevice7_iface
, stage
, &tex
->IDirectDrawSurface7_iface
);
4823 fixup_texture_alpha_op(device
);
4825 wined3d_mutex_unlock();
4830 static const struct tss_lookup
4835 enum wined3d_texture_stage_state texture_state
;
4836 enum wined3d_sampler_state sampler_state
;
4841 {FALSE
, {WINED3D_TSS_INVALID
}}, /* 0, unused */
4842 {FALSE
, {WINED3D_TSS_COLOR_OP
}}, /* 1, D3DTSS_COLOROP */
4843 {FALSE
, {WINED3D_TSS_COLOR_ARG1
}}, /* 2, D3DTSS_COLORARG1 */
4844 {FALSE
, {WINED3D_TSS_COLOR_ARG2
}}, /* 3, D3DTSS_COLORARG2 */
4845 {FALSE
, {WINED3D_TSS_ALPHA_OP
}}, /* 4, D3DTSS_ALPHAOP */
4846 {FALSE
, {WINED3D_TSS_ALPHA_ARG1
}}, /* 5, D3DTSS_ALPHAARG1 */
4847 {FALSE
, {WINED3D_TSS_ALPHA_ARG2
}}, /* 6, D3DTSS_ALPHAARG2 */
4848 {FALSE
, {WINED3D_TSS_BUMPENV_MAT00
}}, /* 7, D3DTSS_BUMPENVMAT00 */
4849 {FALSE
, {WINED3D_TSS_BUMPENV_MAT01
}}, /* 8, D3DTSS_BUMPENVMAT01 */
4850 {FALSE
, {WINED3D_TSS_BUMPENV_MAT10
}}, /* 9, D3DTSS_BUMPENVMAT10 */
4851 {FALSE
, {WINED3D_TSS_BUMPENV_MAT11
}}, /* 10, D3DTSS_BUMPENVMAT11 */
4852 {FALSE
, {WINED3D_TSS_TEXCOORD_INDEX
}}, /* 11, D3DTSS_TEXCOORDINDEX */
4853 {TRUE
, {WINED3D_SAMP_ADDRESS_U
}}, /* 12, D3DTSS_ADDRESS */
4854 {TRUE
, {WINED3D_SAMP_ADDRESS_U
}}, /* 13, D3DTSS_ADDRESSU */
4855 {TRUE
, {WINED3D_SAMP_ADDRESS_V
}}, /* 14, D3DTSS_ADDRESSV */
4856 {TRUE
, {WINED3D_SAMP_BORDER_COLOR
}}, /* 15, D3DTSS_BORDERCOLOR */
4857 {TRUE
, {WINED3D_SAMP_MAG_FILTER
}}, /* 16, D3DTSS_MAGFILTER */
4858 {TRUE
, {WINED3D_SAMP_MIN_FILTER
}}, /* 17, D3DTSS_MINFILTER */
4859 {TRUE
, {WINED3D_SAMP_MIP_FILTER
}}, /* 18, D3DTSS_MIPFILTER */
4860 {TRUE
, {WINED3D_SAMP_MIPMAP_LOD_BIAS
}}, /* 19, D3DTSS_MIPMAPLODBIAS */
4861 {TRUE
, {WINED3D_SAMP_MAX_MIP_LEVEL
}}, /* 20, D3DTSS_MAXMIPLEVEL */
4862 {TRUE
, {WINED3D_SAMP_MAX_ANISOTROPY
}}, /* 21, D3DTSS_MAXANISOTROPY */
4863 {FALSE
, {WINED3D_TSS_BUMPENV_LSCALE
}}, /* 22, D3DTSS_BUMPENVLSCALE */
4864 {FALSE
, {WINED3D_TSS_BUMPENV_LOFFSET
}}, /* 23, D3DTSS_BUMPENVLOFFSET */
4865 {FALSE
, {WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS
}}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4868 /*****************************************************************************
4869 * IDirect3DDevice7::GetTextureStageState
4871 * Retrieves a state from a texture stage.
4876 * Stage: The stage to retrieve the state from
4877 * TexStageStateType: The state type to retrieve
4878 * State: Address to store the state's value at
4882 * DDERR_INVALIDPARAMS if State is NULL
4884 *****************************************************************************/
4885 static HRESULT
d3d_device7_GetTextureStageState(IDirect3DDevice7
*iface
,
4886 DWORD stage
, D3DTEXTURESTAGESTATETYPE state
, DWORD
*value
)
4888 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
4889 const struct wined3d_stateblock_state
*device_state
;
4890 const struct tss_lookup
*l
;
4892 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4893 iface
, stage
, state
, value
);
4896 return DDERR_INVALIDPARAMS
;
4898 if (state
> D3DTSS_TEXTURETRANSFORMFLAGS
)
4900 WARN("Invalid state %#x passed.\n", state
);
4904 if (stage
>= DDRAW_MAX_TEXTURES
)
4906 WARN("Invalid stage %u.\n", stage
);
4911 l
= &tss_lookup
[state
];
4913 wined3d_mutex_lock();
4915 device_state
= device
->stateblock_state
;
4917 if (l
->sampler_state
)
4919 *value
= device_state
->sampler_states
[stage
][l
->u
.sampler_state
];
4923 /* Mipfilter is a sampler state with different values */
4924 case D3DTSS_MIPFILTER
:
4928 case WINED3D_TEXF_NONE
:
4929 *value
= D3DTFP_NONE
;
4931 case WINED3D_TEXF_POINT
:
4932 *value
= D3DTFP_POINT
;
4934 case WINED3D_TEXF_LINEAR
:
4935 *value
= D3DTFP_LINEAR
;
4938 ERR("Unexpected mipfilter value %#x.\n", *value
);
4939 *value
= D3DTFP_NONE
;
4945 /* Magfilter has slightly different values */
4946 case D3DTSS_MAGFILTER
:
4950 case WINED3D_TEXF_POINT
:
4951 *value
= D3DTFG_POINT
;
4953 case WINED3D_TEXF_LINEAR
:
4954 *value
= D3DTFG_LINEAR
;
4956 case WINED3D_TEXF_ANISOTROPIC
:
4957 *value
= D3DTFG_ANISOTROPIC
;
4959 case WINED3D_TEXF_FLAT_CUBIC
:
4960 *value
= D3DTFG_FLATCUBIC
;
4962 case WINED3D_TEXF_GAUSSIAN_CUBIC
:
4963 *value
= D3DTFG_GAUSSIANCUBIC
;
4966 ERR("Unexpected wined3d mag filter value %#x.\n", *value
);
4967 *value
= D3DTFG_POINT
;
4979 *value
= device_state
->texture_states
[stage
][l
->u
.texture_state
];
4982 wined3d_mutex_unlock();
4987 static HRESULT WINAPI
d3d_device7_GetTextureStageState_FPUSetup(IDirect3DDevice7
*iface
,
4988 DWORD stage
, D3DTEXTURESTAGESTATETYPE state
, DWORD
*value
)
4990 return d3d_device7_GetTextureStageState(iface
, stage
, state
, value
);
4993 static HRESULT WINAPI
d3d_device7_GetTextureStageState_FPUPreserve(IDirect3DDevice7
*iface
,
4994 DWORD stage
, D3DTEXTURESTAGESTATETYPE state
, DWORD
*value
)
4999 old_fpucw
= d3d_fpu_setup();
5000 hr
= d3d_device7_GetTextureStageState(iface
, stage
, state
, value
);
5001 set_fpu_control_word(old_fpucw
);
5006 static HRESULT WINAPI
d3d_device3_GetTextureStageState(IDirect3DDevice3
*iface
,
5007 DWORD stage
, D3DTEXTURESTAGESTATETYPE state
, DWORD
*value
)
5009 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
5011 TRACE("iface %p, stage %u, state %#x, value %p.\n",
5012 iface
, stage
, state
, value
);
5014 return IDirect3DDevice7_GetTextureStageState(&device
->IDirect3DDevice7_iface
, stage
, state
, value
);
5017 /*****************************************************************************
5018 * IDirect3DDevice7::SetTextureStageState
5020 * Sets a texture stage state. Some stage types need to be handled specially,
5021 * because they do not exist in WineD3D and were moved to another place
5026 * Stage: The stage to modify
5027 * TexStageStateType: The state to change
5028 * State: The new value for the state
5033 *****************************************************************************/
5034 static HRESULT
d3d_device7_SetTextureStageState(IDirect3DDevice7
*iface
,
5035 DWORD stage
, D3DTEXTURESTAGESTATETYPE state
, DWORD value
)
5037 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5038 const struct tss_lookup
*l
;
5040 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5041 iface
, stage
, state
, value
);
5043 if (state
> D3DTSS_TEXTURETRANSFORMFLAGS
)
5045 WARN("Invalid state %#x passed.\n", state
);
5049 l
= &tss_lookup
[state
];
5051 wined3d_mutex_lock();
5053 if (l
->sampler_state
)
5057 /* Mipfilter is a sampler state with different values */
5058 case D3DTSS_MIPFILTER
:
5063 value
= WINED3D_TEXF_NONE
;
5066 value
= WINED3D_TEXF_POINT
;
5068 case 0: /* Unchecked */
5070 value
= WINED3D_TEXF_LINEAR
;
5073 ERR("Unexpected mipfilter value %#x.\n", value
);
5074 value
= WINED3D_TEXF_NONE
;
5080 /* Magfilter has slightly different values */
5081 case D3DTSS_MAGFILTER
:
5086 value
= WINED3D_TEXF_POINT
;
5089 value
= WINED3D_TEXF_LINEAR
;
5091 case D3DTFG_FLATCUBIC
:
5092 value
= WINED3D_TEXF_FLAT_CUBIC
;
5094 case D3DTFG_GAUSSIANCUBIC
:
5095 value
= WINED3D_TEXF_GAUSSIAN_CUBIC
;
5097 case D3DTFG_ANISOTROPIC
:
5098 value
= WINED3D_TEXF_ANISOTROPIC
;
5101 ERR("Unexpected d3d7 mag filter value %#x.\n", value
);
5102 value
= WINED3D_TEXF_POINT
;
5108 case D3DTSS_ADDRESS
:
5109 wined3d_stateblock_set_sampler_state(device
->state
, stage
, WINED3D_SAMP_ADDRESS_V
, value
);
5116 wined3d_stateblock_set_sampler_state(device
->state
, stage
, l
->u
.sampler_state
, value
);
5119 wined3d_stateblock_set_texture_stage_state(device
->update_state
, stage
, l
->u
.texture_state
, value
);
5121 wined3d_mutex_unlock();
5126 static HRESULT WINAPI
d3d_device7_SetTextureStageState_FPUSetup(IDirect3DDevice7
*iface
,
5127 DWORD stage
, D3DTEXTURESTAGESTATETYPE state
, DWORD value
)
5129 return d3d_device7_SetTextureStageState(iface
, stage
, state
, value
);
5132 static HRESULT WINAPI
d3d_device7_SetTextureStageState_FPUPreserve(IDirect3DDevice7
*iface
,
5133 DWORD stage
, D3DTEXTURESTAGESTATETYPE state
, DWORD value
)
5138 old_fpucw
= d3d_fpu_setup();
5139 hr
= d3d_device7_SetTextureStageState(iface
, stage
, state
, value
);
5140 set_fpu_control_word(old_fpucw
);
5145 static HRESULT WINAPI
d3d_device3_SetTextureStageState(IDirect3DDevice3
*iface
,
5146 DWORD stage
, D3DTEXTURESTAGESTATETYPE state
, DWORD value
)
5148 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
5152 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5153 iface
, stage
, state
, value
);
5155 /* Tests show that legacy texture blending is not reset if the texture stage state
5156 * value is unchanged. */
5157 if (FAILED(hr
= IDirect3DDevice7_GetTextureStageState(&device
->IDirect3DDevice7_iface
,
5158 stage
, state
, &old_value
)))
5161 if (old_value
== value
)
5163 TRACE("Application is setting the same value over, nothing to do.\n");
5167 device
->legacyTextureBlending
= FALSE
;
5169 return IDirect3DDevice7_SetTextureStageState(&device
->IDirect3DDevice7_iface
, stage
, state
, value
);
5172 /*****************************************************************************
5173 * IDirect3DDevice7::ValidateDevice
5175 * SDK: "Reports the device's ability to render the currently set
5176 * texture-blending operations in a single pass". Whatever that means
5182 * NumPasses: Address to write the number of necessary passes for the
5183 * desired effect to.
5188 *****************************************************************************/
5189 static HRESULT
d3d_device7_ValidateDevice(IDirect3DDevice7
*iface
, DWORD
*pass_count
)
5191 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5194 TRACE("iface %p, pass_count %p.\n", iface
, pass_count
);
5196 wined3d_mutex_lock();
5197 wined3d_device_apply_stateblock(device
->wined3d_device
, device
->state
);
5198 hr
= wined3d_device_validate_device(device
->wined3d_device
, pass_count
);
5199 wined3d_mutex_unlock();
5204 static HRESULT WINAPI
d3d_device7_ValidateDevice_FPUSetup(IDirect3DDevice7
*iface
, DWORD
*pass_count
)
5206 return d3d_device7_ValidateDevice(iface
, pass_count
);
5209 static HRESULT WINAPI
d3d_device7_ValidateDevice_FPUPreserve(IDirect3DDevice7
*iface
, DWORD
*pass_count
)
5214 old_fpucw
= d3d_fpu_setup();
5215 hr
= d3d_device7_ValidateDevice(iface
, pass_count
);
5216 set_fpu_control_word(old_fpucw
);
5221 static HRESULT WINAPI
d3d_device3_ValidateDevice(IDirect3DDevice3
*iface
, DWORD
*pass_count
)
5223 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
5225 TRACE("iface %p, pass_count %p.\n", iface
, pass_count
);
5227 return IDirect3DDevice7_ValidateDevice(&device
->IDirect3DDevice7_iface
, pass_count
);
5230 /*****************************************************************************
5231 * IDirect3DDevice7::Clear
5233 * Fills the render target, the z buffer and the stencil buffer with a
5234 * clear color / value
5239 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5240 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5241 * Flags: Some flags, as usual
5242 * Color: Clear color for the render target
5243 * Z: Clear value for the Z buffer
5244 * Stencil: Clear value to store in each stencil buffer entry
5249 *****************************************************************************/
5250 static HRESULT
d3d_device7_Clear(IDirect3DDevice7
*iface
, DWORD count
,
5251 D3DRECT
*rects
, DWORD flags
, D3DCOLOR color
, D3DVALUE z
, DWORD stencil
)
5253 const struct wined3d_color c
=
5255 ((color
>> 16) & 0xff) / 255.0f
,
5256 ((color
>> 8) & 0xff) / 255.0f
,
5257 (color
& 0xff) / 255.0f
,
5258 ((color
>> 24) & 0xff) / 255.0f
,
5260 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5263 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5264 iface
, count
, rects
, flags
, color
, z
, stencil
);
5266 if (count
&& !rects
)
5268 WARN("count %u with NULL rects.\n", count
);
5272 wined3d_mutex_lock();
5273 wined3d_device_apply_stateblock(device
->wined3d_device
, device
->state
);
5274 hr
= wined3d_device_clear(device
->wined3d_device
, count
, (RECT
*)rects
, flags
, &c
, z
, stencil
);
5275 wined3d_mutex_unlock();
5280 static HRESULT WINAPI
d3d_device7_Clear_FPUSetup(IDirect3DDevice7
*iface
, DWORD count
,
5281 D3DRECT
*rects
, DWORD flags
, D3DCOLOR color
, D3DVALUE z
, DWORD stencil
)
5283 return d3d_device7_Clear(iface
, count
, rects
, flags
, color
, z
, stencil
);
5286 static HRESULT WINAPI
d3d_device7_Clear_FPUPreserve(IDirect3DDevice7
*iface
, DWORD count
,
5287 D3DRECT
*rects
, DWORD flags
, D3DCOLOR color
, D3DVALUE z
, DWORD stencil
)
5292 old_fpucw
= d3d_fpu_setup();
5293 hr
= d3d_device7_Clear(iface
, count
, rects
, flags
, color
, z
, stencil
);
5294 set_fpu_control_word(old_fpucw
);
5299 static HRESULT
d3d_device7_SetViewport(IDirect3DDevice7
*iface
, D3DVIEWPORT7
*viewport
)
5301 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5302 struct wined3d_sub_resource_desc rt_desc
;
5303 struct wined3d_rendertarget_view
*rtv
;
5304 struct ddraw_surface
*surface
;
5305 struct wined3d_viewport vp
;
5307 TRACE("iface %p, viewport %p.\n", iface
, viewport
);
5310 return DDERR_INVALIDPARAMS
;
5312 wined3d_mutex_lock();
5313 if (!(rtv
= wined3d_device_get_rendertarget_view(device
->wined3d_device
, 0)))
5315 wined3d_mutex_unlock();
5316 return DDERR_INVALIDCAPS
;
5318 surface
= wined3d_rendertarget_view_get_sub_resource_parent(rtv
);
5319 wined3d_texture_get_sub_resource_desc(surface
->wined3d_texture
, surface
->sub_resource_idx
, &rt_desc
);
5321 if (viewport
->dwX
> rt_desc
.width
|| viewport
->dwWidth
> rt_desc
.width
- viewport
->dwX
5322 || viewport
->dwY
> rt_desc
.height
|| viewport
->dwHeight
> rt_desc
.height
- viewport
->dwY
)
5324 WARN("Invalid viewport, returning E_INVALIDARG.\n");
5325 wined3d_mutex_unlock();
5326 return E_INVALIDARG
;
5329 vp
.x
= viewport
->dwX
;
5330 vp
.y
= viewport
->dwY
;
5331 vp
.width
= viewport
->dwWidth
;
5332 vp
.height
= viewport
->dwHeight
;
5333 vp
.min_z
= viewport
->dvMinZ
;
5334 vp
.max_z
= viewport
->dvMaxZ
;
5336 wined3d_stateblock_set_viewport(device
->update_state
, &vp
);
5337 wined3d_mutex_unlock();
5342 static HRESULT WINAPI
d3d_device7_SetViewport_FPUSetup(IDirect3DDevice7
*iface
, D3DVIEWPORT7
*viewport
)
5344 return d3d_device7_SetViewport(iface
, viewport
);
5347 static HRESULT WINAPI
d3d_device7_SetViewport_FPUPreserve(IDirect3DDevice7
*iface
, D3DVIEWPORT7
*viewport
)
5352 old_fpucw
= d3d_fpu_setup();
5353 hr
= d3d_device7_SetViewport(iface
, viewport
);
5354 set_fpu_control_word(old_fpucw
);
5359 static HRESULT
d3d_device7_GetViewport(IDirect3DDevice7
*iface
, D3DVIEWPORT7
*viewport
)
5361 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5362 struct wined3d_viewport wined3d_viewport
;
5364 TRACE("iface %p, viewport %p.\n", iface
, viewport
);
5367 return DDERR_INVALIDPARAMS
;
5369 wined3d_mutex_lock();
5370 wined3d_viewport
= device
->stateblock_state
->viewport
;
5371 wined3d_mutex_unlock();
5373 viewport
->dwX
= wined3d_viewport
.x
;
5374 viewport
->dwY
= wined3d_viewport
.y
;
5375 viewport
->dwWidth
= wined3d_viewport
.width
;
5376 viewport
->dwHeight
= wined3d_viewport
.height
;
5377 viewport
->dvMinZ
= wined3d_viewport
.min_z
;
5378 viewport
->dvMaxZ
= wined3d_viewport
.max_z
;
5383 static HRESULT WINAPI
d3d_device7_GetViewport_FPUSetup(IDirect3DDevice7
*iface
, D3DVIEWPORT7
*viewport
)
5385 return d3d_device7_GetViewport(iface
, viewport
);
5388 static HRESULT WINAPI
d3d_device7_GetViewport_FPUPreserve(IDirect3DDevice7
*iface
, D3DVIEWPORT7
*viewport
)
5393 old_fpucw
= d3d_fpu_setup();
5394 hr
= d3d_device7_GetViewport(iface
, viewport
);
5395 set_fpu_control_word(old_fpucw
);
5400 /*****************************************************************************
5401 * IDirect3DDevice7::SetMaterial
5408 * Mat: The material to set
5412 * DDERR_INVALIDPARAMS if Mat is NULL.
5414 *****************************************************************************/
5415 static HRESULT
d3d_device7_SetMaterial(IDirect3DDevice7
*iface
, D3DMATERIAL7
*material
)
5417 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5419 TRACE("iface %p, material %p.\n", iface
, material
);
5422 return DDERR_INVALIDPARAMS
;
5424 wined3d_mutex_lock();
5425 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5426 wined3d_stateblock_set_material(device
->update_state
, (const struct wined3d_material
*)material
);
5427 wined3d_mutex_unlock();
5432 static HRESULT WINAPI
d3d_device7_SetMaterial_FPUSetup(IDirect3DDevice7
*iface
, D3DMATERIAL7
*material
)
5434 return d3d_device7_SetMaterial(iface
, material
);
5437 static HRESULT WINAPI
d3d_device7_SetMaterial_FPUPreserve(IDirect3DDevice7
*iface
, D3DMATERIAL7
*material
)
5442 old_fpucw
= d3d_fpu_setup();
5443 hr
= d3d_device7_SetMaterial(iface
, material
);
5444 set_fpu_control_word(old_fpucw
);
5449 /*****************************************************************************
5450 * IDirect3DDevice7::GetMaterial
5452 * Returns the current material
5457 * Mat: D3DMATERIAL7 structure to write the material parameters to
5461 * DDERR_INVALIDPARAMS if Mat is NULL
5463 *****************************************************************************/
5464 static HRESULT
d3d_device7_GetMaterial(IDirect3DDevice7
*iface
, D3DMATERIAL7
*material
)
5466 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5468 TRACE("iface %p, material %p.\n", iface
, material
);
5470 wined3d_mutex_lock();
5471 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5472 memcpy(material
, &device
->stateblock_state
->material
, sizeof(*material
));
5473 wined3d_mutex_unlock();
5478 static HRESULT WINAPI
d3d_device7_GetMaterial_FPUSetup(IDirect3DDevice7
*iface
, D3DMATERIAL7
*material
)
5480 return d3d_device7_GetMaterial(iface
, material
);
5483 static HRESULT WINAPI
d3d_device7_GetMaterial_FPUPreserve(IDirect3DDevice7
*iface
, D3DMATERIAL7
*material
)
5488 old_fpucw
= d3d_fpu_setup();
5489 hr
= d3d_device7_GetMaterial(iface
, material
);
5490 set_fpu_control_word(old_fpucw
);
5495 /*****************************************************************************
5496 * IDirect3DDevice7::SetLight
5498 * Assigns a light to a light index, but doesn't activate it yet.
5500 * Version 7, IDirect3DLight uses this method for older versions
5503 * LightIndex: The index of the new light
5504 * Light: A D3DLIGHT7 structure describing the light
5509 *****************************************************************************/
5510 static HRESULT
d3d_device7_SetLight(IDirect3DDevice7
*iface
, DWORD light_idx
, D3DLIGHT7
*light
)
5512 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5515 TRACE("iface %p, light_idx %u, light %p.\n", iface
, light_idx
, light
);
5517 wined3d_mutex_lock();
5518 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5519 hr
= wined3d_stateblock_set_light(device
->update_state
, light_idx
, (const struct wined3d_light
*)light
);
5520 wined3d_mutex_unlock();
5522 return hr_ddraw_from_wined3d(hr
);
5525 static HRESULT WINAPI
d3d_device7_SetLight_FPUSetup(IDirect3DDevice7
*iface
, DWORD light_idx
, D3DLIGHT7
*light
)
5527 return d3d_device7_SetLight(iface
, light_idx
, light
);
5530 static HRESULT WINAPI
d3d_device7_SetLight_FPUPreserve(IDirect3DDevice7
*iface
, DWORD light_idx
, D3DLIGHT7
*light
)
5535 old_fpucw
= d3d_fpu_setup();
5536 hr
= d3d_device7_SetLight(iface
, light_idx
, light
);
5537 set_fpu_control_word(old_fpucw
);
5542 /*****************************************************************************
5543 * IDirect3DDevice7::GetLight
5545 * Returns the light assigned to a light index
5548 * Light: Structure to write the light information to
5552 * DDERR_INVALIDPARAMS if Light is NULL
5554 *****************************************************************************/
5555 static HRESULT
d3d_device7_GetLight(IDirect3DDevice7
*iface
, DWORD light_idx
, D3DLIGHT7
*light
)
5557 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5561 TRACE("iface %p, light_idx %u, light %p.\n", iface
, light_idx
, light
);
5563 wined3d_mutex_lock();
5564 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5565 hr
= wined3d_stateblock_get_light(device
->state
, light_idx
, (struct wined3d_light
*)light
, &enabled
);
5566 wined3d_mutex_unlock();
5568 return hr_ddraw_from_wined3d(hr
);
5571 static HRESULT WINAPI
d3d_device7_GetLight_FPUSetup(IDirect3DDevice7
*iface
, DWORD light_idx
, D3DLIGHT7
*light
)
5573 return d3d_device7_GetLight(iface
, light_idx
, light
);
5576 static HRESULT WINAPI
d3d_device7_GetLight_FPUPreserve(IDirect3DDevice7
*iface
, DWORD light_idx
, D3DLIGHT7
*light
)
5581 old_fpucw
= d3d_fpu_setup();
5582 hr
= d3d_device7_GetLight(iface
, light_idx
, light
);
5583 set_fpu_control_word(old_fpucw
);
5588 /*****************************************************************************
5589 * IDirect3DDevice7::BeginStateBlock
5591 * Begins recording to a stateblock
5598 *****************************************************************************/
5599 static HRESULT
d3d_device7_BeginStateBlock(IDirect3DDevice7
*iface
)
5601 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5602 struct wined3d_stateblock
*stateblock
;
5605 TRACE("iface %p.\n", iface
);
5607 wined3d_mutex_lock();
5608 if (device
->recording
)
5610 wined3d_mutex_unlock();
5611 WARN("Trying to begin a stateblock while recording, returning D3DERR_INBEGINSTATEBLOCK.\n");
5612 return D3DERR_INBEGINSTATEBLOCK
;
5614 if (SUCCEEDED(hr
= wined3d_stateblock_create(device
->wined3d_device
, NULL
, WINED3D_SBT_RECORDED
, &stateblock
)))
5615 device
->update_state
= device
->recording
= stateblock
;
5616 wined3d_mutex_unlock();
5618 return hr_ddraw_from_wined3d(hr
);
5621 static HRESULT WINAPI
d3d_device7_BeginStateBlock_FPUSetup(IDirect3DDevice7
*iface
)
5623 return d3d_device7_BeginStateBlock(iface
);
5626 static HRESULT WINAPI
d3d_device7_BeginStateBlock_FPUPreserve(IDirect3DDevice7
*iface
)
5631 old_fpucw
= d3d_fpu_setup();
5632 hr
= d3d_device7_BeginStateBlock(iface
);
5633 set_fpu_control_word(old_fpucw
);
5638 /*****************************************************************************
5639 * IDirect3DDevice7::EndStateBlock
5641 * Stops recording to a state block and returns the created stateblock
5647 * BlockHandle: Address to store the stateblock's handle to
5651 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5653 *****************************************************************************/
5654 static HRESULT
d3d_device7_EndStateBlock(IDirect3DDevice7
*iface
, DWORD
*stateblock
)
5656 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5657 struct wined3d_stateblock
*wined3d_sb
;
5660 TRACE("iface %p, stateblock %p.\n", iface
, stateblock
);
5663 return DDERR_INVALIDPARAMS
;
5665 wined3d_mutex_lock();
5666 if (!device
->recording
)
5668 wined3d_mutex_unlock();
5669 WARN("Trying to end a stateblock, but no stateblock is being recorded.\n");
5670 return D3DERR_NOTINBEGINSTATEBLOCK
;
5672 wined3d_sb
= device
->recording
;
5673 wined3d_stateblock_init_contained_states(wined3d_sb
);
5674 device
->recording
= NULL
;
5675 device
->update_state
= device
->state
;
5677 h
= ddraw_allocate_handle(&device
->handle_table
, wined3d_sb
, DDRAW_HANDLE_STATEBLOCK
);
5678 if (h
== DDRAW_INVALID_HANDLE
)
5680 ERR("Failed to allocate a stateblock handle.\n");
5681 wined3d_stateblock_decref(wined3d_sb
);
5682 wined3d_mutex_unlock();
5684 return DDERR_OUTOFMEMORY
;
5687 wined3d_mutex_unlock();
5688 *stateblock
= h
+ 1;
5693 static HRESULT WINAPI
d3d_device7_EndStateBlock_FPUSetup(IDirect3DDevice7
*iface
, DWORD
*stateblock
)
5695 return d3d_device7_EndStateBlock(iface
, stateblock
);
5698 static HRESULT WINAPI
d3d_device7_EndStateBlock_FPUPreserve(IDirect3DDevice7
*iface
, DWORD
*stateblock
)
5703 old_fpucw
= d3d_fpu_setup();
5704 hr
= d3d_device7_EndStateBlock(iface
, stateblock
);
5705 set_fpu_control_word(old_fpucw
);
5710 /*****************************************************************************
5711 * IDirect3DDevice7::PreLoad
5713 * Allows the app to signal that a texture will be used soon, to allow
5714 * the Direct3DDevice to load it to the video card in the meantime.
5719 * Texture: The texture to preload
5723 * DDERR_INVALIDPARAMS if Texture is NULL
5725 *****************************************************************************/
5726 static HRESULT
d3d_device7_PreLoad(IDirect3DDevice7
*iface
, IDirectDrawSurface7
*texture
)
5728 struct ddraw_surface
*surface
= unsafe_impl_from_IDirectDrawSurface7(texture
);
5730 TRACE("iface %p, texture %p.\n", iface
, texture
);
5733 return DDERR_INVALIDPARAMS
;
5735 wined3d_mutex_lock();
5736 wined3d_resource_preload(wined3d_texture_get_resource(surface
->wined3d_texture
));
5737 wined3d_mutex_unlock();
5742 static HRESULT WINAPI
d3d_device7_PreLoad_FPUSetup(IDirect3DDevice7
*iface
, IDirectDrawSurface7
*texture
)
5744 return d3d_device7_PreLoad(iface
, texture
);
5747 static HRESULT WINAPI
d3d_device7_PreLoad_FPUPreserve(IDirect3DDevice7
*iface
, IDirectDrawSurface7
*texture
)
5752 old_fpucw
= d3d_fpu_setup();
5753 hr
= d3d_device7_PreLoad(iface
, texture
);
5754 set_fpu_control_word(old_fpucw
);
5759 /*****************************************************************************
5760 * IDirect3DDevice7::ApplyStateBlock
5762 * Activates the state stored in a state block handle.
5765 * BlockHandle: The stateblock handle to activate
5769 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5771 *****************************************************************************/
5772 static HRESULT
d3d_device7_ApplyStateBlock(IDirect3DDevice7
*iface
, DWORD stateblock
)
5774 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5775 struct wined3d_stateblock
*wined3d_sb
;
5777 TRACE("iface %p, stateblock %#x.\n", iface
, stateblock
);
5779 wined3d_mutex_lock();
5780 if (device
->recording
)
5782 wined3d_mutex_unlock();
5783 WARN("Trying to apply a stateblock while recording, returning D3DERR_INBEGINSTATEBLOCK.\n");
5784 return D3DERR_INBEGINSTATEBLOCK
;
5786 wined3d_sb
= ddraw_get_object(&device
->handle_table
, stateblock
- 1, DDRAW_HANDLE_STATEBLOCK
);
5789 WARN("Invalid stateblock handle.\n");
5790 wined3d_mutex_unlock();
5791 return D3DERR_INVALIDSTATEBLOCK
;
5794 wined3d_stateblock_apply(wined3d_sb
, device
->state
);
5795 wined3d_mutex_unlock();
5800 static HRESULT WINAPI
d3d_device7_ApplyStateBlock_FPUSetup(IDirect3DDevice7
*iface
, DWORD stateblock
)
5802 return d3d_device7_ApplyStateBlock(iface
, stateblock
);
5805 static HRESULT WINAPI
d3d_device7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7
*iface
, DWORD stateblock
)
5810 old_fpucw
= d3d_fpu_setup();
5811 hr
= d3d_device7_ApplyStateBlock(iface
, stateblock
);
5812 set_fpu_control_word(old_fpucw
);
5817 /*****************************************************************************
5818 * IDirect3DDevice7::CaptureStateBlock
5820 * Updates a stateblock's values to the values currently set for the device
5825 * BlockHandle: Stateblock to update
5829 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5831 *****************************************************************************/
5832 static HRESULT
d3d_device7_CaptureStateBlock(IDirect3DDevice7
*iface
, DWORD stateblock
)
5834 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5835 struct wined3d_stateblock
*wined3d_sb
;
5837 TRACE("iface %p, stateblock %#x.\n", iface
, stateblock
);
5839 wined3d_mutex_lock();
5840 if (device
->recording
)
5842 wined3d_mutex_unlock();
5843 WARN("Trying to capture a stateblock while recording, returning D3DERR_INBEGINSTATEBLOCK.\n");
5844 return D3DERR_INBEGINSTATEBLOCK
;
5846 wined3d_sb
= ddraw_get_object(&device
->handle_table
, stateblock
- 1, DDRAW_HANDLE_STATEBLOCK
);
5849 WARN("Invalid stateblock handle.\n");
5850 wined3d_mutex_unlock();
5851 return D3DERR_INVALIDSTATEBLOCK
;
5854 wined3d_stateblock_capture(wined3d_sb
, device
->state
);
5855 wined3d_mutex_unlock();
5860 static HRESULT WINAPI
d3d_device7_CaptureStateBlock_FPUSetup(IDirect3DDevice7
*iface
, DWORD stateblock
)
5862 return d3d_device7_CaptureStateBlock(iface
, stateblock
);
5865 static HRESULT WINAPI
d3d_device7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7
*iface
, DWORD stateblock
)
5870 old_fpucw
= d3d_fpu_setup();
5871 hr
= d3d_device7_CaptureStateBlock(iface
, stateblock
);
5872 set_fpu_control_word(old_fpucw
);
5877 /*****************************************************************************
5878 * IDirect3DDevice7::DeleteStateBlock
5880 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5885 * BlockHandle: Stateblock handle to delete
5889 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5891 *****************************************************************************/
5892 static HRESULT
d3d_device7_DeleteStateBlock(IDirect3DDevice7
*iface
, DWORD stateblock
)
5894 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5895 struct wined3d_stateblock
*wined3d_sb
;
5898 TRACE("iface %p, stateblock %#x.\n", iface
, stateblock
);
5900 wined3d_mutex_lock();
5902 wined3d_sb
= ddraw_free_handle(&device
->handle_table
, stateblock
- 1, DDRAW_HANDLE_STATEBLOCK
);
5905 WARN("Invalid stateblock handle.\n");
5906 wined3d_mutex_unlock();
5907 return D3DERR_INVALIDSTATEBLOCK
;
5910 if ((ref
= wined3d_stateblock_decref(wined3d_sb
)))
5912 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb
, ref
);
5915 wined3d_mutex_unlock();
5920 static HRESULT WINAPI
d3d_device7_DeleteStateBlock_FPUSetup(IDirect3DDevice7
*iface
, DWORD stateblock
)
5922 return d3d_device7_DeleteStateBlock(iface
, stateblock
);
5925 static HRESULT WINAPI
d3d_device7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7
*iface
, DWORD stateblock
)
5930 old_fpucw
= d3d_fpu_setup();
5931 hr
= d3d_device7_DeleteStateBlock(iface
, stateblock
);
5932 set_fpu_control_word(old_fpucw
);
5937 /*****************************************************************************
5938 * IDirect3DDevice7::CreateStateBlock
5940 * Creates a new state block handle.
5945 * Type: The state block type
5946 * BlockHandle: Address to write the created handle to
5950 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5952 *****************************************************************************/
5953 static HRESULT
d3d_device7_CreateStateBlock(IDirect3DDevice7
*iface
,
5954 D3DSTATEBLOCKTYPE type
, DWORD
*stateblock
)
5956 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5957 struct wined3d_stateblock
*wined3d_sb
;
5961 TRACE("iface %p, type %#x, stateblock %p.\n", iface
, type
, stateblock
);
5964 return DDERR_INVALIDPARAMS
;
5966 if (type
!= D3DSBT_ALL
5967 && type
!= D3DSBT_PIXELSTATE
5968 && type
!= D3DSBT_VERTEXSTATE
)
5970 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5971 return DDERR_INVALIDPARAMS
;
5974 wined3d_mutex_lock();
5976 if (device
->recording
)
5978 wined3d_mutex_unlock();
5979 WARN("Trying to apply a stateblock while recording, returning D3DERR_INBEGINSTATEBLOCK.\n");
5980 return D3DERR_INBEGINSTATEBLOCK
;
5983 if (FAILED(hr
= wined3d_stateblock_create(device
->wined3d_device
,
5984 device
->state
, wined3d_stateblock_type_from_ddraw(type
), &wined3d_sb
)))
5986 WARN("Failed to create stateblock, hr %#x.\n", hr
);
5987 wined3d_mutex_unlock();
5988 return hr_ddraw_from_wined3d(hr
);
5991 h
= ddraw_allocate_handle(&device
->handle_table
, wined3d_sb
, DDRAW_HANDLE_STATEBLOCK
);
5992 if (h
== DDRAW_INVALID_HANDLE
)
5994 ERR("Failed to allocate stateblock handle.\n");
5995 wined3d_stateblock_decref(wined3d_sb
);
5996 wined3d_mutex_unlock();
5997 return DDERR_OUTOFMEMORY
;
6000 *stateblock
= h
+ 1;
6001 wined3d_mutex_unlock();
6003 return hr_ddraw_from_wined3d(hr
);
6006 static HRESULT WINAPI
d3d_device7_CreateStateBlock_FPUSetup(IDirect3DDevice7
*iface
,
6007 D3DSTATEBLOCKTYPE type
, DWORD
*stateblock
)
6009 return d3d_device7_CreateStateBlock(iface
, type
, stateblock
);
6012 static HRESULT WINAPI
d3d_device7_CreateStateBlock_FPUPreserve(IDirect3DDevice7
*iface
,
6013 D3DSTATEBLOCKTYPE type
, DWORD
*stateblock
)
6018 old_fpucw
= d3d_fpu_setup();
6019 hr
= d3d_device7_CreateStateBlock(iface
, type
, stateblock
);
6020 set_fpu_control_word(old_fpucw
);
6025 static BOOL
is_mip_level_subset(struct ddraw_surface
*dest
, struct ddraw_surface
*src
)
6027 struct ddraw_surface
*src_level
, *dest_level
;
6028 IDirectDrawSurface7
*temp
;
6029 DDSURFACEDESC2 ddsd
;
6030 BOOL levelFound
; /* at least one suitable sublevel in dest found */
6032 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
6033 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
6034 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
6041 for (;src_level
&& dest_level
;)
6043 if (src_level
->surface_desc
.dwWidth
== dest_level
->surface_desc
.dwWidth
&&
6044 src_level
->surface_desc
.dwHeight
== dest_level
->surface_desc
.dwHeight
)
6048 ddsd
.ddsCaps
.dwCaps
= DDSCAPS_TEXTURE
;
6049 ddsd
.ddsCaps
.dwCaps2
= DDSCAPS2_MIPMAPSUBLEVEL
;
6050 IDirectDrawSurface7_GetAttachedSurface(&dest_level
->IDirectDrawSurface7_iface
, &ddsd
.ddsCaps
, &temp
);
6052 if (dest_level
!= dest
) IDirectDrawSurface7_Release(&dest_level
->IDirectDrawSurface7_iface
);
6054 dest_level
= unsafe_impl_from_IDirectDrawSurface7(temp
);
6057 ddsd
.ddsCaps
.dwCaps
= DDSCAPS_TEXTURE
;
6058 ddsd
.ddsCaps
.dwCaps2
= DDSCAPS2_MIPMAPSUBLEVEL
;
6059 IDirectDrawSurface7_GetAttachedSurface(&src_level
->IDirectDrawSurface7_iface
, &ddsd
.ddsCaps
, &temp
);
6061 if (src_level
!= src
) IDirectDrawSurface7_Release(&src_level
->IDirectDrawSurface7_iface
);
6063 src_level
= unsafe_impl_from_IDirectDrawSurface7(temp
);
6066 if (src_level
&& src_level
!= src
) IDirectDrawSurface7_Release(&src_level
->IDirectDrawSurface7_iface
);
6067 if (dest_level
&& dest_level
!= dest
) IDirectDrawSurface7_Release(&dest_level
->IDirectDrawSurface7_iface
);
6069 return !dest_level
&& levelFound
;
6072 static void copy_mipmap_chain(struct d3d_device
*device
, struct ddraw_surface
*dst
,
6073 struct ddraw_surface
*src
, const POINT
*DestPoint
, const RECT
*SrcRect
)
6075 struct ddraw_surface
*dst_level
, *src_level
;
6076 IDirectDrawSurface7
*temp
;
6077 DDSURFACEDESC2 ddsd
;
6081 IDirectDrawPalette
*pal
= NULL
, *pal_src
= NULL
;
6085 /* Copy palette, if possible. */
6086 IDirectDrawSurface7_GetPalette(&src
->IDirectDrawSurface7_iface
, &pal_src
);
6087 IDirectDrawSurface7_GetPalette(&dst
->IDirectDrawSurface7_iface
, &pal
);
6089 if (pal_src
!= NULL
&& pal
!= NULL
)
6091 PALETTEENTRY palent
[256];
6093 IDirectDrawPalette_GetEntries(pal_src
, 0, 0, 256, palent
);
6094 IDirectDrawPalette_SetEntries(pal
, 0, 0, 256, palent
);
6097 if (pal
) IDirectDrawPalette_Release(pal
);
6098 if (pal_src
) IDirectDrawPalette_Release(pal_src
);
6100 /* Copy colorkeys, if present. */
6101 for (ckeyflag
= DDCKEY_DESTBLT
; ckeyflag
<= DDCKEY_SRCOVERLAY
; ckeyflag
<<= 1)
6103 hr
= IDirectDrawSurface7_GetColorKey(&src
->IDirectDrawSurface7_iface
, ckeyflag
, &ddckey
);
6107 IDirectDrawSurface7_SetColorKey(&dst
->IDirectDrawSurface7_iface
, ckeyflag
, &ddckey
);
6115 src_rect
= *SrcRect
;
6117 for (;src_level
&& dst_level
;)
6119 if (src_level
->surface_desc
.dwWidth
== dst_level
->surface_desc
.dwWidth
6120 && src_level
->surface_desc
.dwHeight
== dst_level
->surface_desc
.dwHeight
)
6122 UINT src_w
= src_rect
.right
- src_rect
.left
;
6123 UINT src_h
= src_rect
.bottom
- src_rect
.top
;
6124 RECT dst_rect
= {point
.x
, point
.y
, point
.x
+ src_w
, point
.y
+ src_h
};
6126 if (FAILED(hr
= wined3d_texture_blt(dst_level
->wined3d_texture
, dst_level
->sub_resource_idx
, &dst_rect
,
6127 src_level
->wined3d_texture
, src_level
->sub_resource_idx
, &src_rect
, 0, NULL
, WINED3D_TEXF_POINT
)))
6128 ERR("Blit failed, hr %#x.\n", hr
);
6130 ddsd
.ddsCaps
.dwCaps
= DDSCAPS_TEXTURE
;
6131 ddsd
.ddsCaps
.dwCaps2
= DDSCAPS2_MIPMAPSUBLEVEL
;
6132 IDirectDrawSurface7_GetAttachedSurface(&dst_level
->IDirectDrawSurface7_iface
, &ddsd
.ddsCaps
, &temp
);
6134 if (dst_level
!= dst
)
6135 IDirectDrawSurface7_Release(&dst_level
->IDirectDrawSurface7_iface
);
6137 dst_level
= unsafe_impl_from_IDirectDrawSurface7(temp
);
6140 ddsd
.ddsCaps
.dwCaps
= DDSCAPS_TEXTURE
;
6141 ddsd
.ddsCaps
.dwCaps2
= DDSCAPS2_MIPMAPSUBLEVEL
;
6142 IDirectDrawSurface7_GetAttachedSurface(&src_level
->IDirectDrawSurface7_iface
, &ddsd
.ddsCaps
, &temp
);
6144 if (src_level
!= src
) IDirectDrawSurface7_Release(&src_level
->IDirectDrawSurface7_iface
);
6146 src_level
= unsafe_impl_from_IDirectDrawSurface7(temp
);
6153 src_rect
.right
= (src_rect
.right
+ 1) / 2;
6154 src_rect
.bottom
= (src_rect
.bottom
+ 1) / 2;
6157 if (src_level
&& src_level
!= src
)
6158 IDirectDrawSurface7_Release(&src_level
->IDirectDrawSurface7_iface
);
6159 if (dst_level
&& dst_level
!= dst
)
6160 IDirectDrawSurface7_Release(&dst_level
->IDirectDrawSurface7_iface
);
6163 /*****************************************************************************
6164 * IDirect3DDevice7::Load
6166 * Loads a rectangular area from the source into the destination texture.
6167 * It can also copy the source to the faces of a cubic environment map
6172 * DestTex: Destination texture
6173 * DestPoint: Point in the destination where the source image should be
6175 * SrcTex: Source texture
6176 * SrcRect: Source rectangle
6177 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6178 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6179 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6183 * DDERR_INVALIDPARAMS if dst_texture or src_texture is NULL, broken coordinates or anything unexpected.
6186 *****************************************************************************/
6187 static HRESULT
d3d_device7_Load(IDirect3DDevice7
*iface
, IDirectDrawSurface7
*dst_texture
, POINT
*dst_pos
,
6188 IDirectDrawSurface7
*src_texture
, RECT
*src_rect
, DWORD flags
)
6190 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
6191 struct ddraw_surface
*dest
= unsafe_impl_from_IDirectDrawSurface7(dst_texture
);
6192 struct ddraw_surface
*src
= unsafe_impl_from_IDirectDrawSurface7(src_texture
);
6196 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6197 iface
, dst_texture
, wine_dbgstr_point(dst_pos
), src_texture
, wine_dbgstr_rect(src_rect
), flags
);
6199 if( (!src
) || (!dest
) )
6200 return DDERR_INVALIDPARAMS
;
6202 wined3d_mutex_lock();
6205 SetRect(&srcrect
, 0, 0, src
->surface_desc
.dwWidth
, src
->surface_desc
.dwHeight
);
6207 srcrect
= *src_rect
;
6210 destpoint
.x
= destpoint
.y
= 0;
6212 destpoint
= *dst_pos
;
6214 /* Check bad dimensions. dst_pos is validated against src, not dest, because
6215 * destination can be a subset of mip levels, in which case actual coordinates used
6216 * for it may be divided. If any dimension of dest is larger than source, it can't be
6217 * mip level subset, so an error can be returned early.
6219 if (IsRectEmpty(&srcrect
) || srcrect
.right
> src
->surface_desc
.dwWidth
||
6220 srcrect
.bottom
> src
->surface_desc
.dwHeight
||
6221 destpoint
.x
+ srcrect
.right
- srcrect
.left
> src
->surface_desc
.dwWidth
||
6222 destpoint
.y
+ srcrect
.bottom
- srcrect
.top
> src
->surface_desc
.dwHeight
||
6223 dest
->surface_desc
.dwWidth
> src
->surface_desc
.dwWidth
||
6224 dest
->surface_desc
.dwHeight
> src
->surface_desc
.dwHeight
)
6226 wined3d_mutex_unlock();
6227 return DDERR_INVALIDPARAMS
;
6230 /* Must be top level surfaces. */
6231 if (src
->surface_desc
.ddsCaps
.dwCaps2
& DDSCAPS2_MIPMAPSUBLEVEL
||
6232 dest
->surface_desc
.ddsCaps
.dwCaps2
& DDSCAPS2_MIPMAPSUBLEVEL
)
6234 wined3d_mutex_unlock();
6235 return DDERR_INVALIDPARAMS
;
6238 if (src
->surface_desc
.ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP
)
6240 struct ddraw_surface
*src_face
, *dest_face
;
6241 DWORD src_face_flag
, dest_face_flag
;
6242 IDirectDrawSurface7
*temp
;
6243 DDSURFACEDESC2 ddsd
;
6246 if (!(dest
->surface_desc
.ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP
))
6248 wined3d_mutex_unlock();
6249 return DDERR_INVALIDPARAMS
;
6252 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6253 * time it's actual surface loading. */
6254 for (i
= 0; i
< 2; i
++)
6259 for (;dest_face
&& src_face
;)
6261 src_face_flag
= src_face
->surface_desc
.ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP_ALLFACES
;
6262 dest_face_flag
= dest_face
->surface_desc
.ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP_ALLFACES
;
6264 if (src_face_flag
== dest_face_flag
)
6268 /* Destination mip levels must be subset of source mip levels. */
6269 if (!is_mip_level_subset(dest_face
, src_face
))
6271 wined3d_mutex_unlock();
6272 return DDERR_INVALIDPARAMS
;
6275 else if (flags
& dest_face_flag
)
6277 copy_mipmap_chain(device
, dest_face
, src_face
, &destpoint
, &srcrect
);
6280 if (src_face_flag
< DDSCAPS2_CUBEMAP_NEGATIVEZ
)
6282 ddsd
.ddsCaps
.dwCaps
= DDSCAPS_TEXTURE
;
6283 ddsd
.ddsCaps
.dwCaps2
= DDSCAPS2_CUBEMAP
| (src_face_flag
<< 1);
6284 IDirectDrawSurface7_GetAttachedSurface(&src
->IDirectDrawSurface7_iface
, &ddsd
.ddsCaps
, &temp
);
6286 if (src_face
!= src
) IDirectDrawSurface7_Release(&src_face
->IDirectDrawSurface7_iface
);
6288 src_face
= unsafe_impl_from_IDirectDrawSurface7(temp
);
6292 if (src_face
!= src
) IDirectDrawSurface7_Release(&src_face
->IDirectDrawSurface7_iface
);
6298 if (dest_face_flag
< DDSCAPS2_CUBEMAP_NEGATIVEZ
)
6300 ddsd
.ddsCaps
.dwCaps
= DDSCAPS_TEXTURE
;
6301 ddsd
.ddsCaps
.dwCaps2
= DDSCAPS2_CUBEMAP
| (dest_face_flag
<< 1);
6302 IDirectDrawSurface7_GetAttachedSurface(&dest
->IDirectDrawSurface7_iface
, &ddsd
.ddsCaps
, &temp
);
6304 if (dest_face
!= dest
) IDirectDrawSurface7_Release(&dest_face
->IDirectDrawSurface7_iface
);
6306 dest_face
= unsafe_impl_from_IDirectDrawSurface7(temp
);
6310 if (dest_face
!= dest
) IDirectDrawSurface7_Release(&dest_face
->IDirectDrawSurface7_iface
);
6318 /* Native returns error if src faces are not subset of dest faces. */
6321 wined3d_mutex_unlock();
6322 return DDERR_INVALIDPARAMS
;
6327 wined3d_mutex_unlock();
6330 else if (dest
->surface_desc
.ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP
)
6332 wined3d_mutex_unlock();
6333 return DDERR_INVALIDPARAMS
;
6336 /* Handle non cube map textures. */
6338 /* Destination mip levels must be subset of source mip levels. */
6339 if (!is_mip_level_subset(dest
, src
))
6341 wined3d_mutex_unlock();
6342 return DDERR_INVALIDPARAMS
;
6345 copy_mipmap_chain(device
, dest
, src
, &destpoint
, &srcrect
);
6347 wined3d_mutex_unlock();
6352 static HRESULT WINAPI
d3d_device7_Load_FPUSetup(IDirect3DDevice7
*iface
, IDirectDrawSurface7
*dst_texture
,
6353 POINT
*dst_pos
, IDirectDrawSurface7
*src_texture
, RECT
*src_rect
, DWORD flags
)
6355 return d3d_device7_Load(iface
, dst_texture
, dst_pos
, src_texture
, src_rect
, flags
);
6358 static HRESULT WINAPI
d3d_device7_Load_FPUPreserve(IDirect3DDevice7
*iface
, IDirectDrawSurface7
*dst_texture
,
6359 POINT
*dst_pos
, IDirectDrawSurface7
*src_texture
, RECT
*src_rect
, DWORD flags
)
6364 old_fpucw
= d3d_fpu_setup();
6365 hr
= d3d_device7_Load(iface
, dst_texture
, dst_pos
, src_texture
, src_rect
, flags
);
6366 set_fpu_control_word(old_fpucw
);
6371 /*****************************************************************************
6372 * IDirect3DDevice7::LightEnable
6374 * Enables or disables a light
6376 * Version 7, IDirect3DLight uses this method too.
6379 * LightIndex: The index of the light to enable / disable
6380 * Enable: Enable or disable the light
6385 *****************************************************************************/
6386 static HRESULT
d3d_device7_LightEnable(IDirect3DDevice7
*iface
, DWORD light_idx
, BOOL enabled
)
6388 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
6391 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface
, light_idx
, enabled
);
6393 wined3d_mutex_lock();
6394 hr
= wined3d_stateblock_set_light_enable(device
->update_state
, light_idx
, enabled
);
6395 wined3d_mutex_unlock();
6397 return hr_ddraw_from_wined3d(hr
);
6400 static HRESULT WINAPI
d3d_device7_LightEnable_FPUSetup(IDirect3DDevice7
*iface
, DWORD light_idx
, BOOL enabled
)
6402 return d3d_device7_LightEnable(iface
, light_idx
, enabled
);
6405 static HRESULT WINAPI
d3d_device7_LightEnable_FPUPreserve(IDirect3DDevice7
*iface
, DWORD light_idx
, BOOL enabled
)
6410 old_fpucw
= d3d_fpu_setup();
6411 hr
= d3d_device7_LightEnable(iface
, light_idx
, enabled
);
6412 set_fpu_control_word(old_fpucw
);
6417 /*****************************************************************************
6418 * IDirect3DDevice7::GetLightEnable
6420 * Retrieves if the light with the given index is enabled or not
6425 * LightIndex: Index of desired light
6426 * Enable: Pointer to a BOOL which contains the result
6430 * DDERR_INVALIDPARAMS if Enable is NULL
6432 *****************************************************************************/
6433 static HRESULT
d3d_device7_GetLightEnable(IDirect3DDevice7
*iface
, DWORD light_idx
, BOOL
*enabled
)
6435 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
6436 struct wined3d_light light
;
6439 TRACE("iface %p, light_idx %u, enabled %p.\n", iface
, light_idx
, enabled
);
6442 return DDERR_INVALIDPARAMS
;
6444 wined3d_mutex_lock();
6445 hr
= wined3d_stateblock_get_light(device
->state
, light_idx
, &light
, enabled
);
6446 wined3d_mutex_unlock();
6448 return hr_ddraw_from_wined3d(hr
);
6451 static HRESULT WINAPI
d3d_device7_GetLightEnable_FPUSetup(IDirect3DDevice7
*iface
, DWORD light_idx
, BOOL
*enabled
)
6453 return d3d_device7_GetLightEnable(iface
, light_idx
, enabled
);
6456 static HRESULT WINAPI
d3d_device7_GetLightEnable_FPUPreserve(IDirect3DDevice7
*iface
, DWORD light_idx
, BOOL
*enabled
)
6461 old_fpucw
= d3d_fpu_setup();
6462 hr
= d3d_device7_GetLightEnable(iface
, light_idx
, enabled
);
6463 set_fpu_control_word(old_fpucw
);
6468 /*****************************************************************************
6469 * IDirect3DDevice7::SetClipPlane
6471 * Sets custom clipping plane
6476 * Index: The index of the clipping plane
6477 * PlaneEquation: An equation defining the clipping plane
6481 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6483 *****************************************************************************/
6484 static HRESULT
d3d_device7_SetClipPlane(IDirect3DDevice7
*iface
, DWORD idx
, D3DVALUE
*plane
)
6486 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
6487 const struct wined3d_vec4
*wined3d_plane
;
6490 TRACE("iface %p, idx %u, plane %p.\n", iface
, idx
, plane
);
6493 return DDERR_INVALIDPARAMS
;
6495 wined3d_plane
= (struct wined3d_vec4
*)plane
;
6497 wined3d_mutex_lock();
6498 hr
= wined3d_stateblock_set_clip_plane(device
->update_state
, idx
, wined3d_plane
);
6499 if (idx
< ARRAY_SIZE(device
->user_clip_planes
))
6501 device
->user_clip_planes
[idx
] = *wined3d_plane
;
6502 if (hr
== WINED3DERR_INVALIDCALL
)
6504 WARN("Clip plane %u is not supported.\n", idx
);
6508 wined3d_mutex_unlock();
6513 static HRESULT WINAPI
d3d_device7_SetClipPlane_FPUSetup(IDirect3DDevice7
*iface
, DWORD idx
, D3DVALUE
*plane
)
6515 return d3d_device7_SetClipPlane(iface
, idx
, plane
);
6518 static HRESULT WINAPI
d3d_device7_SetClipPlane_FPUPreserve(IDirect3DDevice7
*iface
, DWORD idx
, D3DVALUE
*plane
)
6523 old_fpucw
= d3d_fpu_setup();
6524 hr
= d3d_device7_SetClipPlane(iface
, idx
, plane
);
6525 set_fpu_control_word(old_fpucw
);
6530 /*****************************************************************************
6531 * IDirect3DDevice7::GetClipPlane
6533 * Returns the clipping plane with a specific index
6536 * Index: The index of the desired plane
6537 * PlaneEquation: Address to store the plane equation to
6541 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6543 *****************************************************************************/
6544 static HRESULT
d3d_device7_GetClipPlane(IDirect3DDevice7
*iface
, DWORD idx
, D3DVALUE
*plane
)
6546 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
6548 TRACE("iface %p, idx %u, plane %p.\n", iface
, idx
, plane
);
6551 return DDERR_INVALIDPARAMS
;
6553 wined3d_mutex_lock();
6554 if (idx
< WINED3D_MAX_CLIP_DISTANCES
)
6555 memcpy(plane
, &device
->stateblock_state
->clip_planes
[idx
], sizeof(struct wined3d_vec4
));
6558 WARN("Clip plane %u is not supported.\n", idx
);
6559 if (idx
< ARRAY_SIZE(device
->user_clip_planes
))
6560 memcpy(plane
, &device
->user_clip_planes
[idx
], sizeof(struct wined3d_vec4
));
6562 wined3d_mutex_unlock();
6567 static HRESULT WINAPI
d3d_device7_GetClipPlane_FPUSetup(IDirect3DDevice7
*iface
, DWORD idx
, D3DVALUE
*plane
)
6569 return d3d_device7_GetClipPlane(iface
, idx
, plane
);
6572 static HRESULT WINAPI
d3d_device7_GetClipPlane_FPUPreserve(IDirect3DDevice7
*iface
, DWORD idx
, D3DVALUE
*plane
)
6577 old_fpucw
= d3d_fpu_setup();
6578 hr
= d3d_device7_GetClipPlane(iface
, idx
, plane
);
6579 set_fpu_control_word(old_fpucw
);
6584 /*****************************************************************************
6585 * IDirect3DDevice7::GetInfo
6587 * Retrieves some information about the device. The DirectX sdk says that
6588 * this version returns S_FALSE for all retail builds of DirectX, that's what
6589 * this implementation does.
6592 * DevInfoID: Information type requested
6593 * DevInfoStruct: Pointer to a structure to store the info to
6594 * Size: Size of the structure
6597 * S_FALSE, because it's a non-debug driver
6599 *****************************************************************************/
6600 static HRESULT WINAPI
d3d_device7_GetInfo(IDirect3DDevice7
*iface
, DWORD info_id
, void *info
, DWORD info_size
)
6602 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6603 iface
, info_id
, info
, info_size
);
6605 if (TRACE_ON(ddraw
))
6607 TRACE(" info requested : ");
6610 case D3DDEVINFOID_TEXTUREMANAGER
: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6611 case D3DDEVINFOID_D3DTEXTUREMANAGER
: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6612 case D3DDEVINFOID_TEXTURING
: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6613 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS
;
6617 return S_FALSE
; /* According to MSDN, this is valid for a non-debug driver */
6620 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6621 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6622 * are not duplicated.
6624 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6625 * has already been setup for optimal d3d operation.
6627 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6628 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6629 * by Sacrifice (game). */
6630 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl
=
6632 /*** IUnknown Methods ***/
6633 d3d_device7_QueryInterface
,
6635 d3d_device7_Release
,
6636 /*** IDirect3DDevice7 ***/
6637 d3d_device7_GetCaps_FPUSetup
,
6638 d3d_device7_EnumTextureFormats_FPUSetup
,
6639 d3d_device7_BeginScene_FPUSetup
,
6640 d3d_device7_EndScene_FPUSetup
,
6641 d3d_device7_GetDirect3D
,
6642 d3d_device7_SetRenderTarget_FPUSetup
,
6643 d3d_device7_GetRenderTarget
,
6644 d3d_device7_Clear_FPUSetup
,
6645 d3d_device7_SetTransform_FPUSetup
,
6646 d3d_device7_GetTransform_FPUSetup
,
6647 d3d_device7_SetViewport_FPUSetup
,
6648 d3d_device7_MultiplyTransform_FPUSetup
,
6649 d3d_device7_GetViewport_FPUSetup
,
6650 d3d_device7_SetMaterial_FPUSetup
,
6651 d3d_device7_GetMaterial_FPUSetup
,
6652 d3d_device7_SetLight_FPUSetup
,
6653 d3d_device7_GetLight_FPUSetup
,
6654 d3d_device7_SetRenderState_FPUSetup
,
6655 d3d_device7_GetRenderState_FPUSetup
,
6656 d3d_device7_BeginStateBlock_FPUSetup
,
6657 d3d_device7_EndStateBlock_FPUSetup
,
6658 d3d_device7_PreLoad_FPUSetup
,
6659 d3d_device7_DrawPrimitive_FPUSetup
,
6660 d3d_device7_DrawIndexedPrimitive_FPUSetup
,
6661 d3d_device7_SetClipStatus
,
6662 d3d_device7_GetClipStatus
,
6663 d3d_device7_DrawPrimitiveStrided_FPUSetup
,
6664 d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup
,
6665 d3d_device7_DrawPrimitiveVB_FPUSetup
,
6666 d3d_device7_DrawIndexedPrimitiveVB_FPUSetup
,
6667 d3d_device7_ComputeSphereVisibility
,
6668 d3d_device7_GetTexture_FPUSetup
,
6669 d3d_device7_SetTexture_FPUSetup
,
6670 d3d_device7_GetTextureStageState_FPUSetup
,
6671 d3d_device7_SetTextureStageState_FPUSetup
,
6672 d3d_device7_ValidateDevice_FPUSetup
,
6673 d3d_device7_ApplyStateBlock_FPUSetup
,
6674 d3d_device7_CaptureStateBlock_FPUSetup
,
6675 d3d_device7_DeleteStateBlock_FPUSetup
,
6676 d3d_device7_CreateStateBlock_FPUSetup
,
6677 d3d_device7_Load_FPUSetup
,
6678 d3d_device7_LightEnable_FPUSetup
,
6679 d3d_device7_GetLightEnable_FPUSetup
,
6680 d3d_device7_SetClipPlane_FPUSetup
,
6681 d3d_device7_GetClipPlane_FPUSetup
,
6685 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl
=
6687 /*** IUnknown Methods ***/
6688 d3d_device7_QueryInterface
,
6690 d3d_device7_Release
,
6691 /*** IDirect3DDevice7 ***/
6692 d3d_device7_GetCaps_FPUPreserve
,
6693 d3d_device7_EnumTextureFormats_FPUPreserve
,
6694 d3d_device7_BeginScene_FPUPreserve
,
6695 d3d_device7_EndScene_FPUPreserve
,
6696 d3d_device7_GetDirect3D
,
6697 d3d_device7_SetRenderTarget_FPUPreserve
,
6698 d3d_device7_GetRenderTarget
,
6699 d3d_device7_Clear_FPUPreserve
,
6700 d3d_device7_SetTransform_FPUPreserve
,
6701 d3d_device7_GetTransform_FPUPreserve
,
6702 d3d_device7_SetViewport_FPUPreserve
,
6703 d3d_device7_MultiplyTransform_FPUPreserve
,
6704 d3d_device7_GetViewport_FPUPreserve
,
6705 d3d_device7_SetMaterial_FPUPreserve
,
6706 d3d_device7_GetMaterial_FPUPreserve
,
6707 d3d_device7_SetLight_FPUPreserve
,
6708 d3d_device7_GetLight_FPUPreserve
,
6709 d3d_device7_SetRenderState_FPUPreserve
,
6710 d3d_device7_GetRenderState_FPUPreserve
,
6711 d3d_device7_BeginStateBlock_FPUPreserve
,
6712 d3d_device7_EndStateBlock_FPUPreserve
,
6713 d3d_device7_PreLoad_FPUPreserve
,
6714 d3d_device7_DrawPrimitive_FPUPreserve
,
6715 d3d_device7_DrawIndexedPrimitive_FPUPreserve
,
6716 d3d_device7_SetClipStatus
,
6717 d3d_device7_GetClipStatus
,
6718 d3d_device7_DrawPrimitiveStrided_FPUPreserve
,
6719 d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve
,
6720 d3d_device7_DrawPrimitiveVB_FPUPreserve
,
6721 d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve
,
6722 d3d_device7_ComputeSphereVisibility
,
6723 d3d_device7_GetTexture_FPUPreserve
,
6724 d3d_device7_SetTexture_FPUPreserve
,
6725 d3d_device7_GetTextureStageState_FPUPreserve
,
6726 d3d_device7_SetTextureStageState_FPUPreserve
,
6727 d3d_device7_ValidateDevice_FPUPreserve
,
6728 d3d_device7_ApplyStateBlock_FPUPreserve
,
6729 d3d_device7_CaptureStateBlock_FPUPreserve
,
6730 d3d_device7_DeleteStateBlock_FPUPreserve
,
6731 d3d_device7_CreateStateBlock_FPUPreserve
,
6732 d3d_device7_Load_FPUPreserve
,
6733 d3d_device7_LightEnable_FPUPreserve
,
6734 d3d_device7_GetLightEnable_FPUPreserve
,
6735 d3d_device7_SetClipPlane_FPUPreserve
,
6736 d3d_device7_GetClipPlane_FPUPreserve
,
6740 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl
=
6742 /*** IUnknown Methods ***/
6743 d3d_device3_QueryInterface
,
6745 d3d_device3_Release
,
6746 /*** IDirect3DDevice3 ***/
6747 d3d_device3_GetCaps
,
6748 d3d_device3_GetStats
,
6749 d3d_device3_AddViewport
,
6750 d3d_device3_DeleteViewport
,
6751 d3d_device3_NextViewport
,
6752 d3d_device3_EnumTextureFormats
,
6753 d3d_device3_BeginScene
,
6754 d3d_device3_EndScene
,
6755 d3d_device3_GetDirect3D
,
6756 d3d_device3_SetCurrentViewport
,
6757 d3d_device3_GetCurrentViewport
,
6758 d3d_device3_SetRenderTarget
,
6759 d3d_device3_GetRenderTarget
,
6761 d3d_device3_BeginIndexed
,
6765 d3d_device3_GetRenderState
,
6766 d3d_device3_SetRenderState
,
6767 d3d_device3_GetLightState
,
6768 d3d_device3_SetLightState
,
6769 d3d_device3_SetTransform
,
6770 d3d_device3_GetTransform
,
6771 d3d_device3_MultiplyTransform
,
6772 d3d_device3_DrawPrimitive
,
6773 d3d_device3_DrawIndexedPrimitive
,
6774 d3d_device3_SetClipStatus
,
6775 d3d_device3_GetClipStatus
,
6776 d3d_device3_DrawPrimitiveStrided
,
6777 d3d_device3_DrawIndexedPrimitiveStrided
,
6778 d3d_device3_DrawPrimitiveVB
,
6779 d3d_device3_DrawIndexedPrimitiveVB
,
6780 d3d_device3_ComputeSphereVisibility
,
6781 d3d_device3_GetTexture
,
6782 d3d_device3_SetTexture
,
6783 d3d_device3_GetTextureStageState
,
6784 d3d_device3_SetTextureStageState
,
6785 d3d_device3_ValidateDevice
6788 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl
=
6790 /*** IUnknown Methods ***/
6791 d3d_device2_QueryInterface
,
6793 d3d_device2_Release
,
6794 /*** IDirect3DDevice2 ***/
6795 d3d_device2_GetCaps
,
6796 d3d_device2_SwapTextureHandles
,
6797 d3d_device2_GetStats
,
6798 d3d_device2_AddViewport
,
6799 d3d_device2_DeleteViewport
,
6800 d3d_device2_NextViewport
,
6801 d3d_device2_EnumTextureFormats
,
6802 d3d_device2_BeginScene
,
6803 d3d_device2_EndScene
,
6804 d3d_device2_GetDirect3D
,
6805 d3d_device2_SetCurrentViewport
,
6806 d3d_device2_GetCurrentViewport
,
6807 d3d_device2_SetRenderTarget
,
6808 d3d_device2_GetRenderTarget
,
6810 d3d_device2_BeginIndexed
,
6814 d3d_device2_GetRenderState
,
6815 d3d_device2_SetRenderState
,
6816 d3d_device2_GetLightState
,
6817 d3d_device2_SetLightState
,
6818 d3d_device2_SetTransform
,
6819 d3d_device2_GetTransform
,
6820 d3d_device2_MultiplyTransform
,
6821 d3d_device2_DrawPrimitive
,
6822 d3d_device2_DrawIndexedPrimitive
,
6823 d3d_device2_SetClipStatus
,
6824 d3d_device2_GetClipStatus
6827 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl
=
6829 /*** IUnknown Methods ***/
6830 d3d_device1_QueryInterface
,
6832 d3d_device1_Release
,
6833 /*** IDirect3DDevice1 ***/
6834 d3d_device1_Initialize
,
6835 d3d_device1_GetCaps
,
6836 d3d_device1_SwapTextureHandles
,
6837 d3d_device1_CreateExecuteBuffer
,
6838 d3d_device1_GetStats
,
6839 d3d_device1_Execute
,
6840 d3d_device1_AddViewport
,
6841 d3d_device1_DeleteViewport
,
6842 d3d_device1_NextViewport
,
6844 d3d_device1_GetPickRecords
,
6845 d3d_device1_EnumTextureFormats
,
6846 d3d_device1_CreateMatrix
,
6847 d3d_device1_SetMatrix
,
6848 d3d_device1_GetMatrix
,
6849 d3d_device1_DeleteMatrix
,
6850 d3d_device1_BeginScene
,
6851 d3d_device1_EndScene
,
6852 d3d_device1_GetDirect3D
6855 static const struct IUnknownVtbl d3d_device_inner_vtbl
=
6857 d3d_device_inner_QueryInterface
,
6858 d3d_device_inner_AddRef
,
6859 d3d_device_inner_Release
,
6862 struct d3d_device
*unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7
*iface
)
6864 if (!iface
) return NULL
;
6865 assert((iface
->lpVtbl
== &d3d_device7_fpu_preserve_vtbl
) || (iface
->lpVtbl
== &d3d_device7_fpu_setup_vtbl
));
6866 return CONTAINING_RECORD(iface
, struct d3d_device
, IDirect3DDevice7_iface
);
6869 struct d3d_device
*unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3
*iface
)
6871 if (!iface
) return NULL
;
6872 assert(iface
->lpVtbl
== &d3d_device3_vtbl
);
6873 return CONTAINING_RECORD(iface
, struct d3d_device
, IDirect3DDevice3_iface
);
6876 struct d3d_device
*unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2
*iface
)
6878 if (!iface
) return NULL
;
6879 assert(iface
->lpVtbl
== &d3d_device2_vtbl
);
6880 return CONTAINING_RECORD(iface
, struct d3d_device
, IDirect3DDevice2_iface
);
6883 struct d3d_device
*unsafe_impl_from_IDirect3DDevice(IDirect3DDevice
*iface
)
6885 if (!iface
) return NULL
;
6886 assert(iface
->lpVtbl
== &d3d_device1_vtbl
);
6887 return CONTAINING_RECORD(iface
, struct d3d_device
, IDirect3DDevice_iface
);
6890 enum wined3d_depth_buffer_type
d3d_device_update_depth_stencil(struct d3d_device
*device
)
6892 IDirectDrawSurface7
*depthStencil
= NULL
;
6893 IDirectDrawSurface7
*render_target
;
6894 static DDSCAPS2 depthcaps
= { DDSCAPS_ZBUFFER
, 0, 0, {0} };
6895 struct ddraw_surface
*dsi
;
6897 if (device
->rt_iface
&& SUCCEEDED(IUnknown_QueryInterface(device
->rt_iface
,
6898 &IID_IDirectDrawSurface7
, (void **)&render_target
)))
6900 IDirectDrawSurface7_GetAttachedSurface(render_target
, &depthcaps
, &depthStencil
);
6901 IDirectDrawSurface7_Release(render_target
);
6905 TRACE("Setting wined3d depth stencil to NULL\n");
6906 wined3d_device_set_depth_stencil_view(device
->wined3d_device
, NULL
);
6907 return WINED3D_ZB_FALSE
;
6910 dsi
= impl_from_IDirectDrawSurface7(depthStencil
);
6911 wined3d_device_set_depth_stencil_view(device
->wined3d_device
,
6912 ddraw_surface_get_rendertarget_view(dsi
));
6914 IDirectDrawSurface7_Release(depthStencil
);
6915 return WINED3D_ZB_TRUE
;
6918 static void ddraw_reset_viewport_state(struct ddraw
*ddraw
)
6920 struct wined3d_viewport vp
;
6923 wined3d_device_get_viewports(ddraw
->wined3d_device
, NULL
, &vp
);
6924 wined3d_stateblock_set_viewport(ddraw
->state
, &vp
);
6925 wined3d_device_get_scissor_rects(ddraw
->wined3d_device
, NULL
, &rect
);
6926 wined3d_stateblock_set_scissor_rect(ddraw
->state
, &rect
);
6929 static HRESULT
d3d_device_init(struct d3d_device
*device
, struct ddraw
*ddraw
,
6930 struct ddraw_surface
*target
, IUnknown
*rt_iface
, UINT version
, IUnknown
*outer_unknown
)
6932 static const struct wined3d_matrix ident
=
6934 1.0f
, 0.0f
, 0.0f
, 0.0f
,
6935 0.0f
, 1.0f
, 0.0f
, 0.0f
,
6936 0.0f
, 0.0f
, 1.0f
, 0.0f
,
6937 0.0f
, 0.0f
, 0.0f
, 1.0f
,
6941 if (ddraw
->cooperative_level
& DDSCL_FPUPRESERVE
)
6942 device
->IDirect3DDevice7_iface
.lpVtbl
= &d3d_device7_fpu_preserve_vtbl
;
6944 device
->IDirect3DDevice7_iface
.lpVtbl
= &d3d_device7_fpu_setup_vtbl
;
6946 device
->IDirect3DDevice3_iface
.lpVtbl
= &d3d_device3_vtbl
;
6947 device
->IDirect3DDevice2_iface
.lpVtbl
= &d3d_device2_vtbl
;
6948 device
->IDirect3DDevice_iface
.lpVtbl
= &d3d_device1_vtbl
;
6949 device
->IUnknown_inner
.lpVtbl
= &d3d_device_inner_vtbl
;
6951 device
->version
= version
;
6954 device
->outer_unknown
= outer_unknown
;
6956 device
->outer_unknown
= &device
->IUnknown_inner
;
6958 device
->ddraw
= ddraw
;
6959 list_init(&device
->viewport_list
);
6961 if (!ddraw_handle_table_init(&device
->handle_table
, 64))
6963 ERR("Failed to initialize handle table.\n");
6964 return DDERR_OUTOFMEMORY
;
6967 device
->legacyTextureBlending
= FALSE
;
6968 device
->legacy_projection
= ident
;
6969 device
->legacy_clipspace
= ident
;
6971 /* This is for convenience. */
6972 device
->wined3d_device
= ddraw
->wined3d_device
;
6973 wined3d_device_incref(ddraw
->wined3d_device
);
6974 device
->update_state
= device
->state
= ddraw
->state
;
6975 device
->stateblock_state
= ddraw
->stateblock_state
;
6976 wined3d_stateblock_incref(ddraw
->state
);
6978 /* Render to the back buffer */
6979 if (FAILED(hr
= wined3d_device_set_rendertarget_view(ddraw
->wined3d_device
,
6980 0, ddraw_surface_get_rendertarget_view(target
), TRUE
)))
6982 ERR("Failed to set render target, hr %#x.\n", hr
);
6983 wined3d_stateblock_decref(device
->state
);
6984 ddraw_handle_table_destroy(&device
->handle_table
);
6988 device
->rt_iface
= rt_iface
;
6990 IUnknown_AddRef(device
->rt_iface
);
6992 ddraw
->d3ddevice
= device
;
6994 wined3d_stateblock_set_render_state(ddraw
->state
, WINED3D_RS_ZENABLE
,
6995 d3d_device_update_depth_stencil(device
));
6996 if (version
== 1) /* Color keying is initially enabled for version 1 devices. */
6997 wined3d_stateblock_set_render_state(ddraw
->state
, WINED3D_RS_COLORKEYENABLE
, TRUE
);
6998 else if (version
== 2)
6999 wined3d_stateblock_set_render_state(ddraw
->state
, WINED3D_RS_SPECULARENABLE
, TRUE
);
7002 wined3d_stateblock_set_render_state(ddraw
->state
, WINED3D_RS_NORMALIZENORMALS
, TRUE
);
7003 IDirect3DDevice3_SetRenderState(&device
->IDirect3DDevice3_iface
,
7004 D3DRENDERSTATE_TEXTUREMAPBLEND
, D3DTBLEND_MODULATE
);
7006 ddraw_reset_viewport_state(ddraw
);
7010 HRESULT
d3d_device_create(struct ddraw
*ddraw
, struct ddraw_surface
*target
, IUnknown
*rt_iface
,
7011 UINT version
, struct d3d_device
**device
, IUnknown
*outer_unknown
)
7013 struct d3d_device
*object
;
7016 TRACE("ddraw %p, target %p, version %u, device %p, outer_unknown %p.\n",
7017 ddraw
, target
, version
, device
, outer_unknown
);
7019 if (!(target
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_3DDEVICE
)
7020 || (target
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_ZBUFFER
))
7022 WARN("Surface %p is not a render target.\n", target
);
7023 return DDERR_INVALIDCAPS
;
7026 if (!validate_surface_palette(target
))
7028 WARN("Surface %p has an indexed pixel format, but no palette.\n", target
);
7029 return DDERR_NOPALETTEATTACHED
;
7032 if (ddraw
->flags
& DDRAW_NO3D
)
7034 ERR_(winediag
)("The application wants to create a Direct3D device, "
7035 "but the current DirectDrawRenderer does not support this.\n");
7037 return DDERR_OUTOFMEMORY
;
7040 if (!(target
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_VIDEOMEMORY
))
7042 WARN("Surface %p is not in video memory.\n", target
);
7043 return D3DERR_SURFACENOTINVIDMEM
;
7046 if (ddraw
->d3ddevice
)
7048 FIXME("Only one Direct3D device per DirectDraw object supported.\n");
7049 return DDERR_INVALIDPARAMS
;
7052 if (!(object
= heap_alloc_zero(sizeof(*object
))))
7054 ERR("Failed to allocate device memory.\n");
7055 return DDERR_OUTOFMEMORY
;
7058 if (FAILED(hr
= d3d_device_init(object
, ddraw
, target
, rt_iface
, version
, outer_unknown
)))
7060 WARN("Failed to initialize device, hr %#x.\n", hr
);
7065 TRACE("Created device %p.\n", object
);