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
31 #include "wine/port.h"
33 #include "ddraw_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(ddraw
);
36 WINE_DECLARE_DEBUG_CHANNEL(winediag
);
39 const GUID IID_D3DDEVICE_WineD3D
= {
43 { 0xb7,0x98,0xc6,0x8a,0x77,0x2d,0x72,0x2a }
46 static inline void set_fpu_control_word(WORD fpucw
)
48 #if defined(__i386__) && defined(__GNUC__)
49 __asm__
volatile ("fldcw %0" : : "m" (fpucw
));
50 #elif defined(__i386__) && defined(_MSC_VER)
55 static inline WORD
d3d_fpu_setup(void)
59 #if defined(__i386__) && defined(__GNUC__)
60 __asm__
volatile ("fnstcw %0" : "=m" (oldcw
));
61 #elif defined(__i386__) && defined(_MSC_VER)
64 static BOOL warned
= FALSE
;
67 FIXME("FPUPRESERVE not implemented for this platform / compiler\n");
73 set_fpu_control_word(0x37f);
78 static inline struct d3d_device
*impl_from_IUnknown(IUnknown
*iface
)
80 return CONTAINING_RECORD(iface
, struct d3d_device
, IUnknown_inner
);
83 static HRESULT WINAPI
d3d_device_inner_QueryInterface(IUnknown
*iface
, REFIID riid
, void **out
)
85 struct d3d_device
*device
= impl_from_IUnknown(iface
);
87 TRACE("iface %p, riid %s, out %p.\n", iface
, debugstr_guid(riid
), out
);
92 return DDERR_INVALIDPARAMS
;
95 if (IsEqualGUID(&IID_IUnknown
, riid
))
97 IDirect3DDevice7_AddRef(&device
->IDirect3DDevice7_iface
);
98 *out
= &device
->IDirect3DDevice7_iface
;
102 if (device
->version
== 7)
104 if (IsEqualGUID(&IID_IDirect3DDevice7
, riid
))
106 IDirect3DDevice7_AddRef(&device
->IDirect3DDevice7_iface
);
107 *out
= &device
->IDirect3DDevice7_iface
;
113 if (IsEqualGUID(&IID_IDirect3DDevice3
, riid
) && device
->version
== 3)
115 IDirect3DDevice3_AddRef(&device
->IDirect3DDevice3_iface
);
116 *out
= &device
->IDirect3DDevice3_iface
;
120 if (IsEqualGUID(&IID_IDirect3DDevice2
, riid
) && device
->version
>= 2)
122 IDirect3DDevice2_AddRef(&device
->IDirect3DDevice2_iface
);
123 *out
= &device
->IDirect3DDevice2_iface
;
127 if (IsEqualGUID(&IID_IDirect3DDevice
, riid
))
129 IDirect3DDevice_AddRef(&device
->IDirect3DDevice_iface
);
130 *out
= &device
->IDirect3DDevice_iface
;
135 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid
));
138 return E_NOINTERFACE
;
141 static HRESULT WINAPI
d3d_device7_QueryInterface(IDirect3DDevice7
*iface
, REFIID riid
, void **out
)
143 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
145 TRACE("iface %p, riid %s, out %p.\n", iface
, debugstr_guid(riid
), out
);
147 return IUnknown_QueryInterface(device
->outer_unknown
, riid
, out
);
150 static HRESULT WINAPI
d3d_device3_QueryInterface(IDirect3DDevice3
*iface
, REFIID riid
, void **out
)
152 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
154 TRACE("iface %p, riid %s, out %p.\n", iface
, debugstr_guid(riid
), out
);
156 return IUnknown_QueryInterface(device
->outer_unknown
, riid
, out
);
159 static HRESULT WINAPI
d3d_device2_QueryInterface(IDirect3DDevice2
*iface
, REFIID riid
, void **out
)
161 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
163 TRACE("iface %p, riid %s, out %p.\n", iface
, debugstr_guid(riid
), out
);
165 return IUnknown_QueryInterface(device
->outer_unknown
, riid
, out
);
168 static HRESULT WINAPI
d3d_device1_QueryInterface(IDirect3DDevice
*iface
, REFIID riid
, void **out
)
170 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
172 TRACE("iface %p, riid %s, out %p.\n", iface
, debugstr_guid(riid
), out
);
174 return IUnknown_QueryInterface(device
->outer_unknown
, riid
, out
);
177 static ULONG WINAPI
d3d_device_inner_AddRef(IUnknown
*iface
)
179 struct d3d_device
*device
= impl_from_IUnknown(iface
);
180 ULONG ref
= InterlockedIncrement(&device
->ref
);
182 TRACE("%p increasing refcount to %u.\n", device
, ref
);
187 static ULONG WINAPI
d3d_device7_AddRef(IDirect3DDevice7
*iface
)
189 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
191 TRACE("iface %p.\n", iface
);
193 return IUnknown_AddRef(device
->outer_unknown
);
196 static ULONG WINAPI
d3d_device3_AddRef(IDirect3DDevice3
*iface
)
198 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
200 TRACE("iface %p.\n", iface
);
202 return IUnknown_AddRef(device
->outer_unknown
);
205 static ULONG WINAPI
d3d_device2_AddRef(IDirect3DDevice2
*iface
)
207 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
209 TRACE("iface %p.\n", iface
);
211 return IUnknown_AddRef(device
->outer_unknown
);
214 static ULONG WINAPI
d3d_device1_AddRef(IDirect3DDevice
*iface
)
216 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
218 TRACE("iface %p.\n", iface
);
220 return IUnknown_AddRef(device
->outer_unknown
);
223 static ULONG WINAPI
d3d_device_inner_Release(IUnknown
*iface
)
225 struct d3d_device
*This
= impl_from_IUnknown(iface
);
226 ULONG ref
= InterlockedDecrement(&This
->ref
);
229 TRACE("%p decreasing refcount to %u.\n", This
, ref
);
231 /* This method doesn't destroy the wined3d device, because it's still in
232 * use for 2D rendering. IDirectDrawSurface7::Release will destroy the
233 * wined3d device when the render target is released. */
237 struct list
*vp_entry
, *vp_entry2
;
239 wined3d_mutex_lock();
241 /* There is no need to unset any resources here, wined3d will take
242 * care of that on uninit_3d(). */
244 if (This
->index_buffer
)
245 wined3d_buffer_decref(This
->index_buffer
);
246 if (This
->vertex_buffer
)
247 wined3d_buffer_decref(This
->vertex_buffer
);
249 wined3d_device_set_rendertarget_view(This
->wined3d_device
, 0, NULL
, FALSE
);
251 /* Release the wined3d device. This won't destroy it. */
252 if (!wined3d_device_decref(This
->wined3d_device
))
253 ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This
->wined3d_device
);
255 /* The texture handles should be unset by now, but there might be some bits
256 * missing in our reference counting(needs test). Do a sanity check. */
257 for (i
= 0; i
< This
->handle_table
.entry_count
; ++i
)
259 struct ddraw_handle_entry
*entry
= &This
->handle_table
.entries
[i
];
263 case DDRAW_HANDLE_FREE
:
266 case DDRAW_HANDLE_MATERIAL
:
268 struct d3d_material
*m
= entry
->object
;
269 FIXME("Material handle %#x (%p) not unset properly.\n", i
+ 1, m
);
274 case DDRAW_HANDLE_MATRIX
:
276 /* No FIXME here because this might happen because of sloppy applications. */
277 WARN("Leftover matrix handle %#x (%p), deleting.\n", i
+ 1, entry
->object
);
278 IDirect3DDevice_DeleteMatrix(&This
->IDirect3DDevice_iface
, i
+ 1);
282 case DDRAW_HANDLE_STATEBLOCK
:
284 /* No FIXME here because this might happen because of sloppy applications. */
285 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i
+ 1, entry
->object
);
286 IDirect3DDevice7_DeleteStateBlock(&This
->IDirect3DDevice7_iface
, i
+ 1);
290 case DDRAW_HANDLE_SURFACE
:
292 struct ddraw_surface
*surf
= entry
->object
;
293 FIXME("Texture handle %#x (%p) not unset properly.\n", i
+ 1, surf
);
299 FIXME("Handle %#x (%p) has unknown type %#x.\n", i
+ 1, entry
->object
, entry
->type
);
304 ddraw_handle_table_destroy(&This
->handle_table
);
306 LIST_FOR_EACH_SAFE(vp_entry
, vp_entry2
, &This
->viewport_list
)
308 struct d3d_viewport
*vp
= LIST_ENTRY(vp_entry
, struct d3d_viewport
, entry
);
309 IDirect3DDevice3_DeleteViewport(&This
->IDirect3DDevice3_iface
, &vp
->IDirect3DViewport3_iface
);
312 TRACE("Releasing render target %p.\n", This
->rt_iface
);
313 rt_iface
= This
->rt_iface
;
314 This
->rt_iface
= NULL
;
315 if (This
->version
!= 1)
316 IUnknown_Release(rt_iface
);
317 TRACE("Render target release done.\n");
319 /* Releasing the render target above may have released the last
320 * reference to the ddraw object. */
322 This
->ddraw
->d3ddevice
= NULL
;
324 /* Now free the structure */
325 HeapFree(GetProcessHeap(), 0, This
);
326 wined3d_mutex_unlock();
333 static ULONG WINAPI
d3d_device7_Release(IDirect3DDevice7
*iface
)
335 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
337 TRACE("iface %p.\n", iface
);
339 return IUnknown_Release(device
->outer_unknown
);
342 static ULONG WINAPI
d3d_device3_Release(IDirect3DDevice3
*iface
)
344 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
346 TRACE("iface %p.\n", iface
);
348 return IUnknown_Release(device
->outer_unknown
);
351 static ULONG WINAPI
d3d_device2_Release(IDirect3DDevice2
*iface
)
353 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
355 TRACE("iface %p.\n", iface
);
357 return IUnknown_Release(device
->outer_unknown
);
360 static ULONG WINAPI
d3d_device1_Release(IDirect3DDevice
*iface
)
362 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
364 TRACE("iface %p.\n", iface
);
366 return IUnknown_Release(device
->outer_unknown
);
369 /*****************************************************************************
370 * IDirect3DDevice Methods
371 *****************************************************************************/
373 /*****************************************************************************
374 * IDirect3DDevice::Initialize
376 * Initializes a Direct3DDevice. This implementation is a no-op, as all
377 * initialization is done at create time.
379 * Exists in Version 1
382 * No idea what they mean, as the MSDN page is gone
386 *****************************************************************************/
387 static HRESULT WINAPI
d3d_device1_Initialize(IDirect3DDevice
*iface
,
388 IDirect3D
*d3d
, GUID
*guid
, D3DDEVICEDESC
*device_desc
)
390 /* It shouldn't be crucial, but print a FIXME, I'm interested if
391 * any game calls it and when. */
392 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
393 iface
, d3d
, debugstr_guid(guid
), device_desc
);
398 static HRESULT
d3d_device7_GetCaps(IDirect3DDevice7
*iface
, D3DDEVICEDESC7
*device_desc
)
400 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
402 TRACE("iface %p, device_desc %p.\n", iface
, device_desc
);
406 WARN("device_desc is NULL, returning DDERR_INVALIDPARAMS.\n");
407 return DDERR_INVALIDPARAMS
;
410 /* Call the same function used by IDirect3D, this saves code */
411 return ddraw_get_d3dcaps(device
->ddraw
, device_desc
);
414 static HRESULT WINAPI
d3d_device7_GetCaps_FPUSetup(IDirect3DDevice7
*iface
, D3DDEVICEDESC7
*desc
)
416 return d3d_device7_GetCaps(iface
, desc
);
419 static HRESULT WINAPI
d3d_device7_GetCaps_FPUPreserve(IDirect3DDevice7
*iface
, D3DDEVICEDESC7
*desc
)
424 old_fpucw
= d3d_fpu_setup();
425 hr
= d3d_device7_GetCaps(iface
, desc
);
426 set_fpu_control_word(old_fpucw
);
430 /*****************************************************************************
431 * IDirect3DDevice3::GetCaps
433 * Retrieves the capabilities of the hardware device and the emulation
434 * device. For Wine, hardware and emulation are the same (it's all HW).
436 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
439 * HWDesc: Structure to fill with the HW caps
440 * HelDesc: Structure to fill with the hardware emulation caps
444 * D3DERR_* if a problem occurs. See WineD3D
446 *****************************************************************************/
448 /* There are 3 versions of D3DDEVICEDESC. All 3 share the same name because
449 * Microsoft just expanded the existing structure without naming them
450 * D3DDEVICEDESC2 and D3DDEVICEDESC3. Which version is used have depends
451 * on the version of the DirectX SDK. DirectX 6+ and Wine use the latest
452 * one with 252 bytes.
454 * All 3 versions are allowed as parameters and only the specified amount of
457 * Note that Direct3D7 and earlier are not available in native Win64
458 * ddraw.dll builds, so possible size differences between 32 bit and
459 * 64 bit are a non-issue.
461 static inline BOOL
check_d3ddevicedesc_size(DWORD size
)
463 if (size
== FIELD_OFFSET(D3DDEVICEDESC
, dwMinTextureWidth
) /* 172 */
464 || size
== FIELD_OFFSET(D3DDEVICEDESC
, dwMaxTextureRepeat
) /* 204 */
465 || size
== sizeof(D3DDEVICEDESC
) /* 252 */) return TRUE
;
469 static HRESULT WINAPI
d3d_device3_GetCaps(IDirect3DDevice3
*iface
,
470 D3DDEVICEDESC
*HWDesc
, D3DDEVICEDESC
*HelDesc
)
472 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
473 D3DDEVICEDESC7 desc7
;
477 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface
, HWDesc
, HelDesc
);
481 WARN("HWDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
482 return DDERR_INVALIDPARAMS
;
484 if (!check_d3ddevicedesc_size(HWDesc
->dwSize
))
486 WARN("HWDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HWDesc
->dwSize
);
487 return DDERR_INVALIDPARAMS
;
491 WARN("HelDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
492 return DDERR_INVALIDPARAMS
;
494 if (!check_d3ddevicedesc_size(HelDesc
->dwSize
))
496 WARN("HelDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HelDesc
->dwSize
);
497 return DDERR_INVALIDPARAMS
;
500 if (FAILED(hr
= ddraw_get_d3dcaps(device
->ddraw
, &desc7
)))
503 ddraw_d3dcaps1_from_7(&desc1
, &desc7
);
504 DD_STRUCT_COPY_BYSIZE(HWDesc
, &desc1
);
505 DD_STRUCT_COPY_BYSIZE(HelDesc
, &desc1
);
509 static HRESULT WINAPI
d3d_device2_GetCaps(IDirect3DDevice2
*iface
,
510 D3DDEVICEDESC
*hw_desc
, D3DDEVICEDESC
*hel_desc
)
512 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
514 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface
, hw_desc
, hel_desc
);
516 return d3d_device3_GetCaps(&device
->IDirect3DDevice3_iface
, hw_desc
, hel_desc
);
519 static HRESULT WINAPI
d3d_device1_GetCaps(IDirect3DDevice
*iface
,
520 D3DDEVICEDESC
*hw_desc
, D3DDEVICEDESC
*hel_desc
)
522 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
524 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface
, hw_desc
, hel_desc
);
526 return d3d_device3_GetCaps(&device
->IDirect3DDevice3_iface
, hw_desc
, hel_desc
);
529 /*****************************************************************************
530 * IDirect3DDevice2::SwapTextureHandles
532 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
535 * Tex1, Tex2: The 2 Textures to swap
540 *****************************************************************************/
541 static HRESULT WINAPI
d3d_device2_SwapTextureHandles(IDirect3DDevice2
*iface
,
542 IDirect3DTexture2
*tex1
, IDirect3DTexture2
*tex2
)
544 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
545 struct ddraw_surface
*surf1
= unsafe_impl_from_IDirect3DTexture2(tex1
);
546 struct ddraw_surface
*surf2
= unsafe_impl_from_IDirect3DTexture2(tex2
);
549 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface
, tex1
, tex2
);
551 wined3d_mutex_lock();
553 h1
= surf1
->Handle
- 1;
554 h2
= surf2
->Handle
- 1;
555 device
->handle_table
.entries
[h1
].object
= surf2
;
556 device
->handle_table
.entries
[h2
].object
= surf1
;
557 surf2
->Handle
= h1
+ 1;
558 surf1
->Handle
= h2
+ 1;
560 wined3d_mutex_unlock();
565 static HRESULT WINAPI
d3d_device1_SwapTextureHandles(IDirect3DDevice
*iface
,
566 IDirect3DTexture
*tex1
, IDirect3DTexture
*tex2
)
568 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
569 struct ddraw_surface
*surf1
= unsafe_impl_from_IDirect3DTexture(tex1
);
570 struct ddraw_surface
*surf2
= unsafe_impl_from_IDirect3DTexture(tex2
);
571 IDirect3DTexture2
*t1
= surf1
? &surf1
->IDirect3DTexture2_iface
: NULL
;
572 IDirect3DTexture2
*t2
= surf2
? &surf2
->IDirect3DTexture2_iface
: NULL
;
574 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface
, tex1
, tex2
);
576 return d3d_device2_SwapTextureHandles(&device
->IDirect3DDevice2_iface
, t1
, t2
);
579 /*****************************************************************************
580 * IDirect3DDevice3::GetStats
582 * This method seems to retrieve some stats from the device.
583 * The MSDN documentation doesn't exist any more, but the D3DSTATS
584 * structure suggests that the amount of drawn primitives and processed
585 * vertices is returned.
587 * Exists in Version 1, 2 and 3
590 * Stats: Pointer to a D3DSTATS structure to be filled
594 * DDERR_INVALIDPARAMS if Stats == NULL
596 *****************************************************************************/
597 static HRESULT WINAPI
d3d_device3_GetStats(IDirect3DDevice3
*iface
, D3DSTATS
*Stats
)
599 FIXME("iface %p, stats %p stub!\n", iface
, Stats
);
602 return DDERR_INVALIDPARAMS
;
604 /* Fill the Stats with 0 */
605 Stats
->dwTrianglesDrawn
= 0;
606 Stats
->dwLinesDrawn
= 0;
607 Stats
->dwPointsDrawn
= 0;
608 Stats
->dwSpansDrawn
= 0;
609 Stats
->dwVerticesProcessed
= 0;
614 static HRESULT WINAPI
d3d_device2_GetStats(IDirect3DDevice2
*iface
, D3DSTATS
*stats
)
616 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
618 TRACE("iface %p, stats %p.\n", iface
, stats
);
620 return d3d_device3_GetStats(&device
->IDirect3DDevice3_iface
, stats
);
623 static HRESULT WINAPI
d3d_device1_GetStats(IDirect3DDevice
*iface
, D3DSTATS
*stats
)
625 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
627 TRACE("iface %p, stats %p.\n", iface
, stats
);
629 return d3d_device3_GetStats(&device
->IDirect3DDevice3_iface
, stats
);
632 /*****************************************************************************
633 * IDirect3DDevice::CreateExecuteBuffer
635 * Creates an IDirect3DExecuteBuffer, used for rendering with a
641 * Desc: Buffer description
642 * ExecuteBuffer: Address to return the Interface pointer at
643 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
647 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
648 * DDERR_OUTOFMEMORY if we ran out of memory
651 *****************************************************************************/
652 static HRESULT WINAPI
d3d_device1_CreateExecuteBuffer(IDirect3DDevice
*iface
,
653 D3DEXECUTEBUFFERDESC
*buffer_desc
, IDirect3DExecuteBuffer
**ExecuteBuffer
, IUnknown
*outer_unknown
)
655 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
656 struct d3d_execute_buffer
*object
;
659 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
660 iface
, buffer_desc
, ExecuteBuffer
, outer_unknown
);
663 return CLASS_E_NOAGGREGATION
;
665 /* Allocate the new Execute Buffer */
666 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
669 ERR("Failed to allocate execute buffer memory.\n");
670 return DDERR_OUTOFMEMORY
;
673 hr
= d3d_execute_buffer_init(object
, device
, buffer_desc
);
676 WARN("Failed to initialize execute buffer, hr %#x.\n", hr
);
677 HeapFree(GetProcessHeap(), 0, object
);
681 *ExecuteBuffer
= &object
->IDirect3DExecuteBuffer_iface
;
683 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer
, object
);
688 /*****************************************************************************
689 * IDirect3DDevice::Execute
691 * Executes all the stuff in an execute buffer.
694 * ExecuteBuffer: The buffer to execute
695 * Viewport: The viewport used for rendering
699 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
702 *****************************************************************************/
703 static HRESULT WINAPI
d3d_device1_Execute(IDirect3DDevice
*iface
,
704 IDirect3DExecuteBuffer
*ExecuteBuffer
, IDirect3DViewport
*viewport
, DWORD flags
)
706 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
707 struct d3d_execute_buffer
*buffer
= unsafe_impl_from_IDirect3DExecuteBuffer(ExecuteBuffer
);
708 struct d3d_viewport
*viewport_impl
= unsafe_impl_from_IDirect3DViewport(viewport
);
711 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface
, ExecuteBuffer
, viewport
, flags
);
714 return DDERR_INVALIDPARAMS
;
717 wined3d_mutex_lock();
718 hr
= d3d_execute_buffer_execute(buffer
, device
, viewport_impl
);
719 wined3d_mutex_unlock();
724 /*****************************************************************************
725 * IDirect3DDevice3::AddViewport
727 * Add a Direct3DViewport to the device's viewport list. These viewports
728 * are wrapped to IDirect3DDevice7 viewports in viewport.c
730 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
731 * are the same interfaces.
734 * Viewport: The viewport to add
737 * DDERR_INVALIDPARAMS if Viewport == NULL
740 *****************************************************************************/
741 static HRESULT WINAPI
d3d_device3_AddViewport(IDirect3DDevice3
*iface
, IDirect3DViewport3
*viewport
)
743 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
744 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport3(viewport
);
746 TRACE("iface %p, viewport %p.\n", iface
, viewport
);
750 return DDERR_INVALIDPARAMS
;
752 wined3d_mutex_lock();
753 IDirect3DViewport3_AddRef(viewport
);
754 list_add_head(&device
->viewport_list
, &vp
->entry
);
755 /* Viewport must be usable for Clear() after AddViewport, so set active_device here. */
756 vp
->active_device
= device
;
757 wined3d_mutex_unlock();
762 static HRESULT WINAPI
d3d_device2_AddViewport(IDirect3DDevice2
*iface
,
763 IDirect3DViewport2
*viewport
)
765 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
766 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport2(viewport
);
768 TRACE("iface %p, viewport %p.\n", iface
, viewport
);
770 return d3d_device3_AddViewport(&device
->IDirect3DDevice3_iface
, &vp
->IDirect3DViewport3_iface
);
773 static HRESULT WINAPI
d3d_device1_AddViewport(IDirect3DDevice
*iface
, IDirect3DViewport
*viewport
)
775 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
776 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport(viewport
);
778 TRACE("iface %p, viewport %p.\n", iface
, viewport
);
780 return d3d_device3_AddViewport(&device
->IDirect3DDevice3_iface
, &vp
->IDirect3DViewport3_iface
);
783 /*****************************************************************************
784 * IDirect3DDevice3::DeleteViewport
786 * Deletes a Direct3DViewport from the device's viewport list.
788 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
792 * Viewport: The viewport to delete
796 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
798 *****************************************************************************/
799 static HRESULT WINAPI
d3d_device3_DeleteViewport(IDirect3DDevice3
*iface
, IDirect3DViewport3
*viewport
)
801 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
802 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport3(viewport
);
804 TRACE("iface %p, viewport %p.\n", iface
, viewport
);
808 WARN("NULL viewport, returning DDERR_INVALIDPARAMS\n");
809 return DDERR_INVALIDPARAMS
;
812 wined3d_mutex_lock();
814 if (vp
->active_device
!= device
)
816 WARN("Viewport %p active device is %p.\n", vp
, vp
->active_device
);
817 wined3d_mutex_unlock();
818 return DDERR_INVALIDPARAMS
;
821 if (device
->current_viewport
== vp
)
823 TRACE("Deleting current viewport, unsetting and releasing\n");
824 IDirect3DViewport3_Release(viewport
);
825 device
->current_viewport
= NULL
;
828 vp
->active_device
= NULL
;
829 list_remove(&vp
->entry
);
831 IDirect3DViewport3_Release(viewport
);
833 wined3d_mutex_unlock();
838 static HRESULT WINAPI
d3d_device2_DeleteViewport(IDirect3DDevice2
*iface
, IDirect3DViewport2
*viewport
)
840 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
841 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport2(viewport
);
843 TRACE("iface %p, viewport %p.\n", iface
, viewport
);
845 return d3d_device3_DeleteViewport(&device
->IDirect3DDevice3_iface
,
846 vp
? &vp
->IDirect3DViewport3_iface
: NULL
);
849 static HRESULT WINAPI
d3d_device1_DeleteViewport(IDirect3DDevice
*iface
, IDirect3DViewport
*viewport
)
851 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
852 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport(viewport
);
854 TRACE("iface %p, viewport %p.\n", iface
, viewport
);
856 return d3d_device3_DeleteViewport(&device
->IDirect3DDevice3_iface
,
857 vp
? &vp
->IDirect3DViewport3_iface
: NULL
);
860 /*****************************************************************************
861 * IDirect3DDevice3::NextViewport
863 * Returns a viewport from the viewport list, depending on the
864 * passed viewport and the flags.
866 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
870 * Viewport: Viewport to use for beginning the search
871 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
875 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
877 *****************************************************************************/
878 static HRESULT WINAPI
d3d_device3_NextViewport(IDirect3DDevice3
*iface
,
879 IDirect3DViewport3
*Viewport3
, IDirect3DViewport3
**lplpDirect3DViewport3
, DWORD flags
)
881 struct d3d_device
*This
= impl_from_IDirect3DDevice3(iface
);
882 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport3(Viewport3
);
883 struct d3d_viewport
*next
;
886 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
887 iface
, Viewport3
, lplpDirect3DViewport3
, flags
);
891 *lplpDirect3DViewport3
= NULL
;
892 return DDERR_INVALIDPARAMS
;
896 wined3d_mutex_lock();
900 entry
= list_next(&This
->viewport_list
, &vp
->entry
);
904 entry
= list_head(&This
->viewport_list
);
908 entry
= list_tail(&This
->viewport_list
);
912 WARN("Invalid flags %#x.\n", flags
);
913 *lplpDirect3DViewport3
= NULL
;
914 wined3d_mutex_unlock();
915 return DDERR_INVALIDPARAMS
;
920 next
= LIST_ENTRY(entry
, struct d3d_viewport
, entry
);
921 *lplpDirect3DViewport3
= &next
->IDirect3DViewport3_iface
;
924 *lplpDirect3DViewport3
= NULL
;
926 wined3d_mutex_unlock();
931 static HRESULT WINAPI
d3d_device2_NextViewport(IDirect3DDevice2
*iface
,
932 IDirect3DViewport2
*viewport
, IDirect3DViewport2
**next
, DWORD flags
)
934 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
935 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport2(viewport
);
936 IDirect3DViewport3
*res
;
939 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
940 iface
, viewport
, next
, flags
);
942 hr
= d3d_device3_NextViewport(&device
->IDirect3DDevice3_iface
,
943 &vp
->IDirect3DViewport3_iface
, &res
, flags
);
944 *next
= (IDirect3DViewport2
*)res
;
948 static HRESULT WINAPI
d3d_device1_NextViewport(IDirect3DDevice
*iface
,
949 IDirect3DViewport
*viewport
, IDirect3DViewport
**next
, DWORD flags
)
951 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
952 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport(viewport
);
953 IDirect3DViewport3
*res
;
956 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
957 iface
, viewport
, next
, flags
);
959 hr
= d3d_device3_NextViewport(&device
->IDirect3DDevice3_iface
,
960 &vp
->IDirect3DViewport3_iface
, &res
, flags
);
961 *next
= (IDirect3DViewport
*)res
;
965 /*****************************************************************************
966 * IDirect3DDevice::Pick
968 * Executes an execute buffer without performing rendering. Instead, a
969 * list of primitives that intersect with (x1,y1) of the passed rectangle
970 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
976 * ExecuteBuffer: Buffer to execute
977 * Viewport: Viewport to use for execution
978 * Flags: None are defined, according to the SDK
979 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
980 * x2 and y2 are ignored.
983 * D3D_OK because it's a stub
985 *****************************************************************************/
986 static HRESULT WINAPI
d3d_device1_Pick(IDirect3DDevice
*iface
, IDirect3DExecuteBuffer
*buffer
,
987 IDirect3DViewport
*viewport
, DWORD flags
, D3DRECT
*rect
)
989 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
990 iface
, buffer
, viewport
, flags
, wine_dbgstr_rect((RECT
*)rect
));
995 /*****************************************************************************
996 * IDirect3DDevice::GetPickRecords
998 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1003 * Count: Pointer to a DWORD containing the numbers of pick records to
1005 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1008 * D3D_OK, because it's a stub
1010 *****************************************************************************/
1011 static HRESULT WINAPI
d3d_device1_GetPickRecords(IDirect3DDevice
*iface
,
1012 DWORD
*count
, D3DPICKRECORD
*records
)
1014 FIXME("iface %p, count %p, records %p stub!\n", iface
, count
, records
);
1019 /*****************************************************************************
1020 * IDirect3DDevice7::EnumTextureformats
1022 * Enumerates the supported texture formats. It checks against a list of all possible
1023 * formats to see if WineD3D supports it. If so, then it is passed to the app.
1025 * This is for Version 7 and 3, older versions have a different
1026 * callback function and their own implementation
1029 * Callback: Callback to call for each enumerated format
1030 * Arg: Argument to pass to the callback
1034 * DDERR_INVALIDPARAMS if Callback == NULL
1036 *****************************************************************************/
1037 static HRESULT
d3d_device7_EnumTextureFormats(IDirect3DDevice7
*iface
,
1038 LPD3DENUMPIXELFORMATSCALLBACK callback
, void *context
)
1040 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
1041 struct wined3d_display_mode mode
;
1045 static const enum wined3d_format_id FormatList
[] =
1048 WINED3DFMT_B5G5R5X1_UNORM
,
1049 WINED3DFMT_B5G5R5A1_UNORM
,
1050 WINED3DFMT_B4G4R4A4_UNORM
,
1051 WINED3DFMT_B5G6R5_UNORM
,
1053 WINED3DFMT_B8G8R8X8_UNORM
,
1054 WINED3DFMT_B8G8R8A8_UNORM
,
1056 WINED3DFMT_B2G3R3_UNORM
,
1066 static const enum wined3d_format_id BumpFormatList
[] =
1068 WINED3DFMT_R8G8_SNORM
,
1069 WINED3DFMT_R5G5_SNORM_L6_UNORM
,
1070 WINED3DFMT_R8G8_SNORM_L8X8_UNORM
,
1071 WINED3DFMT_R10G11B11_SNORM
,
1072 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1075 TRACE("iface %p, callback %p, context %p.\n", iface
, callback
, context
);
1078 return DDERR_INVALIDPARAMS
;
1080 wined3d_mutex_lock();
1082 memset(&mode
, 0, sizeof(mode
));
1083 if (FAILED(hr
= wined3d_get_adapter_display_mode(device
->ddraw
->wined3d
, WINED3DADAPTER_DEFAULT
, &mode
, NULL
)))
1085 wined3d_mutex_unlock();
1086 WARN("Cannot get the current adapter format\n");
1090 for (i
= 0; i
< sizeof(FormatList
) / sizeof(*FormatList
); ++i
)
1092 if (wined3d_check_device_format(device
->ddraw
->wined3d
, WINED3DADAPTER_DEFAULT
, WINED3D_DEVICE_TYPE_HAL
,
1093 mode
.format_id
, WINED3DUSAGE_TEXTURE
, WINED3D_RTYPE_TEXTURE_2D
, FormatList
[i
]) == D3D_OK
)
1095 DDPIXELFORMAT pformat
;
1097 memset(&pformat
, 0, sizeof(pformat
));
1098 pformat
.dwSize
= sizeof(pformat
);
1099 ddrawformat_from_wined3dformat(&pformat
, FormatList
[i
]);
1101 TRACE("Enumerating WineD3DFormat %d\n", FormatList
[i
]);
1102 hr
= callback(&pformat
, context
);
1103 if(hr
!= DDENUMRET_OK
)
1105 TRACE("Format enumeration cancelled by application\n");
1106 wined3d_mutex_unlock();
1112 for (i
= 0; i
< sizeof(BumpFormatList
) / sizeof(*BumpFormatList
); ++i
)
1114 if (wined3d_check_device_format(device
->ddraw
->wined3d
, WINED3DADAPTER_DEFAULT
,
1115 WINED3D_DEVICE_TYPE_HAL
, mode
.format_id
, WINED3DUSAGE_TEXTURE
| WINED3DUSAGE_QUERY_LEGACYBUMPMAP
,
1116 WINED3D_RTYPE_TEXTURE_2D
, BumpFormatList
[i
]) == D3D_OK
)
1118 DDPIXELFORMAT pformat
;
1120 memset(&pformat
, 0, sizeof(pformat
));
1121 pformat
.dwSize
= sizeof(pformat
);
1122 ddrawformat_from_wined3dformat(&pformat
, BumpFormatList
[i
]);
1124 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList
[i
]);
1125 hr
= callback(&pformat
, context
);
1126 if(hr
!= DDENUMRET_OK
)
1128 TRACE("Format enumeration cancelled by application\n");
1129 wined3d_mutex_unlock();
1134 TRACE("End of enumeration\n");
1135 wined3d_mutex_unlock();
1140 static HRESULT WINAPI
d3d_device7_EnumTextureFormats_FPUSetup(IDirect3DDevice7
*iface
,
1141 LPD3DENUMPIXELFORMATSCALLBACK callback
, void *context
)
1143 return d3d_device7_EnumTextureFormats(iface
, callback
, context
);
1146 static HRESULT WINAPI
d3d_device7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7
*iface
,
1147 LPD3DENUMPIXELFORMATSCALLBACK callback
, void *context
)
1152 old_fpucw
= d3d_fpu_setup();
1153 hr
= d3d_device7_EnumTextureFormats(iface
, callback
, context
);
1154 set_fpu_control_word(old_fpucw
);
1159 static HRESULT WINAPI
d3d_device3_EnumTextureFormats(IDirect3DDevice3
*iface
,
1160 LPD3DENUMPIXELFORMATSCALLBACK callback
, void *context
)
1162 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
1164 TRACE("iface %p, callback %p, context %p.\n", iface
, callback
, context
);
1166 return IDirect3DDevice7_EnumTextureFormats(&device
->IDirect3DDevice7_iface
, callback
, context
);
1169 /*****************************************************************************
1170 * IDirect3DDevice2::EnumTextureformats
1172 * EnumTextureFormats for Version 1 and 2, see
1173 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1175 * This version has a different callback and does not enumerate FourCC
1178 *****************************************************************************/
1179 static HRESULT WINAPI
d3d_device2_EnumTextureFormats(IDirect3DDevice2
*iface
,
1180 LPD3DENUMTEXTUREFORMATSCALLBACK callback
, void *context
)
1182 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
1183 struct wined3d_display_mode mode
;
1187 static const enum wined3d_format_id FormatList
[] =
1190 WINED3DFMT_B5G5R5X1_UNORM
,
1191 WINED3DFMT_B5G5R5A1_UNORM
,
1192 WINED3DFMT_B4G4R4A4_UNORM
,
1193 WINED3DFMT_B5G6R5_UNORM
,
1195 WINED3DFMT_B8G8R8X8_UNORM
,
1196 WINED3DFMT_B8G8R8A8_UNORM
,
1198 WINED3DFMT_B2G3R3_UNORM
,
1200 /* FOURCC codes - Not in this version*/
1203 TRACE("iface %p, callback %p, context %p.\n", iface
, callback
, context
);
1206 return DDERR_INVALIDPARAMS
;
1208 wined3d_mutex_lock();
1210 memset(&mode
, 0, sizeof(mode
));
1211 if (FAILED(hr
= wined3d_get_adapter_display_mode(device
->ddraw
->wined3d
, WINED3DADAPTER_DEFAULT
, &mode
, NULL
)))
1213 wined3d_mutex_unlock();
1214 WARN("Cannot get the current adapter format\n");
1218 for (i
= 0; i
< sizeof(FormatList
) / sizeof(*FormatList
); ++i
)
1220 if (wined3d_check_device_format(device
->ddraw
->wined3d
, 0, WINED3D_DEVICE_TYPE_HAL
,
1221 mode
.format_id
, WINED3DUSAGE_TEXTURE
, WINED3D_RTYPE_TEXTURE_2D
, FormatList
[i
]) == D3D_OK
)
1223 DDSURFACEDESC sdesc
;
1225 memset(&sdesc
, 0, sizeof(sdesc
));
1226 sdesc
.dwSize
= sizeof(sdesc
);
1227 sdesc
.dwFlags
= DDSD_PIXELFORMAT
| DDSD_CAPS
;
1228 sdesc
.ddsCaps
.dwCaps
= DDSCAPS_TEXTURE
;
1229 sdesc
.ddpfPixelFormat
.dwSize
= sizeof(sdesc
.ddpfPixelFormat
);
1230 ddrawformat_from_wined3dformat(&sdesc
.ddpfPixelFormat
, FormatList
[i
]);
1232 TRACE("Enumerating WineD3DFormat %d\n", FormatList
[i
]);
1233 hr
= callback(&sdesc
, context
);
1234 if(hr
!= DDENUMRET_OK
)
1236 TRACE("Format enumeration cancelled by application\n");
1237 wined3d_mutex_unlock();
1242 TRACE("End of enumeration\n");
1243 wined3d_mutex_unlock();
1248 static HRESULT WINAPI
d3d_device1_EnumTextureFormats(IDirect3DDevice
*iface
,
1249 LPD3DENUMTEXTUREFORMATSCALLBACK callback
, void *context
)
1251 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
1253 TRACE("iface %p, callback %p, context %p.\n", iface
, callback
, context
);
1255 return d3d_device2_EnumTextureFormats(&device
->IDirect3DDevice2_iface
, callback
, context
);
1258 /*****************************************************************************
1259 * IDirect3DDevice::CreateMatrix
1261 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1262 * allocated for the handle.
1267 * D3DMatHandle: Address to return the handle at
1271 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1273 *****************************************************************************/
1274 static HRESULT WINAPI
d3d_device1_CreateMatrix(IDirect3DDevice
*iface
, D3DMATRIXHANDLE
*D3DMatHandle
)
1276 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
1280 TRACE("iface %p, matrix_handle %p.\n", iface
, D3DMatHandle
);
1283 return DDERR_INVALIDPARAMS
;
1285 Matrix
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(D3DMATRIX
));
1288 ERR("Out of memory when allocating a D3DMATRIX\n");
1289 return DDERR_OUTOFMEMORY
;
1292 wined3d_mutex_lock();
1294 h
= ddraw_allocate_handle(&device
->handle_table
, Matrix
, DDRAW_HANDLE_MATRIX
);
1295 if (h
== DDRAW_INVALID_HANDLE
)
1297 ERR("Failed to allocate a matrix handle.\n");
1298 HeapFree(GetProcessHeap(), 0, Matrix
);
1299 wined3d_mutex_unlock();
1300 return DDERR_OUTOFMEMORY
;
1303 *D3DMatHandle
= h
+ 1;
1305 TRACE(" returning matrix handle %d\n", *D3DMatHandle
);
1307 wined3d_mutex_unlock();
1312 /*****************************************************************************
1313 * IDirect3DDevice::SetMatrix
1315 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1316 * allocated for the handle
1321 * D3DMatHandle: Handle to set the matrix to
1322 * D3DMatrix: Matrix to set
1326 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1329 *****************************************************************************/
1330 static HRESULT WINAPI
d3d_device1_SetMatrix(IDirect3DDevice
*iface
,
1331 D3DMATRIXHANDLE D3DMatHandle
, D3DMATRIX
*D3DMatrix
)
1333 struct d3d_device
*This
= impl_from_IDirect3DDevice(iface
);
1336 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface
, D3DMatHandle
, D3DMatrix
);
1338 if (!D3DMatrix
) return DDERR_INVALIDPARAMS
;
1340 wined3d_mutex_lock();
1342 m
= ddraw_get_object(&This
->handle_table
, D3DMatHandle
- 1, DDRAW_HANDLE_MATRIX
);
1345 WARN("Invalid matrix handle.\n");
1346 wined3d_mutex_unlock();
1347 return DDERR_INVALIDPARAMS
;
1350 if (TRACE_ON(ddraw
))
1351 dump_D3DMATRIX(D3DMatrix
);
1355 if (D3DMatHandle
== This
->world
)
1356 wined3d_device_set_transform(This
->wined3d_device
,
1357 WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix
*)D3DMatrix
);
1359 if (D3DMatHandle
== This
->view
)
1360 wined3d_device_set_transform(This
->wined3d_device
,
1361 WINED3D_TS_VIEW
, (struct wined3d_matrix
*)D3DMatrix
);
1363 if (D3DMatHandle
== This
->proj
)
1364 wined3d_device_set_transform(This
->wined3d_device
,
1365 WINED3D_TS_PROJECTION
, (struct wined3d_matrix
*)D3DMatrix
);
1367 wined3d_mutex_unlock();
1372 /*****************************************************************************
1373 * IDirect3DDevice::GetMatrix
1375 * Returns the content of a D3DMATRIX handle
1380 * D3DMatHandle: Matrix handle to read the content from
1381 * D3DMatrix: Address to store the content at
1385 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1387 *****************************************************************************/
1388 static HRESULT WINAPI
d3d_device1_GetMatrix(IDirect3DDevice
*iface
,
1389 D3DMATRIXHANDLE D3DMatHandle
, D3DMATRIX
*D3DMatrix
)
1391 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
1394 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface
, D3DMatHandle
, D3DMatrix
);
1396 if (!D3DMatrix
) return DDERR_INVALIDPARAMS
;
1398 wined3d_mutex_lock();
1400 m
= ddraw_get_object(&device
->handle_table
, D3DMatHandle
- 1, DDRAW_HANDLE_MATRIX
);
1403 WARN("Invalid matrix handle.\n");
1404 wined3d_mutex_unlock();
1405 return DDERR_INVALIDPARAMS
;
1410 wined3d_mutex_unlock();
1415 /*****************************************************************************
1416 * IDirect3DDevice::DeleteMatrix
1418 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1423 * D3DMatHandle: Handle to destroy
1427 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1429 *****************************************************************************/
1430 static HRESULT WINAPI
d3d_device1_DeleteMatrix(IDirect3DDevice
*iface
, D3DMATRIXHANDLE D3DMatHandle
)
1432 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
1435 TRACE("iface %p, matrix_handle %#x.\n", iface
, D3DMatHandle
);
1437 wined3d_mutex_lock();
1439 m
= ddraw_free_handle(&device
->handle_table
, D3DMatHandle
- 1, DDRAW_HANDLE_MATRIX
);
1442 WARN("Invalid matrix handle.\n");
1443 wined3d_mutex_unlock();
1444 return DDERR_INVALIDPARAMS
;
1447 wined3d_mutex_unlock();
1449 HeapFree(GetProcessHeap(), 0, m
);
1454 /*****************************************************************************
1455 * IDirect3DDevice7::BeginScene
1457 * This method must be called before any rendering is performed.
1458 * IDirect3DDevice::EndScene has to be called after the scene is complete
1460 * Version 1, 2, 3 and 7
1463 * D3D_OK on success,
1464 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1467 *****************************************************************************/
1468 static HRESULT
d3d_device7_BeginScene(IDirect3DDevice7
*iface
)
1470 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
1473 TRACE("iface %p.\n", iface
);
1475 wined3d_mutex_lock();
1476 hr
= wined3d_device_begin_scene(device
->wined3d_device
);
1477 wined3d_mutex_unlock();
1479 if(hr
== WINED3D_OK
) return D3D_OK
;
1480 else return D3DERR_SCENE_IN_SCENE
; /* TODO: Other possible causes of failure */
1483 static HRESULT WINAPI
d3d_device7_BeginScene_FPUSetup(IDirect3DDevice7
*iface
)
1485 return d3d_device7_BeginScene(iface
);
1488 static HRESULT WINAPI
d3d_device7_BeginScene_FPUPreserve(IDirect3DDevice7
*iface
)
1493 old_fpucw
= d3d_fpu_setup();
1494 hr
= d3d_device7_BeginScene(iface
);
1495 set_fpu_control_word(old_fpucw
);
1500 static HRESULT WINAPI
d3d_device3_BeginScene(IDirect3DDevice3
*iface
)
1502 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
1504 TRACE("iface %p.\n", iface
);
1506 return IDirect3DDevice7_BeginScene(&device
->IDirect3DDevice7_iface
);
1509 static HRESULT WINAPI
d3d_device2_BeginScene(IDirect3DDevice2
*iface
)
1511 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
1513 TRACE("iface %p.\n", iface
);
1515 return IDirect3DDevice7_BeginScene(&device
->IDirect3DDevice7_iface
);
1518 static HRESULT WINAPI
d3d_device1_BeginScene(IDirect3DDevice
*iface
)
1520 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
1522 TRACE("iface %p.\n", iface
);
1524 return IDirect3DDevice7_BeginScene(&device
->IDirect3DDevice7_iface
);
1527 /*****************************************************************************
1528 * IDirect3DDevice7::EndScene
1530 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1531 * This method must be called after rendering is finished.
1533 * Version 1, 2, 3 and 7
1536 * D3D_OK on success,
1537 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1538 * that only if the scene was already ended.
1540 *****************************************************************************/
1541 static HRESULT
d3d_device7_EndScene(IDirect3DDevice7
*iface
)
1543 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
1546 TRACE("iface %p.\n", iface
);
1548 wined3d_mutex_lock();
1549 hr
= wined3d_device_end_scene(device
->wined3d_device
);
1550 wined3d_mutex_unlock();
1552 if(hr
== WINED3D_OK
) return D3D_OK
;
1553 else return D3DERR_SCENE_NOT_IN_SCENE
;
1556 static HRESULT WINAPI DECLSPEC_HOTPATCH
d3d_device7_EndScene_FPUSetup(IDirect3DDevice7
*iface
)
1558 return d3d_device7_EndScene(iface
);
1561 static HRESULT WINAPI DECLSPEC_HOTPATCH
d3d_device7_EndScene_FPUPreserve(IDirect3DDevice7
*iface
)
1566 old_fpucw
= d3d_fpu_setup();
1567 hr
= d3d_device7_EndScene(iface
);
1568 set_fpu_control_word(old_fpucw
);
1573 static HRESULT WINAPI DECLSPEC_HOTPATCH
d3d_device3_EndScene(IDirect3DDevice3
*iface
)
1575 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
1577 TRACE("iface %p.\n", iface
);
1579 return IDirect3DDevice7_EndScene(&device
->IDirect3DDevice7_iface
);
1582 static HRESULT WINAPI DECLSPEC_HOTPATCH
d3d_device2_EndScene(IDirect3DDevice2
*iface
)
1584 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
1586 TRACE("iface %p.\n", iface
);
1588 return IDirect3DDevice7_EndScene(&device
->IDirect3DDevice7_iface
);
1591 static HRESULT WINAPI DECLSPEC_HOTPATCH
d3d_device1_EndScene(IDirect3DDevice
*iface
)
1593 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
1595 TRACE("iface %p.\n", iface
);
1597 return IDirect3DDevice7_EndScene(&device
->IDirect3DDevice7_iface
);
1600 /*****************************************************************************
1601 * IDirect3DDevice7::GetDirect3D
1603 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1607 * Direct3D7: Address to store the interface pointer at
1611 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1613 *****************************************************************************/
1614 static HRESULT WINAPI
d3d_device7_GetDirect3D(IDirect3DDevice7
*iface
, IDirect3D7
**d3d
)
1616 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
1618 TRACE("iface %p, d3d %p.\n", iface
, d3d
);
1621 return DDERR_INVALIDPARAMS
;
1623 *d3d
= &device
->ddraw
->IDirect3D7_iface
;
1624 IDirect3D7_AddRef(*d3d
);
1626 TRACE("Returning interface %p.\n", *d3d
);
1630 static HRESULT WINAPI
d3d_device3_GetDirect3D(IDirect3DDevice3
*iface
, IDirect3D3
**d3d
)
1632 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
1634 TRACE("iface %p, d3d %p.\n", iface
, d3d
);
1637 return DDERR_INVALIDPARAMS
;
1639 *d3d
= &device
->ddraw
->IDirect3D3_iface
;
1640 IDirect3D3_AddRef(*d3d
);
1642 TRACE("Returning interface %p.\n", *d3d
);
1646 static HRESULT WINAPI
d3d_device2_GetDirect3D(IDirect3DDevice2
*iface
, IDirect3D2
**d3d
)
1648 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
1650 TRACE("iface %p, d3d %p.\n", iface
, d3d
);
1653 return DDERR_INVALIDPARAMS
;
1655 *d3d
= &device
->ddraw
->IDirect3D2_iface
;
1656 IDirect3D2_AddRef(*d3d
);
1658 TRACE("Returning interface %p.\n", *d3d
);
1662 static HRESULT WINAPI
d3d_device1_GetDirect3D(IDirect3DDevice
*iface
, IDirect3D
**d3d
)
1664 struct d3d_device
*device
= impl_from_IDirect3DDevice(iface
);
1666 TRACE("iface %p, d3d %p.\n", iface
, d3d
);
1669 return DDERR_INVALIDPARAMS
;
1671 *d3d
= &device
->ddraw
->IDirect3D_iface
;
1672 IDirect3D_AddRef(*d3d
);
1674 TRACE("Returning interface %p.\n", *d3d
);
1678 /*****************************************************************************
1679 * IDirect3DDevice3::SetCurrentViewport
1681 * Sets a Direct3DViewport as the current viewport.
1682 * For the thunks note that all viewport interface versions are equal
1685 * Direct3DViewport3: The viewport to set
1691 * (Is a NULL viewport valid?)
1693 *****************************************************************************/
1694 static HRESULT WINAPI
d3d_device3_SetCurrentViewport(IDirect3DDevice3
*iface
, IDirect3DViewport3
*Direct3DViewport3
)
1696 struct d3d_device
*This
= impl_from_IDirect3DDevice3(iface
);
1697 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport3(Direct3DViewport3
);
1699 TRACE("iface %p, viewport %p.\n", iface
, Direct3DViewport3
);
1703 WARN("Direct3DViewport3 is NULL, returning DDERR_INVALIDPARAMS\n");
1704 return DDERR_INVALIDPARAMS
;
1707 wined3d_mutex_lock();
1708 /* Do nothing if the specified viewport is the same as the current one */
1709 if (This
->current_viewport
== vp
)
1711 wined3d_mutex_unlock();
1715 if (vp
->active_device
!= This
)
1717 WARN("Viewport %p active device is %p.\n", vp
, vp
->active_device
);
1718 wined3d_mutex_unlock();
1719 return DDERR_INVALIDPARAMS
;
1722 /* Release previous viewport and AddRef the new one */
1723 if (This
->current_viewport
)
1725 TRACE("ViewportImpl is at %p, interface is at %p\n", This
->current_viewport
,
1726 &This
->current_viewport
->IDirect3DViewport3_iface
);
1727 IDirect3DViewport3_Release(&This
->current_viewport
->IDirect3DViewport3_iface
);
1729 IDirect3DViewport3_AddRef(Direct3DViewport3
);
1731 /* Set this viewport as the current viewport */
1732 This
->current_viewport
= vp
;
1734 /* Activate this viewport */
1735 viewport_activate(This
->current_viewport
, FALSE
);
1737 wined3d_mutex_unlock();
1742 static HRESULT WINAPI
d3d_device2_SetCurrentViewport(IDirect3DDevice2
*iface
, IDirect3DViewport2
*viewport
)
1744 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
1745 struct d3d_viewport
*vp
= unsafe_impl_from_IDirect3DViewport2(viewport
);
1747 TRACE("iface %p, viewport %p.\n", iface
, viewport
);
1749 return d3d_device3_SetCurrentViewport(&device
->IDirect3DDevice3_iface
,
1750 vp
? &vp
->IDirect3DViewport3_iface
: NULL
);
1753 /*****************************************************************************
1754 * IDirect3DDevice3::GetCurrentViewport
1756 * Returns the currently active viewport.
1761 * Direct3DViewport3: Address to return the interface pointer at
1765 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1767 *****************************************************************************/
1768 static HRESULT WINAPI
d3d_device3_GetCurrentViewport(IDirect3DDevice3
*iface
, IDirect3DViewport3
**viewport
)
1770 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
1772 TRACE("iface %p, viewport %p.\n", iface
, viewport
);
1774 wined3d_mutex_lock();
1775 if (!device
->current_viewport
)
1777 wined3d_mutex_unlock();
1778 WARN("No current viewport, returning D3DERR_NOCURRENTVIEWPORT\n");
1779 return D3DERR_NOCURRENTVIEWPORT
;
1782 *viewport
= &device
->current_viewport
->IDirect3DViewport3_iface
;
1783 IDirect3DViewport3_AddRef(*viewport
);
1785 TRACE("Returning interface %p.\n", *viewport
);
1786 wined3d_mutex_unlock();
1790 static HRESULT WINAPI
d3d_device2_GetCurrentViewport(IDirect3DDevice2
*iface
, IDirect3DViewport2
**viewport
)
1792 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
1794 TRACE("iface %p, viewport %p.\n", iface
, viewport
);
1796 return d3d_device3_GetCurrentViewport(&device
->IDirect3DDevice3_iface
,
1797 (IDirect3DViewport3
**)viewport
);
1800 static BOOL
validate_surface_palette(struct ddraw_surface
*surface
)
1802 return !format_is_paletteindexed(&surface
->surface_desc
.u4
.ddpfPixelFormat
)
1803 || surface
->palette
;
1806 static HRESULT
d3d_device_set_render_target(struct d3d_device
*device
,
1807 struct ddraw_surface
*target
, IUnknown
*rt_iface
)
1811 if (device
->rt_iface
== rt_iface
)
1813 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1818 WARN("Trying to set render target to NULL.\n");
1819 return DDERR_INVALIDPARAMS
;
1822 if (FAILED(hr
= wined3d_device_set_rendertarget_view(device
->wined3d_device
,
1823 0, ddraw_surface_get_rendertarget_view(target
), FALSE
)))
1826 IUnknown_AddRef(rt_iface
);
1827 IUnknown_Release(device
->rt_iface
);
1828 device
->rt_iface
= rt_iface
;
1829 d3d_device_update_depth_stencil(device
);
1834 static HRESULT
d3d_device7_SetRenderTarget(IDirect3DDevice7
*iface
,
1835 IDirectDrawSurface7
*target
, DWORD flags
)
1837 struct ddraw_surface
*target_impl
= unsafe_impl_from_IDirectDrawSurface7(target
);
1838 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
1841 TRACE("iface %p, target %p, flags %#x.\n", iface
, target
, flags
);
1843 wined3d_mutex_lock();
1845 if (!validate_surface_palette(target_impl
))
1847 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl
);
1848 wined3d_mutex_unlock();
1849 return DDERR_INVALIDCAPS
;
1852 if (!(target_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_3DDEVICE
))
1854 WARN("Surface %p is not a render target.\n", target_impl
);
1855 wined3d_mutex_unlock();
1856 return DDERR_INVALIDCAPS
;
1859 if (!(target_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_VIDEOMEMORY
))
1861 WARN("Surface %p is not in video memory.\n", target_impl
);
1862 wined3d_mutex_unlock();
1863 return DDERR_INVALIDPARAMS
;
1866 if (target_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_ZBUFFER
)
1868 WARN("Surface %p is a depth buffer.\n", target_impl
);
1869 IDirectDrawSurface7_AddRef(target
);
1870 IUnknown_Release(device
->rt_iface
);
1871 device
->rt_iface
= (IUnknown
*)target
;
1872 wined3d_mutex_unlock();
1873 return DDERR_INVALIDPIXELFORMAT
;
1876 hr
= d3d_device_set_render_target(device
, target_impl
, (IUnknown
*)target
);
1877 wined3d_mutex_unlock();
1881 static HRESULT WINAPI
d3d_device7_SetRenderTarget_FPUSetup(IDirect3DDevice7
*iface
,
1882 IDirectDrawSurface7
*NewTarget
, DWORD flags
)
1884 return d3d_device7_SetRenderTarget(iface
, NewTarget
, flags
);
1887 static HRESULT WINAPI
d3d_device7_SetRenderTarget_FPUPreserve(IDirect3DDevice7
*iface
,
1888 IDirectDrawSurface7
*NewTarget
, DWORD flags
)
1893 old_fpucw
= d3d_fpu_setup();
1894 hr
= d3d_device7_SetRenderTarget(iface
, NewTarget
, flags
);
1895 set_fpu_control_word(old_fpucw
);
1900 static HRESULT WINAPI
d3d_device3_SetRenderTarget(IDirect3DDevice3
*iface
,
1901 IDirectDrawSurface4
*target
, DWORD flags
)
1903 struct ddraw_surface
*target_impl
= unsafe_impl_from_IDirectDrawSurface4(target
);
1904 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
1907 TRACE("iface %p, target %p, flags %#x.\n", iface
, target
, flags
);
1909 wined3d_mutex_lock();
1911 if (!validate_surface_palette(target_impl
))
1913 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl
);
1914 wined3d_mutex_unlock();
1915 return DDERR_INVALIDCAPS
;
1918 if (!(target_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_3DDEVICE
))
1920 WARN("Surface %p is not a render target.\n", target_impl
);
1921 wined3d_mutex_unlock();
1922 return DDERR_INVALIDCAPS
;
1925 if (target_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_ZBUFFER
)
1927 WARN("Surface %p is a depth buffer.\n", target_impl
);
1928 IDirectDrawSurface4_AddRef(target
);
1929 IUnknown_Release(device
->rt_iface
);
1930 device
->rt_iface
= (IUnknown
*)target
;
1931 wined3d_mutex_unlock();
1932 return DDERR_INVALIDPIXELFORMAT
;
1935 if (!(target_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_VIDEOMEMORY
))
1937 WARN("Surface %p is not in video memory.\n", target_impl
);
1938 IDirectDrawSurface4_AddRef(target
);
1939 IUnknown_Release(device
->rt_iface
);
1940 device
->rt_iface
= (IUnknown
*)target
;
1941 wined3d_mutex_unlock();
1945 hr
= d3d_device_set_render_target(device
, target_impl
, (IUnknown
*)target
);
1946 wined3d_mutex_unlock();
1950 static HRESULT WINAPI
d3d_device2_SetRenderTarget(IDirect3DDevice2
*iface
,
1951 IDirectDrawSurface
*target
, DWORD flags
)
1953 struct ddraw_surface
*target_impl
= unsafe_impl_from_IDirectDrawSurface(target
);
1954 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
1957 TRACE("iface %p, target %p, flags %#x.\n", iface
, target
, flags
);
1959 wined3d_mutex_lock();
1961 if (!validate_surface_palette(target_impl
))
1963 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl
);
1964 wined3d_mutex_unlock();
1965 return DDERR_INVALIDCAPS
;
1968 if (!(target_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_3DDEVICE
))
1970 WARN("Surface %p is not a render target.\n", target_impl
);
1971 wined3d_mutex_unlock();
1972 return DDERR_INVALIDCAPS
;
1975 if (target_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_ZBUFFER
)
1977 WARN("Surface %p is a depth buffer.\n", target_impl
);
1978 IUnknown_Release(device
->rt_iface
);
1979 device
->rt_iface
= (IUnknown
*)target
;
1980 wined3d_mutex_unlock();
1981 return DDERR_INVALIDPIXELFORMAT
;
1984 if (!(target_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_VIDEOMEMORY
))
1986 WARN("Surface %p is not in video memory.\n", target_impl
);
1987 IDirectDrawSurface_AddRef(target
);
1988 IUnknown_Release(device
->rt_iface
);
1989 device
->rt_iface
= (IUnknown
*)target
;
1990 wined3d_mutex_unlock();
1994 hr
= d3d_device_set_render_target(device
, target_impl
, (IUnknown
*)target
);
1995 wined3d_mutex_unlock();
1999 /*****************************************************************************
2000 * IDirect3DDevice7::GetRenderTarget
2002 * Returns the current render target.
2003 * This is handled locally, because the WineD3D render target's parent
2006 * Version 2, 3 and 7
2009 * RenderTarget: Address to store the surface interface pointer
2013 * DDERR_INVALIDPARAMS if RenderTarget == NULL
2015 *****************************************************************************/
2016 static HRESULT WINAPI
d3d_device7_GetRenderTarget(IDirect3DDevice7
*iface
, IDirectDrawSurface7
**RenderTarget
)
2018 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
2021 TRACE("iface %p, target %p.\n", iface
, RenderTarget
);
2024 return DDERR_INVALIDPARAMS
;
2026 wined3d_mutex_lock();
2027 hr
= IUnknown_QueryInterface(device
->rt_iface
, &IID_IDirectDrawSurface7
, (void **)RenderTarget
);
2028 wined3d_mutex_unlock();
2033 static HRESULT WINAPI
d3d_device3_GetRenderTarget(IDirect3DDevice3
*iface
, IDirectDrawSurface4
**RenderTarget
)
2035 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
2036 IDirectDrawSurface7
*RenderTarget7
;
2037 struct ddraw_surface
*RenderTargetImpl
;
2040 TRACE("iface %p, target %p.\n", iface
, RenderTarget
);
2043 return DDERR_INVALIDPARAMS
;
2045 hr
= d3d_device7_GetRenderTarget(&device
->IDirect3DDevice7_iface
, &RenderTarget7
);
2046 if(hr
!= D3D_OK
) return hr
;
2047 RenderTargetImpl
= impl_from_IDirectDrawSurface7(RenderTarget7
);
2048 *RenderTarget
= &RenderTargetImpl
->IDirectDrawSurface4_iface
;
2049 IDirectDrawSurface4_AddRef(*RenderTarget
);
2050 IDirectDrawSurface7_Release(RenderTarget7
);
2054 static HRESULT WINAPI
d3d_device2_GetRenderTarget(IDirect3DDevice2
*iface
, IDirectDrawSurface
**RenderTarget
)
2056 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
2057 IDirectDrawSurface7
*RenderTarget7
;
2058 struct ddraw_surface
*RenderTargetImpl
;
2061 TRACE("iface %p, target %p.\n", iface
, RenderTarget
);
2064 return DDERR_INVALIDPARAMS
;
2066 hr
= d3d_device7_GetRenderTarget(&device
->IDirect3DDevice7_iface
, &RenderTarget7
);
2067 if(hr
!= D3D_OK
) return hr
;
2068 RenderTargetImpl
= impl_from_IDirectDrawSurface7(RenderTarget7
);
2069 *RenderTarget
= &RenderTargetImpl
->IDirectDrawSurface_iface
;
2070 IDirectDrawSurface_AddRef(*RenderTarget
);
2071 IDirectDrawSurface7_Release(RenderTarget7
);
2075 /*****************************************************************************
2076 * IDirect3DDevice3::Begin
2078 * Begins a description block of vertices. This is similar to glBegin()
2079 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2080 * described with IDirect3DDevice::Vertex are drawn.
2085 * PrimitiveType: The type of primitives to draw
2086 * VertexTypeDesc: A flexible vertex format description of the vertices
2087 * Flags: Some flags..
2092 *****************************************************************************/
2093 static HRESULT WINAPI
d3d_device3_Begin(IDirect3DDevice3
*iface
,
2094 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
, DWORD flags
)
2096 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
2098 TRACE("iface %p, primitive_type %#x, fvf %#x, flags %#x.\n",
2099 iface
, primitive_type
, fvf
, flags
);
2101 wined3d_mutex_lock();
2102 device
->primitive_type
= primitive_type
;
2103 device
->vertex_type
= fvf
;
2104 device
->render_flags
= flags
;
2105 device
->vertex_size
= get_flexible_vertex_size(device
->vertex_type
);
2106 device
->nb_vertices
= 0;
2107 wined3d_mutex_unlock();
2112 static HRESULT WINAPI
d3d_device2_Begin(IDirect3DDevice2
*iface
,
2113 D3DPRIMITIVETYPE primitive_type
, D3DVERTEXTYPE vertex_type
, DWORD flags
)
2115 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
2118 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2119 iface
, primitive_type
, vertex_type
, flags
);
2121 switch (vertex_type
)
2123 case D3DVT_VERTEX
: fvf
= D3DFVF_VERTEX
; break;
2124 case D3DVT_LVERTEX
: fvf
= D3DFVF_LVERTEX
; break;
2125 case D3DVT_TLVERTEX
: fvf
= D3DFVF_TLVERTEX
; break;
2127 ERR("Unexpected vertex type %#x.\n", vertex_type
);
2128 return DDERR_INVALIDPARAMS
; /* Should never happen */
2131 return d3d_device3_Begin(&device
->IDirect3DDevice3_iface
, primitive_type
, fvf
, flags
);
2134 /*****************************************************************************
2135 * IDirect3DDevice3::BeginIndexed
2137 * Draws primitives based on vertices in a vertex array which are specified
2143 * PrimitiveType: Primitive type to draw
2144 * VertexType: A FVF description of the vertex format
2145 * Vertices: pointer to an array containing the vertices
2146 * NumVertices: The number of vertices in the vertex array
2147 * Flags: Some flags ...
2150 * D3D_OK, because it's a stub
2152 *****************************************************************************/
2153 static HRESULT WINAPI
d3d_device3_BeginIndexed(IDirect3DDevice3
*iface
,
2154 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
,
2155 void *vertices
, DWORD vertex_count
, DWORD flags
)
2157 FIXME("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2158 iface
, primitive_type
, fvf
, vertices
, vertex_count
, flags
);
2164 static HRESULT WINAPI
d3d_device2_BeginIndexed(IDirect3DDevice2
*iface
,
2165 D3DPRIMITIVETYPE primitive_type
, D3DVERTEXTYPE vertex_type
,
2166 void *vertices
, DWORD vertex_count
, DWORD flags
)
2168 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
2171 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2172 iface
, primitive_type
, vertex_type
, vertices
, vertex_count
, flags
);
2174 switch (vertex_type
)
2176 case D3DVT_VERTEX
: fvf
= D3DFVF_VERTEX
; break;
2177 case D3DVT_LVERTEX
: fvf
= D3DFVF_LVERTEX
; break;
2178 case D3DVT_TLVERTEX
: fvf
= D3DFVF_TLVERTEX
; break;
2180 ERR("Unexpected vertex type %#x.\n", vertex_type
);
2181 return DDERR_INVALIDPARAMS
; /* Should never happen */
2184 return d3d_device3_BeginIndexed(&device
->IDirect3DDevice3_iface
,
2185 primitive_type
, fvf
, vertices
, vertex_count
, flags
);
2188 /*****************************************************************************
2189 * IDirect3DDevice3::Vertex
2191 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2192 * drawn vertices in a vertex buffer. If the buffer is too small, its
2193 * size is increased.
2198 * Vertex: Pointer to the vertex
2201 * D3D_OK, on success
2202 * DDERR_INVALIDPARAMS if Vertex is NULL
2204 *****************************************************************************/
2205 static HRESULT WINAPI
d3d_device3_Vertex(IDirect3DDevice3
*iface
, void *vertex
)
2207 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
2209 TRACE("iface %p, vertex %p.\n", iface
, vertex
);
2212 return DDERR_INVALIDPARAMS
;
2214 wined3d_mutex_lock();
2215 if ((device
->nb_vertices
+ 1) * device
->vertex_size
> device
->buffer_size
)
2219 device
->buffer_size
= device
->buffer_size
? device
->buffer_size
* 2 : device
->vertex_size
* 3;
2220 old_buffer
= device
->sysmem_vertex_buffer
;
2221 device
->sysmem_vertex_buffer
= HeapAlloc(GetProcessHeap(), 0, device
->buffer_size
);
2224 memcpy(device
->sysmem_vertex_buffer
, old_buffer
, device
->nb_vertices
* device
->vertex_size
);
2225 HeapFree(GetProcessHeap(), 0, old_buffer
);
2229 memcpy(device
->sysmem_vertex_buffer
+ device
->nb_vertices
++ * device
->vertex_size
, vertex
, device
->vertex_size
);
2230 wined3d_mutex_unlock();
2235 static HRESULT WINAPI
d3d_device2_Vertex(IDirect3DDevice2
*iface
, void *vertex
)
2237 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
2239 TRACE("iface %p, vertex %p.\n", iface
, vertex
);
2241 return d3d_device3_Vertex(&device
->IDirect3DDevice3_iface
, vertex
);
2244 /*****************************************************************************
2245 * IDirect3DDevice3::Index
2247 * Specifies an index to a vertex to be drawn. The vertex array has to
2248 * be specified with BeginIndexed first.
2251 * VertexIndex: The index of the vertex to draw
2254 * D3D_OK because it's a stub
2256 *****************************************************************************/
2257 static HRESULT WINAPI
d3d_device3_Index(IDirect3DDevice3
*iface
, WORD index
)
2259 FIXME("iface %p, index %#x stub!\n", iface
, index
);
2264 static HRESULT WINAPI
d3d_device2_Index(IDirect3DDevice2
*iface
, WORD index
)
2266 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
2268 TRACE("iface %p, index %#x.\n", iface
, index
);
2270 return d3d_device3_Index(&device
->IDirect3DDevice3_iface
, index
);
2273 /*****************************************************************************
2274 * IDirect3DDevice7::GetRenderState
2276 * Returns the value of a render state. The possible render states are
2277 * defined in include/d3dtypes.h
2279 * Version 2, 3 and 7
2282 * RenderStateType: Render state to return the current setting of
2283 * Value: Address to store the value at
2286 * D3D_OK on success,
2287 * DDERR_INVALIDPARAMS if Value == NULL
2289 *****************************************************************************/
2290 static HRESULT
d3d_device7_GetRenderState(IDirect3DDevice7
*iface
,
2291 D3DRENDERSTATETYPE state
, DWORD
*value
)
2293 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
2294 HRESULT hr
= D3D_OK
;
2296 TRACE("iface %p, state %#x, value %p.\n", iface
, state
, value
);
2299 return DDERR_INVALIDPARAMS
;
2301 wined3d_mutex_lock();
2304 case D3DRENDERSTATE_TEXTUREMAG
:
2306 enum wined3d_texture_filter_type tex_mag
;
2308 tex_mag
= wined3d_device_get_sampler_state(device
->wined3d_device
, 0, WINED3D_SAMP_MAG_FILTER
);
2311 case WINED3D_TEXF_POINT
:
2312 *value
= D3DFILTER_NEAREST
;
2314 case WINED3D_TEXF_LINEAR
:
2315 *value
= D3DFILTER_LINEAR
;
2318 ERR("Unhandled texture mag %d !\n",tex_mag
);
2324 case D3DRENDERSTATE_TEXTUREMIN
:
2326 enum wined3d_texture_filter_type tex_min
;
2327 enum wined3d_texture_filter_type tex_mip
;
2329 tex_min
= wined3d_device_get_sampler_state(device
->wined3d_device
, 0, WINED3D_SAMP_MIN_FILTER
);
2330 tex_mip
= wined3d_device_get_sampler_state(device
->wined3d_device
, 0, WINED3D_SAMP_MIP_FILTER
);
2333 case WINED3D_TEXF_POINT
:
2336 case WINED3D_TEXF_NONE
:
2337 *value
= D3DFILTER_NEAREST
;
2339 case WINED3D_TEXF_POINT
:
2340 *value
= D3DFILTER_MIPNEAREST
;
2342 case WINED3D_TEXF_LINEAR
:
2343 *value
= D3DFILTER_LINEARMIPNEAREST
;
2346 ERR("Unhandled mip filter %#x.\n", tex_mip
);
2347 *value
= D3DFILTER_NEAREST
;
2351 case WINED3D_TEXF_LINEAR
:
2354 case WINED3D_TEXF_NONE
:
2355 *value
= D3DFILTER_LINEAR
;
2357 case WINED3D_TEXF_POINT
:
2358 *value
= D3DFILTER_MIPLINEAR
;
2360 case WINED3D_TEXF_LINEAR
:
2361 *value
= D3DFILTER_LINEARMIPLINEAR
;
2364 ERR("Unhandled mip filter %#x.\n", tex_mip
);
2365 *value
= D3DFILTER_LINEAR
;
2370 ERR("Unhandled texture min filter %#x.\n",tex_min
);
2371 *value
= D3DFILTER_NEAREST
;
2377 case D3DRENDERSTATE_TEXTUREADDRESS
:
2378 case D3DRENDERSTATE_TEXTUREADDRESSU
:
2379 *value
= wined3d_device_get_sampler_state(device
->wined3d_device
, 0, WINED3D_SAMP_ADDRESS_U
);
2381 case D3DRENDERSTATE_TEXTUREADDRESSV
:
2382 *value
= wined3d_device_get_sampler_state(device
->wined3d_device
, 0, WINED3D_SAMP_ADDRESS_V
);
2385 case D3DRENDERSTATE_BORDERCOLOR
:
2386 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2390 case D3DRENDERSTATE_TEXTUREHANDLE
:
2391 case D3DRENDERSTATE_TEXTUREMAPBLEND
:
2392 WARN("Render state %#x is invalid in d3d7.\n", state
);
2393 hr
= DDERR_INVALIDPARAMS
;
2396 case D3DRENDERSTATE_ZBIAS
:
2397 *value
= wined3d_device_get_render_state(device
->wined3d_device
, WINED3D_RS_DEPTHBIAS
);
2401 if (state
>= D3DRENDERSTATE_STIPPLEPATTERN00
2402 && state
<= D3DRENDERSTATE_STIPPLEPATTERN31
)
2404 FIXME("Unhandled stipple pattern render state (%#x).\n", state
);
2408 *value
= wined3d_device_get_render_state(device
->wined3d_device
, state
);
2410 wined3d_mutex_unlock();
2415 static HRESULT WINAPI
d3d_device7_GetRenderState_FPUSetup(IDirect3DDevice7
*iface
,
2416 D3DRENDERSTATETYPE state
, DWORD
*value
)
2418 return d3d_device7_GetRenderState(iface
, state
, value
);
2421 static HRESULT WINAPI
d3d_device7_GetRenderState_FPUPreserve(IDirect3DDevice7
*iface
,
2422 D3DRENDERSTATETYPE state
, DWORD
*value
)
2427 old_fpucw
= d3d_fpu_setup();
2428 hr
= d3d_device7_GetRenderState(iface
, state
, value
);
2429 set_fpu_control_word(old_fpucw
);
2434 static HRESULT WINAPI
d3d_device3_GetRenderState(IDirect3DDevice3
*iface
,
2435 D3DRENDERSTATETYPE state
, DWORD
*value
)
2437 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
2439 TRACE("iface %p, state %#x, value %p.\n", iface
, state
, value
);
2443 case D3DRENDERSTATE_TEXTUREHANDLE
:
2445 /* This state is wrapped to SetTexture in SetRenderState, so
2446 * it has to be wrapped to GetTexture here. */
2447 struct wined3d_texture
*tex
= NULL
;
2450 wined3d_mutex_lock();
2451 if ((tex
= wined3d_device_get_texture(device
->wined3d_device
, 0)))
2453 /* The parent of the texture is the IDirectDrawSurface7
2454 * interface of the ddraw surface. */
2455 struct ddraw_texture
*parent
= wined3d_texture_get_parent(tex
);
2457 *value
= parent
->root
->Handle
;
2459 wined3d_mutex_unlock();
2464 case D3DRENDERSTATE_TEXTUREMAPBLEND
:
2466 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2467 the mapping to get the value. */
2468 DWORD colorop
, colorarg1
, colorarg2
;
2469 DWORD alphaop
, alphaarg1
, alphaarg2
;
2471 wined3d_mutex_lock();
2473 device
->legacyTextureBlending
= TRUE
;
2475 colorop
= wined3d_device_get_texture_stage_state(device
->wined3d_device
, 0, WINED3D_TSS_COLOR_OP
);
2476 colorarg1
= wined3d_device_get_texture_stage_state(device
->wined3d_device
, 0, WINED3D_TSS_COLOR_ARG1
);
2477 colorarg2
= wined3d_device_get_texture_stage_state(device
->wined3d_device
, 0, WINED3D_TSS_COLOR_ARG2
);
2478 alphaop
= wined3d_device_get_texture_stage_state(device
->wined3d_device
, 0, WINED3D_TSS_ALPHA_OP
);
2479 alphaarg1
= wined3d_device_get_texture_stage_state(device
->wined3d_device
, 0, WINED3D_TSS_ALPHA_ARG1
);
2480 alphaarg2
= wined3d_device_get_texture_stage_state(device
->wined3d_device
, 0, WINED3D_TSS_ALPHA_ARG2
);
2482 if (colorop
== WINED3D_TOP_SELECT_ARG1
&& colorarg1
== WINED3DTA_TEXTURE
2483 && alphaop
== WINED3D_TOP_SELECT_ARG1
&& alphaarg1
== WINED3DTA_TEXTURE
)
2484 *value
= D3DTBLEND_DECAL
;
2485 else if (colorop
== WINED3D_TOP_SELECT_ARG1
&& colorarg1
== WINED3DTA_TEXTURE
2486 && alphaop
== WINED3D_TOP_MODULATE
2487 && alphaarg1
== WINED3DTA_TEXTURE
&& alphaarg2
== WINED3DTA_CURRENT
)
2488 *value
= D3DTBLEND_DECALALPHA
;
2489 else if (colorop
== WINED3D_TOP_MODULATE
2490 && colorarg1
== WINED3DTA_TEXTURE
&& colorarg2
== WINED3DTA_CURRENT
2491 && alphaop
== WINED3D_TOP_MODULATE
2492 && alphaarg1
== WINED3DTA_TEXTURE
&& alphaarg2
== WINED3DTA_CURRENT
)
2493 *value
= D3DTBLEND_MODULATEALPHA
;
2496 struct wined3d_texture
*tex
= NULL
;
2497 BOOL tex_alpha
= FALSE
;
2498 DDPIXELFORMAT ddfmt
;
2500 if ((tex
= wined3d_device_get_texture(device
->wined3d_device
, 0)))
2502 struct wined3d_resource_desc desc
;
2504 wined3d_resource_get_desc(wined3d_texture_get_resource(tex
), &desc
);
2505 ddfmt
.dwSize
= sizeof(ddfmt
);
2506 ddrawformat_from_wined3dformat(&ddfmt
, desc
.format
);
2507 if (ddfmt
.u5
.dwRGBAlphaBitMask
)
2511 if (!(colorop
== WINED3D_TOP_MODULATE
2512 && colorarg1
== WINED3DTA_TEXTURE
&& colorarg2
== WINED3DTA_CURRENT
2513 && alphaop
== (tex_alpha
? WINED3D_TOP_SELECT_ARG1
: WINED3D_TOP_SELECT_ARG2
)
2514 && alphaarg1
== WINED3DTA_TEXTURE
&& alphaarg2
== WINED3DTA_CURRENT
))
2515 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous.\n");
2517 *value
= D3DTBLEND_MODULATE
;
2520 wined3d_mutex_unlock();
2525 case D3DRENDERSTATE_LIGHTING
:
2526 case D3DRENDERSTATE_NORMALIZENORMALS
:
2527 case D3DRENDERSTATE_LOCALVIEWER
:
2528 *value
= 0xffffffff;
2532 return IDirect3DDevice7_GetRenderState(&device
->IDirect3DDevice7_iface
, state
, value
);
2536 static HRESULT WINAPI
d3d_device2_GetRenderState(IDirect3DDevice2
*iface
,
2537 D3DRENDERSTATETYPE state
, DWORD
*value
)
2539 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
2541 TRACE("iface %p, state %#x, value %p.\n", iface
, state
, value
);
2543 return IDirect3DDevice3_GetRenderState(&device
->IDirect3DDevice3_iface
, state
, value
);
2546 /*****************************************************************************
2547 * IDirect3DDevice7::SetRenderState
2549 * Sets a render state. The possible render states are defined in
2550 * include/d3dtypes.h
2552 * Version 2, 3 and 7
2555 * RenderStateType: State to set
2556 * Value: Value to assign to that state
2558 *****************************************************************************/
2559 static HRESULT
d3d_device7_SetRenderState(IDirect3DDevice7
*iface
,
2560 D3DRENDERSTATETYPE state
, DWORD value
)
2562 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
2563 HRESULT hr
= D3D_OK
;
2565 TRACE("iface %p, state %#x, value %#x.\n", iface
, state
, value
);
2567 wined3d_mutex_lock();
2568 /* Some render states need special care */
2572 * The ddraw texture filter mapping works like this:
2573 * D3DFILTER_NEAREST Point min/mag, no mip
2574 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2575 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2577 * D3DFILTER_LINEAR Linear min/mag, no mip
2578 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2579 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2581 * This is the opposite of the GL naming convention,
2582 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2584 case D3DRENDERSTATE_TEXTUREMAG
:
2586 enum wined3d_texture_filter_type tex_mag
;
2590 case D3DFILTER_NEAREST
:
2591 case D3DFILTER_MIPNEAREST
:
2592 case D3DFILTER_LINEARMIPNEAREST
:
2593 tex_mag
= WINED3D_TEXF_POINT
;
2595 case D3DFILTER_LINEAR
:
2596 case D3DFILTER_MIPLINEAR
:
2597 case D3DFILTER_LINEARMIPLINEAR
:
2598 tex_mag
= WINED3D_TEXF_LINEAR
;
2601 tex_mag
= WINED3D_TEXF_POINT
;
2602 FIXME("Unhandled texture mag %#x.\n", value
);
2606 wined3d_device_set_sampler_state(device
->wined3d_device
, 0, WINED3D_SAMP_MAG_FILTER
, tex_mag
);
2610 case D3DRENDERSTATE_TEXTUREMIN
:
2612 enum wined3d_texture_filter_type tex_min
;
2613 enum wined3d_texture_filter_type tex_mip
;
2617 case D3DFILTER_NEAREST
:
2618 tex_min
= WINED3D_TEXF_POINT
;
2619 tex_mip
= WINED3D_TEXF_NONE
;
2621 case D3DFILTER_LINEAR
:
2622 tex_min
= WINED3D_TEXF_LINEAR
;
2623 tex_mip
= WINED3D_TEXF_NONE
;
2625 case D3DFILTER_MIPNEAREST
:
2626 tex_min
= WINED3D_TEXF_POINT
;
2627 tex_mip
= WINED3D_TEXF_POINT
;
2629 case D3DFILTER_MIPLINEAR
:
2630 tex_min
= WINED3D_TEXF_LINEAR
;
2631 tex_mip
= WINED3D_TEXF_POINT
;
2633 case D3DFILTER_LINEARMIPNEAREST
:
2634 tex_min
= WINED3D_TEXF_POINT
;
2635 tex_mip
= WINED3D_TEXF_LINEAR
;
2637 case D3DFILTER_LINEARMIPLINEAR
:
2638 tex_min
= WINED3D_TEXF_LINEAR
;
2639 tex_mip
= WINED3D_TEXF_LINEAR
;
2643 FIXME("Unhandled texture min %#x.\n",value
);
2644 tex_min
= WINED3D_TEXF_POINT
;
2645 tex_mip
= WINED3D_TEXF_NONE
;
2649 wined3d_device_set_sampler_state(device
->wined3d_device
,
2650 0, WINED3D_SAMP_MIP_FILTER
, tex_mip
);
2651 wined3d_device_set_sampler_state(device
->wined3d_device
,
2652 0, WINED3D_SAMP_MIN_FILTER
, tex_min
);
2656 case D3DRENDERSTATE_TEXTUREADDRESS
:
2657 wined3d_device_set_sampler_state(device
->wined3d_device
,
2658 0, WINED3D_SAMP_ADDRESS_V
, value
);
2660 case D3DRENDERSTATE_TEXTUREADDRESSU
:
2661 wined3d_device_set_sampler_state(device
->wined3d_device
,
2662 0, WINED3D_SAMP_ADDRESS_U
, value
);
2664 case D3DRENDERSTATE_TEXTUREADDRESSV
:
2665 wined3d_device_set_sampler_state(device
->wined3d_device
,
2666 0, WINED3D_SAMP_ADDRESS_V
, value
);
2669 case D3DRENDERSTATE_BORDERCOLOR
:
2670 /* This should probably just forward to the corresponding sampler
2671 * state. Needs tests. */
2672 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2676 case D3DRENDERSTATE_TEXTUREHANDLE
:
2677 case D3DRENDERSTATE_TEXTUREMAPBLEND
:
2678 WARN("Render state %#x is invalid in d3d7.\n", state
);
2679 hr
= DDERR_INVALIDPARAMS
;
2682 case D3DRENDERSTATE_ZBIAS
:
2683 wined3d_device_set_render_state(device
->wined3d_device
, WINED3D_RS_DEPTHBIAS
, value
);
2687 if (state
>= D3DRENDERSTATE_STIPPLEPATTERN00
2688 && state
<= D3DRENDERSTATE_STIPPLEPATTERN31
)
2690 FIXME("Unhandled stipple pattern render state (%#x).\n", state
);
2695 wined3d_device_set_render_state(device
->wined3d_device
, state
, value
);
2698 wined3d_mutex_unlock();
2703 static HRESULT WINAPI
d3d_device7_SetRenderState_FPUSetup(IDirect3DDevice7
*iface
,
2704 D3DRENDERSTATETYPE state
, DWORD value
)
2706 return d3d_device7_SetRenderState(iface
, state
, value
);
2709 static HRESULT WINAPI
d3d_device7_SetRenderState_FPUPreserve(IDirect3DDevice7
*iface
,
2710 D3DRENDERSTATETYPE state
, DWORD value
)
2715 old_fpucw
= d3d_fpu_setup();
2716 hr
= d3d_device7_SetRenderState(iface
, state
, value
);
2717 set_fpu_control_word(old_fpucw
);
2722 static HRESULT WINAPI
d3d_device3_SetRenderState(IDirect3DDevice3
*iface
,
2723 D3DRENDERSTATETYPE state
, DWORD value
)
2725 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2726 for this state can be directly mapped to texture stage colorop and alphaop, but
2727 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2728 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2729 alphaarg when needed.
2731 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2733 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2734 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2735 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2736 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2737 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2738 in device - TRUE if the app is using TEXTUREMAPBLEND.
2740 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2741 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2742 unless some broken game will be found that cares. */
2744 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
2747 TRACE("iface %p, state %#x, value %#x.\n", iface
, state
, value
);
2749 if (state
>= D3DSTATE_OVERRIDE_BIAS
)
2751 WARN("Unhandled state %#x.\n", state
);
2752 return DDERR_INVALIDPARAMS
;
2755 wined3d_mutex_lock();
2759 case D3DRENDERSTATE_TEXTUREHANDLE
:
2761 struct ddraw_surface
*surf
;
2765 hr
= wined3d_device_set_texture(device
->wined3d_device
, 0, NULL
);
2769 surf
= ddraw_get_object(&device
->handle_table
, value
- 1, DDRAW_HANDLE_SURFACE
);
2772 WARN("Invalid texture handle.\n");
2773 hr
= DDERR_INVALIDPARAMS
;
2777 hr
= IDirect3DDevice3_SetTexture(iface
, 0, &surf
->IDirect3DTexture2_iface
);
2781 case D3DRENDERSTATE_TEXTUREMAPBLEND
:
2783 device
->legacyTextureBlending
= TRUE
;
2787 case D3DTBLEND_MODULATE
:
2789 struct wined3d_texture
*tex
= NULL
;
2790 BOOL tex_alpha
= FALSE
;
2791 DDPIXELFORMAT ddfmt
;
2793 if ((tex
= wined3d_device_get_texture(device
->wined3d_device
, 0)))
2795 struct wined3d_resource_desc desc
;
2797 wined3d_resource_get_desc(wined3d_texture_get_resource(tex
), &desc
);
2798 ddfmt
.dwSize
= sizeof(ddfmt
);
2799 ddrawformat_from_wined3dformat(&ddfmt
, desc
.format
);
2800 if (ddfmt
.u5
.dwRGBAlphaBitMask
)
2805 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2806 0, WINED3D_TSS_ALPHA_OP
, WINED3D_TOP_SELECT_ARG1
);
2808 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2809 0, WINED3D_TSS_ALPHA_OP
, WINED3D_TOP_SELECT_ARG2
);
2810 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2811 0, WINED3D_TSS_ALPHA_ARG1
, WINED3DTA_TEXTURE
);
2812 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2813 0, WINED3D_TSS_ALPHA_ARG2
, WINED3DTA_CURRENT
);
2814 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2815 0, WINED3D_TSS_COLOR_ARG1
, WINED3DTA_TEXTURE
);
2816 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2817 0, WINED3D_TSS_COLOR_ARG2
, WINED3DTA_CURRENT
);
2818 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2819 0, WINED3D_TSS_COLOR_OP
, WINED3D_TOP_MODULATE
);
2824 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2825 0, WINED3D_TSS_COLOR_OP
, WINED3D_TOP_ADD
);
2826 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2827 0, WINED3D_TSS_COLOR_ARG1
, WINED3DTA_TEXTURE
);
2828 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2829 0, WINED3D_TSS_COLOR_ARG2
, WINED3DTA_CURRENT
);
2830 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2831 0, WINED3D_TSS_ALPHA_OP
, WINED3D_TOP_SELECT_ARG2
);
2832 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2833 0, WINED3D_TSS_ALPHA_ARG2
, WINED3DTA_CURRENT
);
2836 case D3DTBLEND_MODULATEALPHA
:
2837 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2838 0, WINED3D_TSS_COLOR_ARG1
, WINED3DTA_TEXTURE
);
2839 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2840 0, WINED3D_TSS_ALPHA_ARG1
, WINED3DTA_TEXTURE
);
2841 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2842 0, WINED3D_TSS_COLOR_ARG2
, WINED3DTA_CURRENT
);
2843 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2844 0, WINED3D_TSS_ALPHA_ARG2
, WINED3DTA_CURRENT
);
2845 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2846 0, WINED3D_TSS_COLOR_OP
, WINED3D_TOP_MODULATE
);
2847 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2848 0, WINED3D_TSS_ALPHA_OP
, WINED3D_TOP_MODULATE
);
2851 case D3DTBLEND_COPY
:
2852 case D3DTBLEND_DECAL
:
2853 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2854 0, WINED3D_TSS_COLOR_ARG1
, WINED3DTA_TEXTURE
);
2855 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2856 0, WINED3D_TSS_ALPHA_ARG1
, WINED3DTA_TEXTURE
);
2857 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2858 0, WINED3D_TSS_COLOR_OP
, WINED3D_TOP_SELECT_ARG1
);
2859 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2860 0, WINED3D_TSS_ALPHA_OP
, WINED3D_TOP_SELECT_ARG1
);
2863 case D3DTBLEND_DECALALPHA
:
2864 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2865 0, WINED3D_TSS_COLOR_OP
, WINED3D_TOP_BLEND_TEXTURE_ALPHA
);
2866 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2867 0, WINED3D_TSS_COLOR_ARG1
, WINED3DTA_TEXTURE
);
2868 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2869 0, WINED3D_TSS_COLOR_ARG2
, WINED3DTA_CURRENT
);
2870 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2871 0, WINED3D_TSS_ALPHA_OP
, WINED3D_TOP_SELECT_ARG2
);
2872 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
2873 0, WINED3D_TSS_ALPHA_ARG2
, WINED3DTA_CURRENT
);
2877 FIXME("Unhandled texture environment %#x.\n", value
);
2884 case D3DRENDERSTATE_LIGHTING
:
2885 case D3DRENDERSTATE_NORMALIZENORMALS
:
2886 case D3DRENDERSTATE_LOCALVIEWER
:
2891 hr
= IDirect3DDevice7_SetRenderState(&device
->IDirect3DDevice7_iface
, state
, value
);
2894 wined3d_mutex_unlock();
2899 static HRESULT WINAPI
d3d_device2_SetRenderState(IDirect3DDevice2
*iface
,
2900 D3DRENDERSTATETYPE state
, DWORD value
)
2902 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
2904 TRACE("iface %p, state %#x, value %#x.\n", iface
, state
, value
);
2906 return IDirect3DDevice3_SetRenderState(&device
->IDirect3DDevice3_iface
, state
, value
);
2909 /*****************************************************************************
2910 * Direct3DDevice3::SetLightState
2912 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2913 * light states are forwarded to Direct3DDevice7 render states
2918 * LightStateType: The light state to change
2919 * Value: The value to assign to that light state
2923 * DDERR_INVALIDPARAMS if the parameters were incorrect
2924 * Also check IDirect3DDevice7::SetRenderState
2926 *****************************************************************************/
2927 static HRESULT WINAPI
d3d_device3_SetLightState(IDirect3DDevice3
*iface
,
2928 D3DLIGHTSTATETYPE state
, DWORD value
)
2930 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
2933 TRACE("iface %p, state %#x, value %#x.\n", iface
, state
, value
);
2935 if (!state
|| (state
> D3DLIGHTSTATE_COLORVERTEX
))
2937 TRACE("Unexpected Light State Type\n");
2938 return DDERR_INVALIDPARAMS
;
2941 wined3d_mutex_lock();
2942 if (state
== D3DLIGHTSTATE_MATERIAL
)
2946 struct d3d_material
*m
;
2948 if (!(m
= ddraw_get_object(&device
->handle_table
, value
- 1, DDRAW_HANDLE_MATERIAL
)))
2950 WARN("Invalid material handle.\n");
2951 wined3d_mutex_unlock();
2952 return DDERR_INVALIDPARAMS
;
2955 material_activate(m
);
2958 device
->material
= value
;
2960 else if (state
== D3DLIGHTSTATE_COLORMODEL
)
2965 ERR("DDCOLOR_MONO should not happen!\n");
2968 /* We are already in this mode */
2969 TRACE("Setting color model to RGB (no-op).\n");
2972 ERR("Unknown color model!\n");
2973 wined3d_mutex_unlock();
2974 return DDERR_INVALIDPARAMS
;
2979 D3DRENDERSTATETYPE rs
;
2982 case D3DLIGHTSTATE_AMBIENT
: /* 2 */
2983 rs
= D3DRENDERSTATE_AMBIENT
;
2985 case D3DLIGHTSTATE_FOGMODE
: /* 4 */
2986 rs
= D3DRENDERSTATE_FOGVERTEXMODE
;
2988 case D3DLIGHTSTATE_FOGSTART
: /* 5 */
2989 rs
= D3DRENDERSTATE_FOGSTART
;
2991 case D3DLIGHTSTATE_FOGEND
: /* 6 */
2992 rs
= D3DRENDERSTATE_FOGEND
;
2994 case D3DLIGHTSTATE_FOGDENSITY
: /* 7 */
2995 rs
= D3DRENDERSTATE_FOGDENSITY
;
2997 case D3DLIGHTSTATE_COLORVERTEX
: /* 8 */
2998 rs
= D3DRENDERSTATE_COLORVERTEX
;
3001 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state
);
3002 wined3d_mutex_unlock();
3003 return DDERR_INVALIDPARAMS
;
3006 hr
= IDirect3DDevice7_SetRenderState(&device
->IDirect3DDevice7_iface
, rs
, value
);
3007 wined3d_mutex_unlock();
3010 wined3d_mutex_unlock();
3015 static HRESULT WINAPI
d3d_device2_SetLightState(IDirect3DDevice2
*iface
,
3016 D3DLIGHTSTATETYPE state
, DWORD value
)
3018 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
3020 TRACE("iface %p, state %#x, value %#x.\n", iface
, state
, value
);
3022 return d3d_device3_SetLightState(&device
->IDirect3DDevice3_iface
, state
, value
);
3025 /*****************************************************************************
3026 * IDirect3DDevice3::GetLightState
3028 * Returns the current setting of a light state. The state is read from
3029 * the Direct3DDevice7 render state.
3034 * LightStateType: The light state to return
3035 * Value: The address to store the light state setting at
3039 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3040 * Also see IDirect3DDevice7::GetRenderState
3042 *****************************************************************************/
3043 static HRESULT WINAPI
d3d_device3_GetLightState(IDirect3DDevice3
*iface
,
3044 D3DLIGHTSTATETYPE state
, DWORD
*value
)
3046 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
3049 TRACE("iface %p, state %#x, value %p.\n", iface
, state
, value
);
3051 if (!state
|| (state
> D3DLIGHTSTATE_COLORVERTEX
))
3053 TRACE("Unexpected Light State Type\n");
3054 return DDERR_INVALIDPARAMS
;
3058 return DDERR_INVALIDPARAMS
;
3060 wined3d_mutex_lock();
3061 if (state
== D3DLIGHTSTATE_MATERIAL
)
3063 *value
= device
->material
;
3065 else if (state
== D3DLIGHTSTATE_COLORMODEL
)
3067 *value
= D3DCOLOR_RGB
;
3071 D3DRENDERSTATETYPE rs
;
3074 case D3DLIGHTSTATE_AMBIENT
: /* 2 */
3075 rs
= D3DRENDERSTATE_AMBIENT
;
3077 case D3DLIGHTSTATE_FOGMODE
: /* 4 */
3078 rs
= D3DRENDERSTATE_FOGVERTEXMODE
;
3080 case D3DLIGHTSTATE_FOGSTART
: /* 5 */
3081 rs
= D3DRENDERSTATE_FOGSTART
;
3083 case D3DLIGHTSTATE_FOGEND
: /* 6 */
3084 rs
= D3DRENDERSTATE_FOGEND
;
3086 case D3DLIGHTSTATE_FOGDENSITY
: /* 7 */
3087 rs
= D3DRENDERSTATE_FOGDENSITY
;
3089 case D3DLIGHTSTATE_COLORVERTEX
: /* 8 */
3090 rs
= D3DRENDERSTATE_COLORVERTEX
;
3093 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state
);
3094 wined3d_mutex_unlock();
3095 return DDERR_INVALIDPARAMS
;
3098 hr
= IDirect3DDevice7_GetRenderState(&device
->IDirect3DDevice7_iface
, rs
, value
);
3099 wined3d_mutex_unlock();
3102 wined3d_mutex_unlock();
3107 static HRESULT WINAPI
d3d_device2_GetLightState(IDirect3DDevice2
*iface
,
3108 D3DLIGHTSTATETYPE state
, DWORD
*value
)
3110 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
3112 TRACE("iface %p, state %#x, value %p.\n", iface
, state
, value
);
3114 return d3d_device3_GetLightState(&device
->IDirect3DDevice3_iface
, state
, value
);
3117 /*****************************************************************************
3118 * IDirect3DDevice7::SetTransform
3120 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3121 * in include/d3dtypes.h.
3122 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3123 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3124 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3126 * Version 2, 3 and 7
3129 * TransformStateType: transform state to set
3130 * Matrix: Matrix to assign to the state
3134 * DDERR_INVALIDPARAMS if Matrix == NULL
3136 *****************************************************************************/
3137 static HRESULT
d3d_device7_SetTransform(IDirect3DDevice7
*iface
,
3138 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3140 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
3141 enum wined3d_transform_state wined3d_state
;
3143 TRACE("iface %p, state %#x, matrix %p.\n", iface
, state
, matrix
);
3147 case D3DTRANSFORMSTATE_WORLD
:
3148 wined3d_state
= WINED3D_TS_WORLD_MATRIX(0);
3150 case D3DTRANSFORMSTATE_WORLD1
:
3151 wined3d_state
= WINED3D_TS_WORLD_MATRIX(1);
3153 case D3DTRANSFORMSTATE_WORLD2
:
3154 wined3d_state
= WINED3D_TS_WORLD_MATRIX(2);
3156 case D3DTRANSFORMSTATE_WORLD3
:
3157 wined3d_state
= WINED3D_TS_WORLD_MATRIX(3);
3160 wined3d_state
= state
;
3164 return DDERR_INVALIDPARAMS
;
3166 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3167 wined3d_mutex_lock();
3168 wined3d_device_set_transform(device
->wined3d_device
, wined3d_state
, (struct wined3d_matrix
*)matrix
);
3169 wined3d_mutex_unlock();
3174 static HRESULT WINAPI
d3d_device7_SetTransform_FPUSetup(IDirect3DDevice7
*iface
,
3175 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3177 return d3d_device7_SetTransform(iface
, state
, matrix
);
3180 static HRESULT WINAPI
d3d_device7_SetTransform_FPUPreserve(IDirect3DDevice7
*iface
,
3181 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3186 old_fpucw
= d3d_fpu_setup();
3187 hr
= d3d_device7_SetTransform(iface
, state
, matrix
);
3188 set_fpu_control_word(old_fpucw
);
3193 static HRESULT WINAPI
d3d_device3_SetTransform(IDirect3DDevice3
*iface
,
3194 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3196 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
3198 TRACE("iface %p, state %#x, matrix %p.\n", iface
, state
, matrix
);
3201 return DDERR_INVALIDPARAMS
;
3203 if (state
== D3DTRANSFORMSTATE_PROJECTION
)
3205 D3DMATRIX projection
;
3207 wined3d_mutex_lock();
3208 multiply_matrix(&projection
, &device
->legacy_clipspace
, matrix
);
3209 wined3d_device_set_transform(device
->wined3d_device
,
3210 WINED3D_TS_PROJECTION
, (struct wined3d_matrix
*)&projection
);
3211 device
->legacy_projection
= *matrix
;
3212 wined3d_mutex_unlock();
3217 return IDirect3DDevice7_SetTransform(&device
->IDirect3DDevice7_iface
, state
, matrix
);
3220 static HRESULT WINAPI
d3d_device2_SetTransform(IDirect3DDevice2
*iface
,
3221 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3223 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
3225 TRACE("iface %p, state %#x, matrix %p.\n", iface
, state
, matrix
);
3227 return IDirect3DDevice3_SetTransform(&device
->IDirect3DDevice3_iface
, state
, matrix
);
3230 /*****************************************************************************
3231 * IDirect3DDevice7::GetTransform
3233 * Returns the matrix assigned to a transform state
3234 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3238 * TransformStateType: State to read the matrix from
3239 * Matrix: Address to store the matrix at
3243 * DDERR_INVALIDPARAMS if Matrix == NULL
3245 *****************************************************************************/
3246 static HRESULT
d3d_device7_GetTransform(IDirect3DDevice7
*iface
,
3247 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3249 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
3250 enum wined3d_transform_state wined3d_state
;
3252 TRACE("iface %p, state %#x, matrix %p.\n", iface
, state
, matrix
);
3256 case D3DTRANSFORMSTATE_WORLD
:
3257 wined3d_state
= WINED3D_TS_WORLD_MATRIX(0);
3259 case D3DTRANSFORMSTATE_WORLD1
:
3260 wined3d_state
= WINED3D_TS_WORLD_MATRIX(1);
3262 case D3DTRANSFORMSTATE_WORLD2
:
3263 wined3d_state
= WINED3D_TS_WORLD_MATRIX(2);
3265 case D3DTRANSFORMSTATE_WORLD3
:
3266 wined3d_state
= WINED3D_TS_WORLD_MATRIX(3);
3269 wined3d_state
= state
;
3273 return DDERR_INVALIDPARAMS
;
3275 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3276 wined3d_mutex_lock();
3277 wined3d_device_get_transform(device
->wined3d_device
, wined3d_state
, (struct wined3d_matrix
*)matrix
);
3278 wined3d_mutex_unlock();
3283 static HRESULT WINAPI
d3d_device7_GetTransform_FPUSetup(IDirect3DDevice7
*iface
,
3284 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3286 return d3d_device7_GetTransform(iface
, state
, matrix
);
3289 static HRESULT WINAPI
d3d_device7_GetTransform_FPUPreserve(IDirect3DDevice7
*iface
,
3290 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3295 old_fpucw
= d3d_fpu_setup();
3296 hr
= d3d_device7_GetTransform(iface
, state
, matrix
);
3297 set_fpu_control_word(old_fpucw
);
3302 static HRESULT WINAPI
d3d_device3_GetTransform(IDirect3DDevice3
*iface
,
3303 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3305 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
3307 TRACE("iface %p, state %#x, matrix %p.\n", iface
, state
, matrix
);
3310 return DDERR_INVALIDPARAMS
;
3312 if (state
== D3DTRANSFORMSTATE_PROJECTION
)
3314 wined3d_mutex_lock();
3315 *matrix
= device
->legacy_projection
;
3316 wined3d_mutex_unlock();
3320 return IDirect3DDevice7_GetTransform(&device
->IDirect3DDevice7_iface
, state
, matrix
);
3323 static HRESULT WINAPI
d3d_device2_GetTransform(IDirect3DDevice2
*iface
,
3324 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3326 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
3328 TRACE("iface %p, state %#x, matrix %p.\n", iface
, state
, matrix
);
3330 return IDirect3DDevice3_GetTransform(&device
->IDirect3DDevice3_iface
, state
, matrix
);
3333 /*****************************************************************************
3334 * IDirect3DDevice7::MultiplyTransform
3336 * Multiplies the already-set transform matrix of a transform state
3337 * with another matrix. For the world matrix, see SetTransform
3339 * Version 2, 3 and 7
3342 * TransformStateType: Transform state to multiply
3343 * D3DMatrix Matrix to multiply with.
3347 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3349 *****************************************************************************/
3350 static HRESULT
d3d_device7_MultiplyTransform(IDirect3DDevice7
*iface
,
3351 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3353 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
3354 enum wined3d_transform_state wined3d_state
;
3356 TRACE("iface %p, state %#x, matrix %p.\n", iface
, state
, matrix
);
3360 case D3DTRANSFORMSTATE_WORLD
:
3361 wined3d_state
= WINED3D_TS_WORLD_MATRIX(0);
3363 case D3DTRANSFORMSTATE_WORLD1
:
3364 wined3d_state
= WINED3D_TS_WORLD_MATRIX(1);
3366 case D3DTRANSFORMSTATE_WORLD2
:
3367 wined3d_state
= WINED3D_TS_WORLD_MATRIX(2);
3369 case D3DTRANSFORMSTATE_WORLD3
:
3370 wined3d_state
= WINED3D_TS_WORLD_MATRIX(3);
3373 wined3d_state
= state
;
3376 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3377 wined3d_mutex_lock();
3378 wined3d_device_multiply_transform(device
->wined3d_device
,
3379 wined3d_state
, (struct wined3d_matrix
*)matrix
);
3380 wined3d_mutex_unlock();
3385 static HRESULT WINAPI
d3d_device7_MultiplyTransform_FPUSetup(IDirect3DDevice7
*iface
,
3386 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3388 return d3d_device7_MultiplyTransform(iface
, state
, matrix
);
3391 static HRESULT WINAPI
d3d_device7_MultiplyTransform_FPUPreserve(IDirect3DDevice7
*iface
,
3392 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3397 old_fpucw
= d3d_fpu_setup();
3398 hr
= d3d_device7_MultiplyTransform(iface
, state
, matrix
);
3399 set_fpu_control_word(old_fpucw
);
3404 static HRESULT WINAPI
d3d_device3_MultiplyTransform(IDirect3DDevice3
*iface
,
3405 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3407 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
3409 TRACE("iface %p, state %#x, matrix %p.\n", iface
, state
, matrix
);
3411 if (state
== D3DTRANSFORMSTATE_PROJECTION
)
3413 D3DMATRIX projection
, tmp
;
3415 wined3d_mutex_lock();
3416 multiply_matrix(&tmp
, &device
->legacy_projection
, matrix
);
3417 multiply_matrix(&projection
, &device
->legacy_clipspace
, &tmp
);
3418 wined3d_device_set_transform(device
->wined3d_device
,
3419 WINED3D_TS_PROJECTION
, (struct wined3d_matrix
*)&projection
);
3420 device
->legacy_projection
= tmp
;
3421 wined3d_mutex_unlock();
3426 return IDirect3DDevice7_MultiplyTransform(&device
->IDirect3DDevice7_iface
, state
, matrix
);
3429 static HRESULT WINAPI
d3d_device2_MultiplyTransform(IDirect3DDevice2
*iface
,
3430 D3DTRANSFORMSTATETYPE state
, D3DMATRIX
*matrix
)
3432 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
3434 TRACE("iface %p, state %#x, matrix %p.\n", iface
, state
, matrix
);
3436 return IDirect3DDevice3_MultiplyTransform(&device
->IDirect3DDevice3_iface
, state
, matrix
);
3439 /*****************************************************************************
3440 * IDirect3DDevice7::DrawPrimitive
3442 * Draws primitives based on vertices in an application-provided pointer
3444 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3445 * an FVF format for D3D7
3448 * PrimitiveType: The type of the primitives to draw
3449 * Vertex type: Flexible vertex format vertex description
3450 * Vertices: Pointer to the vertex array
3451 * VertexCount: The number of vertices to draw
3452 * Flags: As usual a few flags
3456 * DDERR_INVALIDPARAMS if Vertices is NULL
3458 *****************************************************************************/
3460 /* The caller is responsible for wined3d locking */
3461 static HRESULT
d3d_device_prepare_vertex_buffer(struct d3d_device
*device
, UINT min_size
)
3465 if (device
->vertex_buffer_size
< min_size
|| !device
->vertex_buffer
)
3467 UINT size
= max(device
->vertex_buffer_size
* 2, min_size
);
3468 struct wined3d_buffer
*buffer
;
3470 TRACE("Growing vertex buffer to %u bytes\n", size
);
3472 hr
= wined3d_buffer_create_vb(device
->wined3d_device
, size
, WINED3DUSAGE_DYNAMIC
| WINED3DUSAGE_WRITEONLY
,
3473 WINED3D_POOL_DEFAULT
, NULL
, &ddraw_null_wined3d_parent_ops
, &buffer
);
3476 ERR("(%p) wined3d_buffer_create_vb failed with hr = %08x\n", device
, hr
);
3480 if (device
->vertex_buffer
)
3481 wined3d_buffer_decref(device
->vertex_buffer
);
3483 device
->vertex_buffer
= buffer
;
3484 device
->vertex_buffer_size
= size
;
3485 device
->vertex_buffer_pos
= 0;
3490 static HRESULT
d3d_device7_DrawPrimitive(IDirect3DDevice7
*iface
,
3491 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
, void *vertices
,
3492 DWORD vertex_count
, DWORD flags
)
3494 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
3495 struct wined3d_map_desc wined3d_map_desc
;
3496 struct wined3d_box wined3d_box
= {0};
3497 UINT stride
, vb_pos
, size
, align
;
3498 struct wined3d_resource
*vb
;
3501 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3502 iface
, primitive_type
, fvf
, vertices
, vertex_count
, flags
);
3506 WARN("0 vertex count.\n");
3510 /* Get the stride */
3511 stride
= get_flexible_vertex_size(fvf
);
3512 size
= vertex_count
* stride
;
3514 wined3d_mutex_lock();
3515 hr
= d3d_device_prepare_vertex_buffer(device
, size
);
3519 vb_pos
= device
->vertex_buffer_pos
;
3520 align
= vb_pos
% stride
;
3521 if (align
) align
= stride
- align
;
3522 if (vb_pos
+ size
+ align
> device
->vertex_buffer_size
)
3527 wined3d_box
.left
= vb_pos
;
3528 wined3d_box
.right
= vb_pos
+ size
;
3529 vb
= wined3d_buffer_get_resource(device
->vertex_buffer
);
3530 if (FAILED(hr
= wined3d_resource_map(vb
, 0, &wined3d_map_desc
, &wined3d_box
,
3531 vb_pos
? WINED3D_MAP_NOOVERWRITE
: WINED3D_MAP_DISCARD
)))
3533 memcpy(wined3d_map_desc
.data
, vertices
, size
);
3534 wined3d_resource_unmap(vb
, 0);
3535 device
->vertex_buffer_pos
= vb_pos
+ size
;
3537 hr
= wined3d_device_set_stream_source(device
->wined3d_device
, 0, device
->vertex_buffer
, 0, stride
);
3541 wined3d_device_set_vertex_declaration(device
->wined3d_device
, ddraw_find_decl(device
->ddraw
, fvf
));
3542 wined3d_device_set_primitive_type(device
->wined3d_device
, primitive_type
, 0);
3543 hr
= wined3d_device_draw_primitive(device
->wined3d_device
, vb_pos
/ stride
, vertex_count
);
3546 wined3d_mutex_unlock();
3550 static HRESULT WINAPI
d3d_device7_DrawPrimitive_FPUSetup(IDirect3DDevice7
*iface
,
3551 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
, void *vertices
,
3552 DWORD vertex_count
, DWORD flags
)
3554 return d3d_device7_DrawPrimitive(iface
, primitive_type
, fvf
, vertices
, vertex_count
, flags
);
3557 static HRESULT WINAPI
d3d_device7_DrawPrimitive_FPUPreserve(IDirect3DDevice7
*iface
,
3558 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
, void *vertices
,
3559 DWORD vertex_count
, DWORD flags
)
3564 old_fpucw
= d3d_fpu_setup();
3565 hr
= d3d_device7_DrawPrimitive(iface
, primitive_type
, fvf
, vertices
, vertex_count
, flags
);
3566 set_fpu_control_word(old_fpucw
);
3571 static void setup_lighting(const struct d3d_device
*device
, DWORD fvf
, DWORD flags
)
3575 /* Ignore the D3DFVF_XYZRHW case here, wined3d takes care of that */
3576 if (!device
->material
|| !(fvf
& D3DFVF_NORMAL
) || (flags
& D3DDP_DONOTLIGHT
))
3579 wined3d_device_set_render_state(device
->wined3d_device
, WINED3D_RS_LIGHTING
, enable
);
3583 static HRESULT WINAPI
d3d_device3_DrawPrimitive(IDirect3DDevice3
*iface
,
3584 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
, void *vertices
, DWORD vertex_count
,
3587 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
3589 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3590 iface
, primitive_type
, fvf
, vertices
, vertex_count
, flags
);
3592 setup_lighting(device
, fvf
, flags
);
3594 return IDirect3DDevice7_DrawPrimitive(&device
->IDirect3DDevice7_iface
,
3595 primitive_type
, fvf
, vertices
, vertex_count
, flags
);
3598 static HRESULT WINAPI
d3d_device2_DrawPrimitive(IDirect3DDevice2
*iface
,
3599 D3DPRIMITIVETYPE primitive_type
, D3DVERTEXTYPE vertex_type
, void *vertices
,
3600 DWORD vertex_count
, DWORD flags
)
3602 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
3605 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3606 iface
, primitive_type
, vertex_type
, vertices
, vertex_count
, flags
);
3608 switch (vertex_type
)
3610 case D3DVT_VERTEX
: fvf
= D3DFVF_VERTEX
; break;
3611 case D3DVT_LVERTEX
: fvf
= D3DFVF_LVERTEX
; break;
3612 case D3DVT_TLVERTEX
: fvf
= D3DFVF_TLVERTEX
; break;
3614 FIXME("Unhandled vertex type %#x.\n", vertex_type
);
3615 return DDERR_INVALIDPARAMS
; /* Should never happen */
3618 return d3d_device3_DrawPrimitive(&device
->IDirect3DDevice3_iface
,
3619 primitive_type
, fvf
, vertices
, vertex_count
, flags
);
3622 /*****************************************************************************
3623 * IDirect3DDevice7::DrawIndexedPrimitive
3625 * Draws vertices from an application-provided pointer, based on the index
3626 * numbers in a WORD array.
3628 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3629 * an FVF format for D3D7
3632 * PrimitiveType: The primitive type to draw
3633 * VertexType: The FVF vertex description
3634 * Vertices: Pointer to the vertex array
3636 * Indices: Pointer to the index array
3637 * IndexCount: Number of indices = Number of vertices to draw
3638 * Flags: As usual, some flags
3642 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3644 *****************************************************************************/
3645 /* The caller is responsible for wined3d locking */
3646 static HRESULT
d3d_device_prepare_index_buffer(struct d3d_device
*device
, UINT min_size
)
3650 if (device
->index_buffer_size
< min_size
|| !device
->index_buffer
)
3652 UINT size
= max(device
->index_buffer_size
* 2, min_size
);
3653 struct wined3d_buffer
*buffer
;
3655 TRACE("Growing index buffer to %u bytes\n", size
);
3657 hr
= wined3d_buffer_create_ib(device
->wined3d_device
, size
, WINED3DUSAGE_DYNAMIC
| WINED3DUSAGE_WRITEONLY
,
3658 WINED3D_POOL_DEFAULT
, NULL
, &ddraw_null_wined3d_parent_ops
, &buffer
);
3661 ERR("(%p) wined3d_buffer_create_ib failed with hr = %08x\n", device
, hr
);
3665 if (device
->index_buffer
)
3666 wined3d_buffer_decref(device
->index_buffer
);
3667 device
->index_buffer
= buffer
;
3668 device
->index_buffer_size
= size
;
3669 device
->index_buffer_pos
= 0;
3674 static HRESULT
d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7
*iface
,
3675 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
, void *vertices
, DWORD vertex_count
,
3676 WORD
*indices
, DWORD index_count
, DWORD flags
)
3678 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
3680 UINT stride
= get_flexible_vertex_size(fvf
);
3681 UINT vtx_size
= stride
* vertex_count
, idx_size
= index_count
* sizeof(*indices
);
3682 struct wined3d_map_desc wined3d_map_desc
;
3683 struct wined3d_box wined3d_box
= {0};
3684 struct wined3d_resource
*ib
, *vb
;
3685 UINT vb_pos
, ib_pos
, align
;
3687 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3688 "indices %p, index_count %u, flags %#x.\n",
3689 iface
, primitive_type
, fvf
, vertices
, vertex_count
, indices
, index_count
, flags
);
3691 if (!vertex_count
|| !index_count
)
3693 WARN("0 vertex or index count.\n");
3697 /* Set the D3DDevice's FVF */
3698 wined3d_mutex_lock();
3700 hr
= d3d_device_prepare_vertex_buffer(device
, vtx_size
);
3704 vb_pos
= device
->vertex_buffer_pos
;
3705 align
= vb_pos
% stride
;
3706 if (align
) align
= stride
- align
;
3707 if (vb_pos
+ vtx_size
+ align
> device
->vertex_buffer_size
)
3712 wined3d_box
.left
= vb_pos
;
3713 wined3d_box
.right
= vb_pos
+ vtx_size
;
3714 vb
= wined3d_buffer_get_resource(device
->vertex_buffer
);
3715 if (FAILED(hr
= wined3d_resource_map(vb
, 0, &wined3d_map_desc
, &wined3d_box
,
3716 vb_pos
? WINED3D_MAP_NOOVERWRITE
: WINED3D_MAP_DISCARD
)))
3718 memcpy(wined3d_map_desc
.data
, vertices
, vtx_size
);
3719 wined3d_resource_unmap(vb
, 0);
3720 device
->vertex_buffer_pos
= vb_pos
+ vtx_size
;
3722 hr
= d3d_device_prepare_index_buffer(device
, idx_size
);
3725 ib_pos
= device
->index_buffer_pos
;
3726 if (device
->index_buffer_size
- idx_size
< ib_pos
)
3729 wined3d_box
.left
= ib_pos
;
3730 wined3d_box
.right
= ib_pos
+ idx_size
;
3731 ib
= wined3d_buffer_get_resource(device
->index_buffer
);
3732 if (FAILED(hr
= wined3d_resource_map(ib
, 0, &wined3d_map_desc
, &wined3d_box
,
3733 ib_pos
? WINED3D_MAP_NOOVERWRITE
: WINED3D_MAP_DISCARD
)))
3735 memcpy(wined3d_map_desc
.data
, indices
, idx_size
);
3736 wined3d_resource_unmap(ib
, 0);
3737 device
->index_buffer_pos
= ib_pos
+ idx_size
;
3739 hr
= wined3d_device_set_stream_source(device
->wined3d_device
, 0, device
->vertex_buffer
, 0, stride
);
3742 wined3d_device_set_index_buffer(device
->wined3d_device
, device
->index_buffer
, WINED3DFMT_R16_UINT
, 0);
3744 wined3d_device_set_vertex_declaration(device
->wined3d_device
, ddraw_find_decl(device
->ddraw
, fvf
));
3745 wined3d_device_set_primitive_type(device
->wined3d_device
, primitive_type
, 0);
3746 wined3d_device_set_base_vertex_index(device
->wined3d_device
, vb_pos
/ stride
);
3747 hr
= wined3d_device_draw_indexed_primitive(device
->wined3d_device
, ib_pos
/ sizeof(*indices
), index_count
);
3750 wined3d_mutex_unlock();
3754 static HRESULT WINAPI
d3d_device7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7
*iface
,
3755 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
, void *vertices
, DWORD vertex_count
,
3756 WORD
*indices
, DWORD index_count
, DWORD flags
)
3758 return d3d_device7_DrawIndexedPrimitive(iface
, primitive_type
, fvf
,
3759 vertices
, vertex_count
, indices
, index_count
, flags
);
3762 static HRESULT WINAPI
d3d_device7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7
*iface
,
3763 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
, void *vertices
, DWORD vertex_count
,
3764 WORD
*indices
, DWORD index_count
, DWORD flags
)
3769 old_fpucw
= d3d_fpu_setup();
3770 hr
= d3d_device7_DrawIndexedPrimitive(iface
, primitive_type
, fvf
,
3771 vertices
, vertex_count
, indices
, index_count
, flags
);
3772 set_fpu_control_word(old_fpucw
);
3777 static HRESULT WINAPI
d3d_device3_DrawIndexedPrimitive(IDirect3DDevice3
*iface
,
3778 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
, void *vertices
, DWORD vertex_count
,
3779 WORD
*indices
, DWORD index_count
, DWORD flags
)
3781 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
3783 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3784 "indices %p, index_count %u, flags %#x.\n",
3785 iface
, primitive_type
, fvf
, vertices
, vertex_count
, indices
, index_count
, flags
);
3787 setup_lighting(device
, fvf
, flags
);
3789 return IDirect3DDevice7_DrawIndexedPrimitive(&device
->IDirect3DDevice7_iface
,
3790 primitive_type
, fvf
, vertices
, vertex_count
, indices
, index_count
, flags
);
3793 static HRESULT WINAPI
d3d_device2_DrawIndexedPrimitive(IDirect3DDevice2
*iface
,
3794 D3DPRIMITIVETYPE primitive_type
, D3DVERTEXTYPE vertex_type
, void *vertices
,
3795 DWORD vertex_count
, WORD
*indices
, DWORD index_count
, DWORD flags
)
3797 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
3800 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, "
3801 "indices %p, index_count %u, flags %#x.\n",
3802 iface
, primitive_type
, vertex_type
, vertices
, vertex_count
, indices
, index_count
, flags
);
3804 switch (vertex_type
)
3806 case D3DVT_VERTEX
: fvf
= D3DFVF_VERTEX
; break;
3807 case D3DVT_LVERTEX
: fvf
= D3DFVF_LVERTEX
; break;
3808 case D3DVT_TLVERTEX
: fvf
= D3DFVF_TLVERTEX
; break;
3810 ERR("Unhandled vertex type %#x.\n", vertex_type
);
3811 return DDERR_INVALIDPARAMS
; /* Should never happen */
3814 return d3d_device3_DrawIndexedPrimitive(&device
->IDirect3DDevice3_iface
,
3815 primitive_type
, fvf
, vertices
, vertex_count
, indices
, index_count
, flags
);
3818 /*****************************************************************************
3819 * IDirect3DDevice3::End
3821 * Ends a draw begun with IDirect3DDevice3::Begin or
3822 * IDirect3DDevice::BeginIndexed. The vertices specified with
3823 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
3824 * the IDirect3DDevice3::DrawPrimitive method. So far only
3825 * non-indexed mode is supported
3830 * Flags: Some flags, as usual. Don't know which are defined
3833 * The return value of IDirect3DDevice3::DrawPrimitive
3835 *****************************************************************************/
3836 static HRESULT WINAPI
d3d_device3_End(IDirect3DDevice3
*iface
, DWORD flags
)
3838 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
3840 TRACE("iface %p, flags %#x.\n", iface
, flags
);
3842 return d3d_device3_DrawPrimitive(&device
->IDirect3DDevice3_iface
, device
->primitive_type
,
3843 device
->vertex_type
, device
->sysmem_vertex_buffer
, device
->nb_vertices
, device
->render_flags
);
3846 static HRESULT WINAPI
d3d_device2_End(IDirect3DDevice2
*iface
, DWORD flags
)
3848 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
3850 TRACE("iface %p, flags %#x.\n", iface
, flags
);
3852 return d3d_device3_End(&device
->IDirect3DDevice3_iface
, flags
);
3855 /*****************************************************************************
3856 * IDirect3DDevice7::SetClipStatus
3858 * Sets the clip status. This defines things as clipping conditions and
3859 * the extents of the clipping region.
3861 * Version 2, 3 and 7
3867 * D3D_OK because it's a stub
3868 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3870 *****************************************************************************/
3871 static HRESULT WINAPI
d3d_device7_SetClipStatus(IDirect3DDevice7
*iface
, D3DCLIPSTATUS
*clip_status
)
3873 FIXME("iface %p, clip_status %p stub!\n", iface
, clip_status
);
3878 static HRESULT WINAPI
d3d_device3_SetClipStatus(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_SetClipStatus(&device
->IDirect3DDevice7_iface
, clip_status
);
3887 static HRESULT WINAPI
d3d_device2_SetClipStatus(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_SetClipStatus(&device
->IDirect3DDevice7_iface
, clip_status
);
3896 /*****************************************************************************
3897 * IDirect3DDevice7::GetClipStatus
3899 * Returns the clip status
3902 * ClipStatus: Address to write the clip status to
3905 * D3D_OK because it's a stub
3907 *****************************************************************************/
3908 static HRESULT WINAPI
d3d_device7_GetClipStatus(IDirect3DDevice7
*iface
, D3DCLIPSTATUS
*clip_status
)
3910 FIXME("iface %p, clip_status %p stub!\n", iface
, clip_status
);
3915 static HRESULT WINAPI
d3d_device3_GetClipStatus(IDirect3DDevice3
*iface
, D3DCLIPSTATUS
*clip_status
)
3917 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
3919 TRACE("iface %p, clip_status %p.\n", iface
, clip_status
);
3921 return IDirect3DDevice7_GetClipStatus(&device
->IDirect3DDevice7_iface
, clip_status
);
3924 static HRESULT WINAPI
d3d_device2_GetClipStatus(IDirect3DDevice2
*iface
, D3DCLIPSTATUS
*clip_status
)
3926 struct d3d_device
*device
= impl_from_IDirect3DDevice2(iface
);
3928 TRACE("iface %p, clip_status %p.\n", iface
, clip_status
);
3930 return IDirect3DDevice7_GetClipStatus(&device
->IDirect3DDevice7_iface
, clip_status
);
3933 /*****************************************************************************
3934 * IDirect3DDevice::DrawPrimitiveStrided
3936 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3941 * PrimitiveType: The primitive type to draw
3942 * VertexType: The FVF description of the vertices to draw (for the stride??)
3943 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3944 * the vertex data locations
3945 * VertexCount: The number of vertices to draw
3949 * D3D_OK, because it's a stub
3950 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3952 *****************************************************************************/
3953 static void pack_strided_data(BYTE
*dst
, DWORD count
, const D3DDRAWPRIMITIVESTRIDEDDATA
*src
, DWORD fvf
)
3955 DWORD i
, tex
, offset
;
3957 for (i
= 0; i
< count
; i
++)
3959 /* The contents of the strided data are determined by the fvf,
3960 * not by the members set in src. So it's valid
3961 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3962 * not set in the fvf. */
3963 if (fvf
& D3DFVF_POSITION_MASK
)
3965 offset
= i
* src
->position
.dwStride
;
3966 if (fvf
& D3DFVF_XYZRHW
)
3968 memcpy(dst
, ((BYTE
*)src
->position
.lpvData
) + offset
, 4 * sizeof(float));
3969 dst
+= 4 * sizeof(float);
3973 memcpy(dst
, ((BYTE
*)src
->position
.lpvData
) + offset
, 3 * sizeof(float));
3974 dst
+= 3 * sizeof(float);
3978 if (fvf
& D3DFVF_NORMAL
)
3980 offset
= i
* src
->normal
.dwStride
;
3981 memcpy(dst
, ((BYTE
*)src
->normal
.lpvData
) + offset
, 3 * sizeof(float));
3982 dst
+= 3 * sizeof(float);
3985 if (fvf
& D3DFVF_DIFFUSE
)
3987 offset
= i
* src
->diffuse
.dwStride
;
3988 memcpy(dst
, ((BYTE
*)src
->diffuse
.lpvData
) + offset
, sizeof(DWORD
));
3989 dst
+= sizeof(DWORD
);
3992 if (fvf
& D3DFVF_SPECULAR
)
3994 offset
= i
* src
->specular
.dwStride
;
3995 memcpy(dst
, ((BYTE
*)src
->specular
.lpvData
) + offset
, sizeof(DWORD
));
3996 dst
+= sizeof(DWORD
);
3999 for (tex
= 0; tex
< GET_TEXCOUNT_FROM_FVF(fvf
); ++tex
)
4001 DWORD attrib_count
= GET_TEXCOORD_SIZE_FROM_FVF(fvf
, tex
);
4002 offset
= i
* src
->textureCoords
[tex
].dwStride
;
4003 memcpy(dst
, ((BYTE
*)src
->textureCoords
[tex
].lpvData
) + offset
, attrib_count
* sizeof(float));
4004 dst
+= attrib_count
* sizeof(float);
4009 static HRESULT
d3d_device7_DrawPrimitiveStrided(IDirect3DDevice7
*iface
, D3DPRIMITIVETYPE primitive_type
,
4010 DWORD fvf
, D3DDRAWPRIMITIVESTRIDEDDATA
*strided_data
, DWORD vertex_count
, DWORD flags
)
4012 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
4014 UINT dst_stride
= get_flexible_vertex_size(fvf
);
4015 UINT dst_size
= dst_stride
* vertex_count
;
4016 struct wined3d_map_desc wined3d_map_desc
;
4017 struct wined3d_box wined3d_box
= {0};
4018 struct wined3d_resource
*vb
;
4021 TRACE("iface %p, primitive_type %#x, fvf %#x, strided_data %p, vertex_count %u, flags %#x.\n",
4022 iface
, primitive_type
, fvf
, strided_data
, vertex_count
, flags
);
4026 WARN("0 vertex count.\n");
4030 wined3d_mutex_lock();
4031 hr
= d3d_device_prepare_vertex_buffer(device
, dst_size
);
4035 vb_pos
= device
->vertex_buffer_pos
;
4036 align
= vb_pos
% dst_stride
;
4037 if (align
) align
= dst_stride
- align
;
4038 if (vb_pos
+ dst_size
+ align
> device
->vertex_buffer_size
)
4043 wined3d_box
.left
= vb_pos
;
4044 wined3d_box
.right
= vb_pos
+ dst_size
;
4045 vb
= wined3d_buffer_get_resource(device
->vertex_buffer
);
4046 if (FAILED(hr
= wined3d_resource_map(vb
, 0, &wined3d_map_desc
, &wined3d_box
,
4047 vb_pos
? WINED3D_MAP_NOOVERWRITE
: WINED3D_MAP_DISCARD
)))
4049 pack_strided_data(wined3d_map_desc
.data
, vertex_count
, strided_data
, fvf
);
4050 wined3d_resource_unmap(vb
, 0);
4051 device
->vertex_buffer_pos
= vb_pos
+ dst_size
;
4053 hr
= wined3d_device_set_stream_source(device
->wined3d_device
, 0, device
->vertex_buffer
, 0, dst_stride
);
4056 wined3d_device_set_vertex_declaration(device
->wined3d_device
, ddraw_find_decl(device
->ddraw
, fvf
));
4058 wined3d_device_set_primitive_type(device
->wined3d_device
, primitive_type
, 0);
4059 hr
= wined3d_device_draw_primitive(device
->wined3d_device
, vb_pos
/ dst_stride
, vertex_count
);
4062 wined3d_mutex_unlock();
4066 static HRESULT WINAPI
d3d_device7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7
*iface
,
4067 D3DPRIMITIVETYPE PrimitiveType
, DWORD VertexType
,
4068 D3DDRAWPRIMITIVESTRIDEDDATA
*D3DDrawPrimStrideData
, DWORD VertexCount
, DWORD Flags
)
4070 return d3d_device7_DrawPrimitiveStrided(iface
, PrimitiveType
,
4071 VertexType
, D3DDrawPrimStrideData
, VertexCount
, Flags
);
4074 static HRESULT WINAPI
d3d_device7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7
*iface
,
4075 D3DPRIMITIVETYPE PrimitiveType
, DWORD VertexType
,
4076 D3DDRAWPRIMITIVESTRIDEDDATA
*D3DDrawPrimStrideData
, DWORD VertexCount
, DWORD Flags
)
4081 old_fpucw
= d3d_fpu_setup();
4082 hr
= d3d_device7_DrawPrimitiveStrided(iface
, PrimitiveType
,
4083 VertexType
, D3DDrawPrimStrideData
, VertexCount
, Flags
);
4084 set_fpu_control_word(old_fpucw
);
4089 static HRESULT WINAPI
d3d_device3_DrawPrimitiveStrided(IDirect3DDevice3
*iface
,
4090 D3DPRIMITIVETYPE PrimitiveType
, DWORD VertexType
,
4091 D3DDRAWPRIMITIVESTRIDEDDATA
*D3DDrawPrimStrideData
, DWORD VertexCount
, DWORD Flags
)
4093 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
4095 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
4096 iface
, PrimitiveType
, VertexType
, D3DDrawPrimStrideData
, VertexCount
, Flags
);
4098 setup_lighting(device
, VertexType
, Flags
);
4100 return IDirect3DDevice7_DrawPrimitiveStrided(&device
->IDirect3DDevice7_iface
,
4101 PrimitiveType
, VertexType
, D3DDrawPrimStrideData
, VertexCount
, Flags
);
4104 /*****************************************************************************
4105 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
4107 * Draws primitives specified by strided data locations based on indices
4115 * D3D_OK, because it's a stub
4116 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
4117 * (DDERR_INVALIDPARAMS if Indices is NULL)
4119 *****************************************************************************/
4120 static HRESULT
d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7
*iface
,
4121 D3DPRIMITIVETYPE primitive_type
, DWORD fvf
, D3DDRAWPRIMITIVESTRIDEDDATA
*strided_data
,
4122 DWORD vertex_count
, WORD
*indices
, DWORD index_count
, DWORD flags
)
4124 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
4125 UINT vtx_dst_stride
= get_flexible_vertex_size(fvf
);
4126 UINT vtx_dst_size
= vertex_count
* vtx_dst_stride
;
4127 UINT idx_size
= index_count
* sizeof(WORD
);
4128 struct wined3d_map_desc wined3d_map_desc
;
4129 struct wined3d_box wined3d_box
= {0};
4130 struct wined3d_resource
*ib
, *vb
;
4135 TRACE("iface %p, primitive_type %#x, fvf %#x, strided_data %p, "
4136 "vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4137 iface
, primitive_type
, fvf
, strided_data
, vertex_count
, indices
, index_count
, flags
);
4139 if (!vertex_count
|| !index_count
)
4141 WARN("0 vertex or index count.\n");
4145 wined3d_mutex_lock();
4147 hr
= d3d_device_prepare_vertex_buffer(device
, vtx_dst_size
);
4151 vb_pos
= device
->vertex_buffer_pos
;
4152 align
= vb_pos
% vtx_dst_stride
;
4153 if (align
) align
= vtx_dst_stride
- align
;
4154 if (vb_pos
+ vtx_dst_size
+ align
> device
->vertex_buffer_size
)
4159 wined3d_box
.left
= vb_pos
;
4160 wined3d_box
.right
= vb_pos
+ vtx_dst_size
;
4161 vb
= wined3d_buffer_get_resource(device
->vertex_buffer
);
4162 if (FAILED(hr
= wined3d_resource_map(vb
, 0, &wined3d_map_desc
, &wined3d_box
,
4163 vb_pos
? WINED3D_MAP_NOOVERWRITE
: WINED3D_MAP_DISCARD
)))
4165 pack_strided_data(wined3d_map_desc
.data
, vertex_count
, strided_data
, fvf
);
4166 wined3d_resource_unmap(vb
, 0);
4167 device
->vertex_buffer_pos
= vb_pos
+ vtx_dst_size
;
4169 hr
= d3d_device_prepare_index_buffer(device
, idx_size
);
4172 ib_pos
= device
->index_buffer_pos
;
4173 if (device
->index_buffer_size
- idx_size
< ib_pos
)
4176 wined3d_box
.left
= ib_pos
;
4177 wined3d_box
.right
= ib_pos
+ idx_size
;
4178 ib
= wined3d_buffer_get_resource(device
->index_buffer
);
4179 if (FAILED(hr
= wined3d_resource_map(ib
, 0, &wined3d_map_desc
, &wined3d_box
,
4180 ib_pos
? WINED3D_MAP_NOOVERWRITE
: WINED3D_MAP_DISCARD
)))
4182 memcpy(wined3d_map_desc
.data
, indices
, idx_size
);
4183 wined3d_resource_unmap(ib
, 0);
4184 device
->index_buffer_pos
= ib_pos
+ idx_size
;
4186 hr
= wined3d_device_set_stream_source(device
->wined3d_device
, 0, device
->vertex_buffer
, 0, vtx_dst_stride
);
4189 wined3d_device_set_index_buffer(device
->wined3d_device
, device
->index_buffer
, WINED3DFMT_R16_UINT
, 0);
4190 wined3d_device_set_base_vertex_index(device
->wined3d_device
, vb_pos
/ vtx_dst_stride
);
4192 wined3d_device_set_vertex_declaration(device
->wined3d_device
, ddraw_find_decl(device
->ddraw
, fvf
));
4193 wined3d_device_set_primitive_type(device
->wined3d_device
, primitive_type
, 0);
4194 hr
= wined3d_device_draw_indexed_primitive(device
->wined3d_device
, ib_pos
/ sizeof(WORD
), index_count
);
4197 wined3d_mutex_unlock();
4201 static HRESULT WINAPI
d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7
*iface
,
4202 D3DPRIMITIVETYPE PrimitiveType
, DWORD VertexType
,
4203 D3DDRAWPRIMITIVESTRIDEDDATA
*D3DDrawPrimStrideData
, DWORD VertexCount
,
4204 WORD
*Indices
, DWORD IndexCount
, DWORD Flags
)
4206 return d3d_device7_DrawIndexedPrimitiveStrided(iface
, PrimitiveType
, VertexType
,
4207 D3DDrawPrimStrideData
, VertexCount
, Indices
, IndexCount
, Flags
);
4210 static HRESULT WINAPI
d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7
*iface
,
4211 D3DPRIMITIVETYPE PrimitiveType
, DWORD VertexType
,
4212 D3DDRAWPRIMITIVESTRIDEDDATA
*D3DDrawPrimStrideData
, DWORD VertexCount
,
4213 WORD
*Indices
, DWORD IndexCount
, DWORD Flags
)
4218 old_fpucw
= d3d_fpu_setup();
4219 hr
= d3d_device7_DrawIndexedPrimitiveStrided(iface
, PrimitiveType
, VertexType
,
4220 D3DDrawPrimStrideData
, VertexCount
, Indices
, IndexCount
, Flags
);
4221 set_fpu_control_word(old_fpucw
);
4226 static HRESULT WINAPI
d3d_device3_DrawIndexedPrimitiveStrided(IDirect3DDevice3
*iface
,
4227 D3DPRIMITIVETYPE PrimitiveType
, DWORD VertexType
,
4228 D3DDRAWPRIMITIVESTRIDEDDATA
*D3DDrawPrimStrideData
, DWORD VertexCount
, WORD
*Indices
,
4229 DWORD IndexCount
, DWORD Flags
)
4231 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
4233 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4234 iface
, PrimitiveType
, VertexType
, D3DDrawPrimStrideData
, VertexCount
, Indices
, IndexCount
, Flags
);
4236 setup_lighting(device
, VertexType
, Flags
);
4238 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&device
->IDirect3DDevice7_iface
,
4239 PrimitiveType
, VertexType
, D3DDrawPrimStrideData
, VertexCount
, Indices
, IndexCount
, Flags
);
4242 /*****************************************************************************
4243 * IDirect3DDevice7::DrawPrimitiveVB
4245 * Draws primitives from a vertex buffer to the screen.
4250 * PrimitiveType: Type of primitive to be rendered.
4251 * D3DVertexBuf: Source Vertex Buffer
4252 * StartVertex: Index of the first vertex from the buffer to be rendered
4253 * NumVertices: Number of vertices to be rendered
4254 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4258 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4260 *****************************************************************************/
4261 static HRESULT
d3d_device7_DrawPrimitiveVB(IDirect3DDevice7
*iface
, D3DPRIMITIVETYPE primitive_type
,
4262 IDirect3DVertexBuffer7
*vb
, DWORD start_vertex
, DWORD vertex_count
, DWORD flags
)
4264 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
4265 struct d3d_vertex_buffer
*vb_impl
= unsafe_impl_from_IDirect3DVertexBuffer7(vb
);
4269 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4270 iface
, primitive_type
, vb
, start_vertex
, vertex_count
, flags
);
4274 WARN("0 vertex count.\n");
4278 stride
= get_flexible_vertex_size(vb_impl
->fvf
);
4280 wined3d_mutex_lock();
4281 wined3d_device_set_vertex_declaration(device
->wined3d_device
, vb_impl
->wined3d_declaration
);
4282 if (FAILED(hr
= wined3d_device_set_stream_source(device
->wined3d_device
,
4283 0, vb_impl
->wined3d_buffer
, 0, stride
)))
4285 WARN("Failed to set stream source, hr %#x.\n", hr
);
4286 wined3d_mutex_unlock();
4290 /* Now draw the primitives */
4291 wined3d_device_set_primitive_type(device
->wined3d_device
, primitive_type
, 0);
4292 hr
= wined3d_device_draw_primitive(device
->wined3d_device
, start_vertex
, vertex_count
);
4294 wined3d_mutex_unlock();
4299 static HRESULT WINAPI
d3d_device7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7
*iface
, D3DPRIMITIVETYPE PrimitiveType
,
4300 IDirect3DVertexBuffer7
*D3DVertexBuf
, DWORD StartVertex
, DWORD NumVertices
, DWORD Flags
)
4302 return d3d_device7_DrawPrimitiveVB(iface
, PrimitiveType
, D3DVertexBuf
, StartVertex
, NumVertices
, Flags
);
4305 static HRESULT WINAPI
d3d_device7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7
*iface
, D3DPRIMITIVETYPE PrimitiveType
,
4306 IDirect3DVertexBuffer7
*D3DVertexBuf
, DWORD StartVertex
, DWORD NumVertices
, DWORD Flags
)
4311 old_fpucw
= d3d_fpu_setup();
4312 hr
= d3d_device7_DrawPrimitiveVB(iface
, PrimitiveType
, D3DVertexBuf
, StartVertex
, NumVertices
, Flags
);
4313 set_fpu_control_word(old_fpucw
);
4318 static HRESULT WINAPI
d3d_device3_DrawPrimitiveVB(IDirect3DDevice3
*iface
, D3DPRIMITIVETYPE PrimitiveType
,
4319 IDirect3DVertexBuffer
*D3DVertexBuf
, DWORD StartVertex
, DWORD NumVertices
, DWORD Flags
)
4321 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
4322 struct d3d_vertex_buffer
*vb
= unsafe_impl_from_IDirect3DVertexBuffer7((IDirect3DVertexBuffer7
*)D3DVertexBuf
);
4324 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4325 iface
, PrimitiveType
, D3DVertexBuf
, StartVertex
, NumVertices
, Flags
);
4327 setup_lighting(device
, vb
->fvf
, Flags
);
4329 return IDirect3DDevice7_DrawPrimitiveVB(&device
->IDirect3DDevice7_iface
,
4330 PrimitiveType
, &vb
->IDirect3DVertexBuffer7_iface
, StartVertex
, NumVertices
, Flags
);
4333 /*****************************************************************************
4334 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4336 * Draws primitives from a vertex buffer to the screen
4339 * PrimitiveType: Type of primitive to be rendered.
4340 * D3DVertexBuf: Source Vertex Buffer
4341 * StartVertex: Index of the first vertex from the buffer to be rendered
4342 * NumVertices: Number of vertices to be rendered
4343 * Indices: Array of DWORDs used to index into the Vertices
4344 * IndexCount: Number of indices in Indices
4345 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4349 *****************************************************************************/
4350 static HRESULT
d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7
*iface
,
4351 D3DPRIMITIVETYPE primitive_type
, IDirect3DVertexBuffer7
*vb
,
4352 DWORD start_vertex
, DWORD vertex_count
, WORD
*indices
, DWORD index_count
, DWORD flags
)
4354 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
4355 struct d3d_vertex_buffer
*vb_impl
= unsafe_impl_from_IDirect3DVertexBuffer7(vb
);
4356 DWORD stride
= get_flexible_vertex_size(vb_impl
->fvf
);
4357 struct wined3d_map_desc wined3d_map_desc
;
4358 struct wined3d_box wined3d_box
= {0};
4359 struct wined3d_resource
*ib
;
4363 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, "
4364 "vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4365 iface
, primitive_type
, vb
, start_vertex
, vertex_count
, indices
, index_count
, flags
);
4367 if (!vertex_count
|| !index_count
)
4369 WARN("0 vertex or index count.\n");
4374 * 1) Upload the indices to the index buffer
4375 * 2) Set the index source
4376 * 3) Set the Vertex Buffer as the Stream source
4377 * 4) Call wined3d_device_draw_indexed_primitive()
4380 wined3d_mutex_lock();
4382 wined3d_device_set_vertex_declaration(device
->wined3d_device
, vb_impl
->wined3d_declaration
);
4384 hr
= d3d_device_prepare_index_buffer(device
, index_count
* sizeof(WORD
));
4387 wined3d_mutex_unlock();
4390 ib_pos
= device
->index_buffer_pos
;
4392 if (device
->index_buffer_size
- index_count
* sizeof(WORD
) < ib_pos
)
4395 /* Copy the index stream into the index buffer. */
4396 wined3d_box
.left
= ib_pos
;
4397 wined3d_box
.right
= ib_pos
+ index_count
* sizeof(WORD
);
4398 ib
= wined3d_buffer_get_resource(device
->index_buffer
);
4399 if (FAILED(hr
= wined3d_resource_map(ib
, 0, &wined3d_map_desc
, &wined3d_box
,
4400 ib_pos
? WINED3D_MAP_NOOVERWRITE
: WINED3D_MAP_DISCARD
)))
4402 ERR("Failed to map buffer, hr %#x.\n", hr
);
4403 wined3d_mutex_unlock();
4406 memcpy(wined3d_map_desc
.data
, indices
, index_count
* sizeof(WORD
));
4407 wined3d_resource_unmap(ib
, 0);
4408 device
->index_buffer_pos
= ib_pos
+ index_count
* sizeof(WORD
);
4410 /* Set the index stream */
4411 wined3d_device_set_base_vertex_index(device
->wined3d_device
, start_vertex
);
4412 wined3d_device_set_index_buffer(device
->wined3d_device
, device
->index_buffer
, WINED3DFMT_R16_UINT
, 0);
4414 /* Set the vertex stream source */
4415 if (FAILED(hr
= wined3d_device_set_stream_source(device
->wined3d_device
,
4416 0, vb_impl
->wined3d_buffer
, 0, stride
)))
4418 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", device
, hr
);
4419 wined3d_mutex_unlock();
4423 wined3d_device_set_primitive_type(device
->wined3d_device
, primitive_type
, 0);
4424 hr
= wined3d_device_draw_indexed_primitive(device
->wined3d_device
, ib_pos
/ sizeof(WORD
), index_count
);
4426 wined3d_mutex_unlock();
4431 static HRESULT WINAPI
d3d_device7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7
*iface
,
4432 D3DPRIMITIVETYPE PrimitiveType
, IDirect3DVertexBuffer7
*D3DVertexBuf
,
4433 DWORD StartVertex
, DWORD NumVertices
, WORD
*Indices
, DWORD IndexCount
, DWORD Flags
)
4435 return d3d_device7_DrawIndexedPrimitiveVB(iface
, PrimitiveType
,
4436 D3DVertexBuf
, StartVertex
, NumVertices
, Indices
, IndexCount
, Flags
);
4439 static HRESULT WINAPI
d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7
*iface
,
4440 D3DPRIMITIVETYPE PrimitiveType
, IDirect3DVertexBuffer7
*D3DVertexBuf
,
4441 DWORD StartVertex
, DWORD NumVertices
, WORD
*Indices
, DWORD IndexCount
, DWORD Flags
)
4446 old_fpucw
= d3d_fpu_setup();
4447 hr
= d3d_device7_DrawIndexedPrimitiveVB(iface
, PrimitiveType
,
4448 D3DVertexBuf
, StartVertex
, NumVertices
, Indices
, IndexCount
, Flags
);
4449 set_fpu_control_word(old_fpucw
);
4454 static HRESULT WINAPI
d3d_device3_DrawIndexedPrimitiveVB(IDirect3DDevice3
*iface
,
4455 D3DPRIMITIVETYPE PrimitiveType
, IDirect3DVertexBuffer
*D3DVertexBuf
, WORD
*Indices
,
4456 DWORD IndexCount
, DWORD Flags
)
4458 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
4459 struct d3d_vertex_buffer
*vb
= unsafe_impl_from_IDirect3DVertexBuffer7((IDirect3DVertexBuffer7
*)D3DVertexBuf
);
4461 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4462 iface
, PrimitiveType
, D3DVertexBuf
, Indices
, IndexCount
, Flags
);
4464 setup_lighting(device
, vb
->fvf
, Flags
);
4466 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&device
->IDirect3DDevice7_iface
, PrimitiveType
,
4467 &vb
->IDirect3DVertexBuffer7_iface
, 0, IndexCount
, Indices
, IndexCount
, Flags
);
4470 /*****************************************************************************
4471 * IDirect3DDevice7::ComputeSphereVisibility
4473 * Calculates the visibility of spheres in the current viewport. The spheres
4474 * are passed in the Centers and Radii arrays, the results are passed back
4475 * in the ReturnValues array. Return values are either completely visible,
4476 * partially visible or completely invisible.
4477 * The return value consists of a combination of D3DCLIP_* flags, or is
4478 * 0 if the sphere is completely visible (according to the SDK, not checked)
4483 * Centers: Array containing the sphere centers
4484 * Radii: Array containing the sphere radii
4485 * NumSpheres: The number of centers and radii in the arrays
4487 * ReturnValues: Array to write the results to
4491 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4492 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4495 *****************************************************************************/
4497 static DWORD
in_plane(UINT idx
, struct wined3d_vec4 p
, D3DVECTOR center
, D3DVALUE radius
, BOOL equality
)
4499 float distance
, norm
;
4501 norm
= sqrtf(p
.x
* p
.x
+ p
.y
* p
.y
+ p
.z
* p
.z
);
4502 distance
= (p
.x
* center
.u1
.x
+ p
.y
* center
.u2
.y
+ p
.z
* center
.u3
.z
+ p
.w
) / norm
;
4506 if (fabs(distance
) <= radius
)
4507 return D3DSTATUS_CLIPUNIONLEFT
<< idx
;
4508 if (distance
<= -radius
)
4509 return (D3DSTATUS_CLIPUNIONLEFT
| D3DSTATUS_CLIPINTERSECTIONLEFT
) << idx
;
4513 if (fabs(distance
) < radius
)
4514 return D3DSTATUS_CLIPUNIONLEFT
<< idx
;
4515 if (distance
< -radius
)
4516 return (D3DSTATUS_CLIPUNIONLEFT
| D3DSTATUS_CLIPINTERSECTIONLEFT
) << idx
;
4521 static void prepare_clip_space_planes(struct d3d_device
*device
, struct wined3d_vec4
*plane
)
4525 /* We want the wined3d matrices since those include the legacy viewport
4526 * transformation. */
4527 wined3d_mutex_lock();
4528 wined3d_device_get_transform(device
->wined3d_device
,
4529 WINED3D_TS_WORLD
, (struct wined3d_matrix
*)&m
);
4531 wined3d_device_get_transform(device
->wined3d_device
,
4532 WINED3D_TS_VIEW
, (struct wined3d_matrix
*)&temp
);
4533 multiply_matrix(&m
, &temp
, &m
);
4535 wined3d_device_get_transform(device
->wined3d_device
,
4536 WINED3D_TS_PROJECTION
, (struct wined3d_matrix
*)&temp
);
4537 multiply_matrix(&m
, &temp
, &m
);
4538 wined3d_mutex_unlock();
4541 plane
[0].x
= m
._14
+ m
._11
;
4542 plane
[0].y
= m
._24
+ m
._21
;
4543 plane
[0].z
= m
._34
+ m
._31
;
4544 plane
[0].w
= m
._44
+ m
._41
;
4547 plane
[1].x
= m
._14
- m
._11
;
4548 plane
[1].y
= m
._24
- m
._21
;
4549 plane
[1].z
= m
._34
- m
._31
;
4550 plane
[1].w
= m
._44
- m
._41
;
4553 plane
[2].x
= m
._14
- m
._12
;
4554 plane
[2].y
= m
._24
- m
._22
;
4555 plane
[2].z
= m
._34
- m
._32
;
4556 plane
[2].w
= m
._44
- m
._42
;
4559 plane
[3].x
= m
._14
+ m
._12
;
4560 plane
[3].y
= m
._24
+ m
._22
;
4561 plane
[3].z
= m
._34
+ m
._32
;
4562 plane
[3].w
= m
._44
+ m
._42
;
4571 plane
[5].x
= m
._14
- m
._13
;
4572 plane
[5].y
= m
._24
- m
._23
;
4573 plane
[5].z
= m
._34
- m
._33
;
4574 plane
[5].w
= m
._44
- m
._43
;
4577 static void compute_sphere_visibility(struct wined3d_vec4 plane
[12], DWORD enabled_planes
, BOOL equality
,
4578 D3DVECTOR
*centers
, D3DVALUE
*radii
, DWORD sphere_count
, DWORD
*return_values
)
4582 for (i
= 0; i
< sphere_count
; ++i
)
4584 return_values
[i
] = 0;
4585 for (j
= 0; j
< 12; ++j
)
4586 if (enabled_planes
& 1u << j
)
4587 return_values
[i
] |= in_plane(j
, plane
[j
], centers
[i
], radii
[i
], equality
);
4591 static HRESULT WINAPI
d3d_device7_ComputeSphereVisibility(IDirect3DDevice7
*iface
,
4592 D3DVECTOR
*centers
, D3DVALUE
*radii
, DWORD sphere_count
, DWORD flags
, DWORD
*return_values
)
4594 struct wined3d_vec4 plane
[12];
4595 DWORD enabled_planes
= 0x3f;
4596 DWORD user_clip_planes
;
4599 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4600 iface
, centers
, radii
, sphere_count
, flags
, return_values
);
4602 prepare_clip_space_planes(impl_from_IDirect3DDevice7(iface
), plane
);
4604 IDirect3DDevice7_GetRenderState(iface
, D3DRENDERSTATE_CLIPPLANEENABLE
, &user_clip_planes
);
4605 enabled_planes
|= user_clip_planes
<< 6;
4606 for (j
= 6; j
< 12; ++j
)
4607 IDirect3DDevice7_GetClipPlane(iface
, j
- 6, (D3DVALUE
*)&plane
[j
]);
4609 compute_sphere_visibility(plane
, enabled_planes
, FALSE
, centers
, radii
, sphere_count
, return_values
);
4613 static HRESULT WINAPI
d3d_device3_ComputeSphereVisibility(IDirect3DDevice3
*iface
,
4614 D3DVECTOR
*centers
, D3DVALUE
*radii
, DWORD sphere_count
, DWORD flags
, DWORD
*return_values
)
4616 static const DWORD enabled_planes
= 0x3f;
4617 struct wined3d_vec4 plane
[6];
4620 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4621 iface
, centers
, radii
, sphere_count
, flags
, return_values
);
4623 prepare_clip_space_planes(impl_from_IDirect3DDevice3(iface
), plane
);
4625 compute_sphere_visibility(plane
, enabled_planes
, TRUE
, centers
, radii
, sphere_count
, return_values
);
4626 for (i
= 0; i
< sphere_count
; ++i
)
4628 BOOL intersect_frustum
= FALSE
, outside_frustum
= FALSE
;
4629 DWORD d3d7_result
= return_values
[i
];
4631 return_values
[i
] = 0;
4633 for (j
= 0; j
< 6; ++j
)
4635 DWORD clip
= (d3d7_result
>> j
) & (D3DSTATUS_CLIPUNIONLEFT
| D3DSTATUS_CLIPINTERSECTIONLEFT
);
4637 if (clip
== D3DSTATUS_CLIPUNIONLEFT
)
4639 return_values
[i
] |= D3DVIS_INTERSECT_LEFT
<< j
* 2;
4640 intersect_frustum
= TRUE
;
4644 return_values
[i
] |= D3DVIS_OUTSIDE_LEFT
<< j
* 2;
4645 outside_frustum
= TRUE
;
4648 if (outside_frustum
)
4649 return_values
[i
] |= D3DVIS_OUTSIDE_FRUSTUM
;
4650 else if (intersect_frustum
)
4651 return_values
[i
] |= D3DVIS_INTERSECT_FRUSTUM
;
4656 /*****************************************************************************
4657 * IDirect3DDevice7::GetTexture
4659 * Returns the texture interface handle assigned to a texture stage.
4660 * The returned texture is AddRefed. This is taken from old ddraw,
4661 * not checked in Windows.
4666 * Stage: Texture stage to read the texture from
4667 * Texture: Address to store the interface pointer at
4671 * DDERR_INVALIDPARAMS if Texture is NULL
4673 *****************************************************************************/
4674 static HRESULT
d3d_device7_GetTexture(IDirect3DDevice7
*iface
,
4675 DWORD stage
, IDirectDrawSurface7
**texture
)
4677 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
4678 struct wined3d_texture
*wined3d_texture
;
4679 struct ddraw_texture
*ddraw_texture
;
4681 TRACE("iface %p, stage %u, texture %p.\n", iface
, stage
, texture
);
4684 return DDERR_INVALIDPARAMS
;
4686 wined3d_mutex_lock();
4687 if (!(wined3d_texture
= wined3d_device_get_texture(device
->wined3d_device
, stage
)))
4690 wined3d_mutex_unlock();
4694 ddraw_texture
= wined3d_texture_get_parent(wined3d_texture
);
4695 *texture
= &ddraw_texture
->root
->IDirectDrawSurface7_iface
;
4696 IDirectDrawSurface7_AddRef(*texture
);
4697 wined3d_mutex_unlock();
4702 static HRESULT WINAPI
d3d_device7_GetTexture_FPUSetup(IDirect3DDevice7
*iface
,
4703 DWORD stage
, IDirectDrawSurface7
**Texture
)
4705 return d3d_device7_GetTexture(iface
, stage
, Texture
);
4708 static HRESULT WINAPI
d3d_device7_GetTexture_FPUPreserve(IDirect3DDevice7
*iface
,
4709 DWORD stage
, IDirectDrawSurface7
**Texture
)
4714 old_fpucw
= d3d_fpu_setup();
4715 hr
= d3d_device7_GetTexture(iface
, stage
, Texture
);
4716 set_fpu_control_word(old_fpucw
);
4721 static HRESULT WINAPI
d3d_device3_GetTexture(IDirect3DDevice3
*iface
, DWORD stage
, IDirect3DTexture2
**Texture2
)
4723 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
4724 struct ddraw_surface
*ret_val_impl
;
4726 IDirectDrawSurface7
*ret_val
;
4728 TRACE("iface %p, stage %u, texture %p.\n", iface
, stage
, Texture2
);
4730 ret
= IDirect3DDevice7_GetTexture(&device
->IDirect3DDevice7_iface
, stage
, &ret_val
);
4732 ret_val_impl
= unsafe_impl_from_IDirectDrawSurface7(ret_val
);
4733 *Texture2
= ret_val_impl
? &ret_val_impl
->IDirect3DTexture2_iface
: NULL
;
4735 TRACE("Returning texture %p.\n", *Texture2
);
4740 /*****************************************************************************
4741 * IDirect3DDevice7::SetTexture
4743 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4748 * Stage: The stage to assign the texture to
4749 * Texture: Interface pointer to the texture surface
4754 *****************************************************************************/
4755 static HRESULT
d3d_device7_SetTexture(IDirect3DDevice7
*iface
,
4756 DWORD stage
, IDirectDrawSurface7
*texture
)
4758 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
4759 struct ddraw_surface
*surf
= unsafe_impl_from_IDirectDrawSurface7(texture
);
4760 struct wined3d_texture
*wined3d_texture
= NULL
;
4763 TRACE("iface %p, stage %u, texture %p.\n", iface
, stage
, texture
);
4765 if (surf
&& (surf
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_TEXTURE
))
4766 wined3d_texture
= surf
->wined3d_texture
;
4768 wined3d_mutex_lock();
4769 hr
= wined3d_device_set_texture(device
->wined3d_device
, stage
, wined3d_texture
);
4770 wined3d_mutex_unlock();
4775 static HRESULT WINAPI
d3d_device7_SetTexture_FPUSetup(IDirect3DDevice7
*iface
,
4776 DWORD stage
, IDirectDrawSurface7
*texture
)
4778 return d3d_device7_SetTexture(iface
, stage
, texture
);
4781 static HRESULT WINAPI
d3d_device7_SetTexture_FPUPreserve(IDirect3DDevice7
*iface
,
4782 DWORD stage
, IDirectDrawSurface7
*texture
)
4787 old_fpucw
= d3d_fpu_setup();
4788 hr
= d3d_device7_SetTexture(iface
, stage
, texture
);
4789 set_fpu_control_word(old_fpucw
);
4794 static HRESULT WINAPI
d3d_device3_SetTexture(IDirect3DDevice3
*iface
,
4795 DWORD stage
, IDirect3DTexture2
*texture
)
4797 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
4798 struct ddraw_surface
*tex
= unsafe_impl_from_IDirect3DTexture2(texture
);
4802 TRACE("iface %p, stage %u, texture %p.\n", iface
, stage
, texture
);
4804 wined3d_mutex_lock();
4806 if (device
->legacyTextureBlending
)
4807 IDirect3DDevice3_GetRenderState(iface
, D3DRENDERSTATE_TEXTUREMAPBLEND
, &texmapblend
);
4809 hr
= IDirect3DDevice7_SetTexture(&device
->IDirect3DDevice7_iface
, stage
, &tex
->IDirectDrawSurface7_iface
);
4811 if (device
->legacyTextureBlending
&& texmapblend
== D3DTBLEND_MODULATE
)
4813 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4814 See d3d_device3_SetRenderState() for details. */
4815 struct wined3d_texture
*tex
= NULL
;
4816 BOOL tex_alpha
= FALSE
;
4817 DDPIXELFORMAT ddfmt
;
4819 if ((tex
= wined3d_device_get_texture(device
->wined3d_device
, 0)))
4821 struct wined3d_resource_desc desc
;
4823 wined3d_resource_get_desc(wined3d_texture_get_resource(tex
), &desc
);
4824 ddfmt
.dwSize
= sizeof(ddfmt
);
4825 ddrawformat_from_wined3dformat(&ddfmt
, desc
.format
);
4826 if (ddfmt
.u5
.dwRGBAlphaBitMask
)
4830 /* Args 1 and 2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4832 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
4833 0, WINED3D_TSS_ALPHA_OP
, WINED3D_TOP_SELECT_ARG1
);
4835 wined3d_device_set_texture_stage_state(device
->wined3d_device
,
4836 0, WINED3D_TSS_ALPHA_OP
, WINED3D_TOP_SELECT_ARG2
);
4839 wined3d_mutex_unlock();
4844 static const struct tss_lookup
4849 enum wined3d_texture_stage_state texture_state
;
4850 enum wined3d_sampler_state sampler_state
;
4855 {FALSE
, {WINED3D_TSS_INVALID
}}, /* 0, unused */
4856 {FALSE
, {WINED3D_TSS_COLOR_OP
}}, /* 1, D3DTSS_COLOROP */
4857 {FALSE
, {WINED3D_TSS_COLOR_ARG1
}}, /* 2, D3DTSS_COLORARG1 */
4858 {FALSE
, {WINED3D_TSS_COLOR_ARG2
}}, /* 3, D3DTSS_COLORARG2 */
4859 {FALSE
, {WINED3D_TSS_ALPHA_OP
}}, /* 4, D3DTSS_ALPHAOP */
4860 {FALSE
, {WINED3D_TSS_ALPHA_ARG1
}}, /* 5, D3DTSS_ALPHAARG1 */
4861 {FALSE
, {WINED3D_TSS_ALPHA_ARG2
}}, /* 6, D3DTSS_ALPHAARG2 */
4862 {FALSE
, {WINED3D_TSS_BUMPENV_MAT00
}}, /* 7, D3DTSS_BUMPENVMAT00 */
4863 {FALSE
, {WINED3D_TSS_BUMPENV_MAT01
}}, /* 8, D3DTSS_BUMPENVMAT01 */
4864 {FALSE
, {WINED3D_TSS_BUMPENV_MAT10
}}, /* 9, D3DTSS_BUMPENVMAT10 */
4865 {FALSE
, {WINED3D_TSS_BUMPENV_MAT11
}}, /* 10, D3DTSS_BUMPENVMAT11 */
4866 {FALSE
, {WINED3D_TSS_TEXCOORD_INDEX
}}, /* 11, D3DTSS_TEXCOORDINDEX */
4867 {TRUE
, {WINED3D_SAMP_ADDRESS_U
}}, /* 12, D3DTSS_ADDRESS */
4868 {TRUE
, {WINED3D_SAMP_ADDRESS_U
}}, /* 13, D3DTSS_ADDRESSU */
4869 {TRUE
, {WINED3D_SAMP_ADDRESS_V
}}, /* 14, D3DTSS_ADDRESSV */
4870 {TRUE
, {WINED3D_SAMP_BORDER_COLOR
}}, /* 15, D3DTSS_BORDERCOLOR */
4871 {TRUE
, {WINED3D_SAMP_MAG_FILTER
}}, /* 16, D3DTSS_MAGFILTER */
4872 {TRUE
, {WINED3D_SAMP_MIN_FILTER
}}, /* 17, D3DTSS_MINFILTER */
4873 {TRUE
, {WINED3D_SAMP_MIP_FILTER
}}, /* 18, D3DTSS_MIPFILTER */
4874 {TRUE
, {WINED3D_SAMP_MIPMAP_LOD_BIAS
}}, /* 19, D3DTSS_MIPMAPLODBIAS */
4875 {TRUE
, {WINED3D_SAMP_MAX_MIP_LEVEL
}}, /* 20, D3DTSS_MAXMIPLEVEL */
4876 {TRUE
, {WINED3D_SAMP_MAX_ANISOTROPY
}}, /* 21, D3DTSS_MAXANISOTROPY */
4877 {FALSE
, {WINED3D_TSS_BUMPENV_LSCALE
}}, /* 22, D3DTSS_BUMPENVLSCALE */
4878 {FALSE
, {WINED3D_TSS_BUMPENV_LOFFSET
}}, /* 23, D3DTSS_BUMPENVLOFFSET */
4879 {FALSE
, {WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS
}}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4882 /*****************************************************************************
4883 * IDirect3DDevice7::GetTextureStageState
4885 * Retrieves a state from a texture stage.
4890 * Stage: The stage to retrieve the state from
4891 * TexStageStateType: The state type to retrieve
4892 * State: Address to store the state's value at
4896 * DDERR_INVALIDPARAMS if State is NULL
4898 *****************************************************************************/
4899 static HRESULT
d3d_device7_GetTextureStageState(IDirect3DDevice7
*iface
,
4900 DWORD stage
, D3DTEXTURESTAGESTATETYPE state
, DWORD
*value
)
4902 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
4903 const struct tss_lookup
*l
;
4905 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4906 iface
, stage
, state
, value
);
4909 return DDERR_INVALIDPARAMS
;
4911 if (state
> D3DTSS_TEXTURETRANSFORMFLAGS
)
4913 WARN("Invalid state %#x passed.\n", state
);
4917 l
= &tss_lookup
[state
];
4919 wined3d_mutex_lock();
4921 if (l
->sampler_state
)
4923 *value
= wined3d_device_get_sampler_state(device
->wined3d_device
, stage
, l
->u
.sampler_state
);
4927 /* Mipfilter is a sampler state with different values */
4928 case D3DTSS_MIPFILTER
:
4932 case WINED3D_TEXF_NONE
:
4933 *value
= D3DTFP_NONE
;
4935 case WINED3D_TEXF_POINT
:
4936 *value
= D3DTFP_POINT
;
4938 case WINED3D_TEXF_LINEAR
:
4939 *value
= D3DTFP_LINEAR
;
4942 ERR("Unexpected mipfilter value %#x.\n", *value
);
4943 *value
= D3DTFP_NONE
;
4949 /* Magfilter has slightly different values */
4950 case D3DTSS_MAGFILTER
:
4954 case WINED3D_TEXF_POINT
:
4955 *value
= D3DTFG_POINT
;
4957 case WINED3D_TEXF_LINEAR
:
4958 *value
= D3DTFG_LINEAR
;
4960 case WINED3D_TEXF_ANISOTROPIC
:
4961 *value
= D3DTFG_ANISOTROPIC
;
4963 case WINED3D_TEXF_FLAT_CUBIC
:
4964 *value
= D3DTFG_FLATCUBIC
;
4966 case WINED3D_TEXF_GAUSSIAN_CUBIC
:
4967 *value
= D3DTFG_GAUSSIANCUBIC
;
4970 ERR("Unexpected wined3d mag filter value %#x.\n", *value
);
4971 *value
= D3DTFG_POINT
;
4983 *value
= wined3d_device_get_texture_stage_state(device
->wined3d_device
, stage
, l
->u
.texture_state
);
4986 wined3d_mutex_unlock();
4991 static HRESULT WINAPI
d3d_device7_GetTextureStageState_FPUSetup(IDirect3DDevice7
*iface
,
4992 DWORD stage
, D3DTEXTURESTAGESTATETYPE state
, DWORD
*value
)
4994 return d3d_device7_GetTextureStageState(iface
, stage
, state
, value
);
4997 static HRESULT WINAPI
d3d_device7_GetTextureStageState_FPUPreserve(IDirect3DDevice7
*iface
,
4998 DWORD stage
, D3DTEXTURESTAGESTATETYPE state
, DWORD
*value
)
5003 old_fpucw
= d3d_fpu_setup();
5004 hr
= d3d_device7_GetTextureStageState(iface
, stage
, state
, value
);
5005 set_fpu_control_word(old_fpucw
);
5010 static HRESULT WINAPI
d3d_device3_GetTextureStageState(IDirect3DDevice3
*iface
,
5011 DWORD stage
, D3DTEXTURESTAGESTATETYPE state
, DWORD
*value
)
5013 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
5015 TRACE("iface %p, stage %u, state %#x, value %p.\n",
5016 iface
, stage
, state
, value
);
5018 return IDirect3DDevice7_GetTextureStageState(&device
->IDirect3DDevice7_iface
, stage
, state
, value
);
5021 /*****************************************************************************
5022 * IDirect3DDevice7::SetTextureStageState
5024 * Sets a texture stage state. Some stage types need to be handled specially,
5025 * because they do not exist in WineD3D and were moved to another place
5030 * Stage: The stage to modify
5031 * TexStageStateType: The state to change
5032 * State: The new value for the state
5037 *****************************************************************************/
5038 static HRESULT
d3d_device7_SetTextureStageState(IDirect3DDevice7
*iface
,
5039 DWORD stage
, D3DTEXTURESTAGESTATETYPE state
, DWORD value
)
5041 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5042 const struct tss_lookup
*l
;
5044 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5045 iface
, stage
, state
, value
);
5047 if (state
> D3DTSS_TEXTURETRANSFORMFLAGS
)
5049 WARN("Invalid state %#x passed.\n", state
);
5053 l
= &tss_lookup
[state
];
5055 wined3d_mutex_lock();
5057 if (l
->sampler_state
)
5061 /* Mipfilter is a sampler state with different values */
5062 case D3DTSS_MIPFILTER
:
5067 value
= WINED3D_TEXF_NONE
;
5070 value
= WINED3D_TEXF_POINT
;
5072 case 0: /* Unchecked */
5074 value
= WINED3D_TEXF_LINEAR
;
5077 ERR("Unexpected mipfilter value %#x.\n", value
);
5078 value
= WINED3D_TEXF_NONE
;
5084 /* Magfilter has slightly different values */
5085 case D3DTSS_MAGFILTER
:
5090 value
= WINED3D_TEXF_POINT
;
5093 value
= WINED3D_TEXF_LINEAR
;
5095 case D3DTFG_FLATCUBIC
:
5096 value
= WINED3D_TEXF_FLAT_CUBIC
;
5098 case D3DTFG_GAUSSIANCUBIC
:
5099 value
= WINED3D_TEXF_GAUSSIAN_CUBIC
;
5101 case D3DTFG_ANISOTROPIC
:
5102 value
= WINED3D_TEXF_ANISOTROPIC
;
5105 ERR("Unexpected d3d7 mag filter value %#x.\n", value
);
5106 value
= WINED3D_TEXF_POINT
;
5112 case D3DTSS_ADDRESS
:
5113 wined3d_device_set_sampler_state(device
->wined3d_device
, stage
, WINED3D_SAMP_ADDRESS_V
, value
);
5120 wined3d_device_set_sampler_state(device
->wined3d_device
, stage
, l
->u
.sampler_state
, value
);
5124 wined3d_device_set_texture_stage_state(device
->wined3d_device
, stage
, l
->u
.texture_state
, value
);
5127 wined3d_mutex_unlock();
5132 static HRESULT WINAPI
d3d_device7_SetTextureStageState_FPUSetup(IDirect3DDevice7
*iface
,
5133 DWORD stage
, D3DTEXTURESTAGESTATETYPE state
, DWORD value
)
5135 return d3d_device7_SetTextureStageState(iface
, stage
, state
, value
);
5138 static HRESULT WINAPI
d3d_device7_SetTextureStageState_FPUPreserve(IDirect3DDevice7
*iface
,
5139 DWORD stage
, D3DTEXTURESTAGESTATETYPE state
, DWORD value
)
5144 old_fpucw
= d3d_fpu_setup();
5145 hr
= d3d_device7_SetTextureStageState(iface
, stage
, state
, value
);
5146 set_fpu_control_word(old_fpucw
);
5151 static HRESULT WINAPI
d3d_device3_SetTextureStageState(IDirect3DDevice3
*iface
,
5152 DWORD stage
, D3DTEXTURESTAGESTATETYPE state
, DWORD value
)
5154 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
5156 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5157 iface
, stage
, state
, value
);
5159 return IDirect3DDevice7_SetTextureStageState(&device
->IDirect3DDevice7_iface
, stage
, state
, value
);
5162 /*****************************************************************************
5163 * IDirect3DDevice7::ValidateDevice
5165 * SDK: "Reports the device's ability to render the currently set
5166 * texture-blending operations in a single pass". Whatever that means
5172 * NumPasses: Address to write the number of necessary passes for the
5173 * desired effect to.
5178 *****************************************************************************/
5179 static HRESULT
d3d_device7_ValidateDevice(IDirect3DDevice7
*iface
, DWORD
*pass_count
)
5181 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5184 TRACE("iface %p, pass_count %p.\n", iface
, pass_count
);
5186 wined3d_mutex_lock();
5187 hr
= wined3d_device_validate_device(device
->wined3d_device
, pass_count
);
5188 wined3d_mutex_unlock();
5193 static HRESULT WINAPI
d3d_device7_ValidateDevice_FPUSetup(IDirect3DDevice7
*iface
, DWORD
*pass_count
)
5195 return d3d_device7_ValidateDevice(iface
, pass_count
);
5198 static HRESULT WINAPI
d3d_device7_ValidateDevice_FPUPreserve(IDirect3DDevice7
*iface
, DWORD
*pass_count
)
5203 old_fpucw
= d3d_fpu_setup();
5204 hr
= d3d_device7_ValidateDevice(iface
, pass_count
);
5205 set_fpu_control_word(old_fpucw
);
5210 static HRESULT WINAPI
d3d_device3_ValidateDevice(IDirect3DDevice3
*iface
, DWORD
*pass_count
)
5212 struct d3d_device
*device
= impl_from_IDirect3DDevice3(iface
);
5214 TRACE("iface %p, pass_count %p.\n", iface
, pass_count
);
5216 return IDirect3DDevice7_ValidateDevice(&device
->IDirect3DDevice7_iface
, pass_count
);
5219 /*****************************************************************************
5220 * IDirect3DDevice7::Clear
5222 * Fills the render target, the z buffer and the stencil buffer with a
5223 * clear color / value
5228 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5229 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5230 * Flags: Some flags, as usual
5231 * Color: Clear color for the render target
5232 * Z: Clear value for the Z buffer
5233 * Stencil: Clear value to store in each stencil buffer entry
5238 *****************************************************************************/
5239 static HRESULT
d3d_device7_Clear(IDirect3DDevice7
*iface
, DWORD count
,
5240 D3DRECT
*rects
, DWORD flags
, D3DCOLOR color
, D3DVALUE z
, DWORD stencil
)
5242 const struct wined3d_color c
=
5244 ((color
>> 16) & 0xff) / 255.0f
,
5245 ((color
>> 8) & 0xff) / 255.0f
,
5246 (color
& 0xff) / 255.0f
,
5247 ((color
>> 24) & 0xff) / 255.0f
,
5249 struct d3d_device
*This
= impl_from_IDirect3DDevice7(iface
);
5252 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5253 iface
, count
, rects
, flags
, color
, z
, stencil
);
5255 if (count
&& !rects
)
5257 WARN("count %u with NULL rects.\n", count
);
5261 wined3d_mutex_lock();
5262 hr
= wined3d_device_clear(This
->wined3d_device
, count
, (RECT
*)rects
, flags
, &c
, z
, stencil
);
5263 wined3d_mutex_unlock();
5268 static HRESULT WINAPI
d3d_device7_Clear_FPUSetup(IDirect3DDevice7
*iface
, DWORD count
,
5269 D3DRECT
*rects
, DWORD flags
, D3DCOLOR color
, D3DVALUE z
, DWORD stencil
)
5271 return d3d_device7_Clear(iface
, count
, rects
, flags
, color
, z
, stencil
);
5274 static HRESULT WINAPI
d3d_device7_Clear_FPUPreserve(IDirect3DDevice7
*iface
, DWORD count
,
5275 D3DRECT
*rects
, DWORD flags
, D3DCOLOR color
, D3DVALUE z
, DWORD stencil
)
5280 old_fpucw
= d3d_fpu_setup();
5281 hr
= d3d_device7_Clear(iface
, count
, rects
, flags
, color
, z
, stencil
);
5282 set_fpu_control_word(old_fpucw
);
5287 /*****************************************************************************
5288 * IDirect3DDevice7::SetViewport
5290 * Sets the current viewport.
5292 * Version 7 only, but IDirect3DViewport uses this call for older
5296 * Data: The new viewport to set
5300 * DDERR_INVALIDPARAMS if Data is NULL
5302 *****************************************************************************/
5303 static HRESULT
d3d_device7_SetViewport(IDirect3DDevice7
*iface
, D3DVIEWPORT7
*viewport
)
5305 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5306 struct wined3d_viewport vp
;
5308 TRACE("iface %p, viewport %p.\n", iface
, viewport
);
5311 return DDERR_INVALIDPARAMS
;
5313 vp
.x
= viewport
->dwX
;
5314 vp
.y
= viewport
->dwY
;
5315 vp
.width
= viewport
->dwWidth
;
5316 vp
.height
= viewport
->dwHeight
;
5317 vp
.min_z
= viewport
->dvMinZ
;
5318 vp
.max_z
= viewport
->dvMaxZ
;
5320 wined3d_mutex_lock();
5321 wined3d_device_set_viewport(device
->wined3d_device
, &vp
);
5322 wined3d_mutex_unlock();
5327 static HRESULT WINAPI
d3d_device7_SetViewport_FPUSetup(IDirect3DDevice7
*iface
, D3DVIEWPORT7
*viewport
)
5329 return d3d_device7_SetViewport(iface
, viewport
);
5332 static HRESULT WINAPI
d3d_device7_SetViewport_FPUPreserve(IDirect3DDevice7
*iface
, D3DVIEWPORT7
*viewport
)
5337 old_fpucw
= d3d_fpu_setup();
5338 hr
= d3d_device7_SetViewport(iface
, viewport
);
5339 set_fpu_control_word(old_fpucw
);
5344 /*****************************************************************************
5345 * IDirect3DDevice::GetViewport
5347 * Returns the current viewport
5352 * Data: D3D7Viewport structure to write the viewport information to
5356 * DDERR_INVALIDPARAMS if Data is NULL
5358 *****************************************************************************/
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_device_get_viewport(device
->wined3d_device
, &wined3d_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_device_set_material(device
->wined3d_device
, (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 wined3d_device_get_material(device
->wined3d_device
, (struct wined3d_material
*)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_device_set_light(device
->wined3d_device
, light_idx
, (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
);
5560 TRACE("iface %p, light_idx %u, light %p.\n", iface
, light_idx
, light
);
5562 wined3d_mutex_lock();
5563 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5564 rc
= wined3d_device_get_light(device
->wined3d_device
, light_idx
, (struct wined3d_light
*)light
);
5565 wined3d_mutex_unlock();
5567 /* Translate the result. WineD3D returns other values than D3D7 */
5568 return hr_ddraw_from_wined3d(rc
);
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
);
5604 TRACE("iface %p.\n", iface
);
5606 wined3d_mutex_lock();
5607 hr
= wined3d_device_begin_stateblock(device
->wined3d_device
);
5608 wined3d_mutex_unlock();
5610 return hr_ddraw_from_wined3d(hr
);
5613 static HRESULT WINAPI
d3d_device7_BeginStateBlock_FPUSetup(IDirect3DDevice7
*iface
)
5615 return d3d_device7_BeginStateBlock(iface
);
5618 static HRESULT WINAPI
d3d_device7_BeginStateBlock_FPUPreserve(IDirect3DDevice7
*iface
)
5623 old_fpucw
= d3d_fpu_setup();
5624 hr
= d3d_device7_BeginStateBlock(iface
);
5625 set_fpu_control_word(old_fpucw
);
5630 /*****************************************************************************
5631 * IDirect3DDevice7::EndStateBlock
5633 * Stops recording to a state block and returns the created stateblock
5639 * BlockHandle: Address to store the stateblock's handle to
5643 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5645 *****************************************************************************/
5646 static HRESULT
d3d_device7_EndStateBlock(IDirect3DDevice7
*iface
, DWORD
*stateblock
)
5648 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5649 struct wined3d_stateblock
*wined3d_sb
;
5653 TRACE("iface %p, stateblock %p.\n", iface
, stateblock
);
5656 return DDERR_INVALIDPARAMS
;
5658 wined3d_mutex_lock();
5660 hr
= wined3d_device_end_stateblock(device
->wined3d_device
, &wined3d_sb
);
5663 WARN("Failed to end stateblock, hr %#x.\n", hr
);
5664 wined3d_mutex_unlock();
5666 return hr_ddraw_from_wined3d(hr
);
5669 h
= ddraw_allocate_handle(&device
->handle_table
, wined3d_sb
, DDRAW_HANDLE_STATEBLOCK
);
5670 if (h
== DDRAW_INVALID_HANDLE
)
5672 ERR("Failed to allocate a stateblock handle.\n");
5673 wined3d_stateblock_decref(wined3d_sb
);
5674 wined3d_mutex_unlock();
5676 return DDERR_OUTOFMEMORY
;
5679 wined3d_mutex_unlock();
5680 *stateblock
= h
+ 1;
5682 return hr_ddraw_from_wined3d(hr
);
5685 static HRESULT WINAPI
d3d_device7_EndStateBlock_FPUSetup(IDirect3DDevice7
*iface
, DWORD
*stateblock
)
5687 return d3d_device7_EndStateBlock(iface
, stateblock
);
5690 static HRESULT WINAPI
d3d_device7_EndStateBlock_FPUPreserve(IDirect3DDevice7
*iface
, DWORD
*stateblock
)
5695 old_fpucw
= d3d_fpu_setup();
5696 hr
= d3d_device7_EndStateBlock(iface
, stateblock
);
5697 set_fpu_control_word(old_fpucw
);
5702 /*****************************************************************************
5703 * IDirect3DDevice7::PreLoad
5705 * Allows the app to signal that a texture will be used soon, to allow
5706 * the Direct3DDevice to load it to the video card in the meantime.
5711 * Texture: The texture to preload
5715 * DDERR_INVALIDPARAMS if Texture is NULL
5717 *****************************************************************************/
5718 static HRESULT
d3d_device7_PreLoad(IDirect3DDevice7
*iface
, IDirectDrawSurface7
*texture
)
5720 struct ddraw_surface
*surface
= unsafe_impl_from_IDirectDrawSurface7(texture
);
5722 TRACE("iface %p, texture %p.\n", iface
, texture
);
5725 return DDERR_INVALIDPARAMS
;
5727 wined3d_mutex_lock();
5728 wined3d_resource_preload(wined3d_texture_get_resource(surface
->wined3d_texture
));
5729 wined3d_mutex_unlock();
5734 static HRESULT WINAPI
d3d_device7_PreLoad_FPUSetup(IDirect3DDevice7
*iface
, IDirectDrawSurface7
*texture
)
5736 return d3d_device7_PreLoad(iface
, texture
);
5739 static HRESULT WINAPI
d3d_device7_PreLoad_FPUPreserve(IDirect3DDevice7
*iface
, IDirectDrawSurface7
*texture
)
5744 old_fpucw
= d3d_fpu_setup();
5745 hr
= d3d_device7_PreLoad(iface
, texture
);
5746 set_fpu_control_word(old_fpucw
);
5751 /*****************************************************************************
5752 * IDirect3DDevice7::ApplyStateBlock
5754 * Activates the state stored in a state block handle.
5757 * BlockHandle: The stateblock handle to activate
5761 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5763 *****************************************************************************/
5764 static HRESULT
d3d_device7_ApplyStateBlock(IDirect3DDevice7
*iface
, DWORD stateblock
)
5766 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5767 struct wined3d_stateblock
*wined3d_sb
;
5769 TRACE("iface %p, stateblock %#x.\n", iface
, stateblock
);
5771 wined3d_mutex_lock();
5772 wined3d_sb
= ddraw_get_object(&device
->handle_table
, stateblock
- 1, DDRAW_HANDLE_STATEBLOCK
);
5775 WARN("Invalid stateblock handle.\n");
5776 wined3d_mutex_unlock();
5777 return D3DERR_INVALIDSTATEBLOCK
;
5780 wined3d_stateblock_apply(wined3d_sb
);
5781 wined3d_mutex_unlock();
5786 static HRESULT WINAPI
d3d_device7_ApplyStateBlock_FPUSetup(IDirect3DDevice7
*iface
, DWORD stateblock
)
5788 return d3d_device7_ApplyStateBlock(iface
, stateblock
);
5791 static HRESULT WINAPI
d3d_device7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7
*iface
, DWORD stateblock
)
5796 old_fpucw
= d3d_fpu_setup();
5797 hr
= d3d_device7_ApplyStateBlock(iface
, stateblock
);
5798 set_fpu_control_word(old_fpucw
);
5803 /*****************************************************************************
5804 * IDirect3DDevice7::CaptureStateBlock
5806 * Updates a stateblock's values to the values currently set for the device
5811 * BlockHandle: Stateblock to update
5815 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5817 *****************************************************************************/
5818 static HRESULT
d3d_device7_CaptureStateBlock(IDirect3DDevice7
*iface
, DWORD stateblock
)
5820 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5821 struct wined3d_stateblock
*wined3d_sb
;
5823 TRACE("iface %p, stateblock %#x.\n", iface
, stateblock
);
5825 wined3d_mutex_lock();
5826 wined3d_sb
= ddraw_get_object(&device
->handle_table
, stateblock
- 1, DDRAW_HANDLE_STATEBLOCK
);
5829 WARN("Invalid stateblock handle.\n");
5830 wined3d_mutex_unlock();
5831 return D3DERR_INVALIDSTATEBLOCK
;
5834 wined3d_stateblock_capture(wined3d_sb
);
5835 wined3d_mutex_unlock();
5840 static HRESULT WINAPI
d3d_device7_CaptureStateBlock_FPUSetup(IDirect3DDevice7
*iface
, DWORD stateblock
)
5842 return d3d_device7_CaptureStateBlock(iface
, stateblock
);
5845 static HRESULT WINAPI
d3d_device7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7
*iface
, DWORD stateblock
)
5850 old_fpucw
= d3d_fpu_setup();
5851 hr
= d3d_device7_CaptureStateBlock(iface
, stateblock
);
5852 set_fpu_control_word(old_fpucw
);
5857 /*****************************************************************************
5858 * IDirect3DDevice7::DeleteStateBlock
5860 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5865 * BlockHandle: Stateblock handle to delete
5869 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5871 *****************************************************************************/
5872 static HRESULT
d3d_device7_DeleteStateBlock(IDirect3DDevice7
*iface
, DWORD stateblock
)
5874 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5875 struct wined3d_stateblock
*wined3d_sb
;
5878 TRACE("iface %p, stateblock %#x.\n", iface
, stateblock
);
5880 wined3d_mutex_lock();
5882 wined3d_sb
= ddraw_free_handle(&device
->handle_table
, stateblock
- 1, DDRAW_HANDLE_STATEBLOCK
);
5885 WARN("Invalid stateblock handle.\n");
5886 wined3d_mutex_unlock();
5887 return D3DERR_INVALIDSTATEBLOCK
;
5890 if ((ref
= wined3d_stateblock_decref(wined3d_sb
)))
5892 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb
, ref
);
5895 wined3d_mutex_unlock();
5900 static HRESULT WINAPI
d3d_device7_DeleteStateBlock_FPUSetup(IDirect3DDevice7
*iface
, DWORD stateblock
)
5902 return d3d_device7_DeleteStateBlock(iface
, stateblock
);
5905 static HRESULT WINAPI
d3d_device7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7
*iface
, DWORD stateblock
)
5910 old_fpucw
= d3d_fpu_setup();
5911 hr
= d3d_device7_DeleteStateBlock(iface
, stateblock
);
5912 set_fpu_control_word(old_fpucw
);
5917 /*****************************************************************************
5918 * IDirect3DDevice7::CreateStateBlock
5920 * Creates a new state block handle.
5925 * Type: The state block type
5926 * BlockHandle: Address to write the created handle to
5930 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5932 *****************************************************************************/
5933 static HRESULT
d3d_device7_CreateStateBlock(IDirect3DDevice7
*iface
,
5934 D3DSTATEBLOCKTYPE type
, DWORD
*stateblock
)
5936 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
5937 struct wined3d_stateblock
*wined3d_sb
;
5941 TRACE("iface %p, type %#x, stateblock %p.\n", iface
, type
, stateblock
);
5944 return DDERR_INVALIDPARAMS
;
5946 if (type
!= D3DSBT_ALL
5947 && type
!= D3DSBT_PIXELSTATE
5948 && type
!= D3DSBT_VERTEXSTATE
)
5950 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5951 return DDERR_INVALIDPARAMS
;
5954 wined3d_mutex_lock();
5956 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5957 hr
= wined3d_stateblock_create(device
->wined3d_device
, type
, &wined3d_sb
);
5960 WARN("Failed to create stateblock, hr %#x.\n", hr
);
5961 wined3d_mutex_unlock();
5962 return hr_ddraw_from_wined3d(hr
);
5965 h
= ddraw_allocate_handle(&device
->handle_table
, wined3d_sb
, DDRAW_HANDLE_STATEBLOCK
);
5966 if (h
== DDRAW_INVALID_HANDLE
)
5968 ERR("Failed to allocate stateblock handle.\n");
5969 wined3d_stateblock_decref(wined3d_sb
);
5970 wined3d_mutex_unlock();
5971 return DDERR_OUTOFMEMORY
;
5974 *stateblock
= h
+ 1;
5975 wined3d_mutex_unlock();
5977 return hr_ddraw_from_wined3d(hr
);
5980 static HRESULT WINAPI
d3d_device7_CreateStateBlock_FPUSetup(IDirect3DDevice7
*iface
,
5981 D3DSTATEBLOCKTYPE type
, DWORD
*stateblock
)
5983 return d3d_device7_CreateStateBlock(iface
, type
, stateblock
);
5986 static HRESULT WINAPI
d3d_device7_CreateStateBlock_FPUPreserve(IDirect3DDevice7
*iface
,
5987 D3DSTATEBLOCKTYPE type
, DWORD
*stateblock
)
5992 old_fpucw
= d3d_fpu_setup();
5993 hr
= d3d_device7_CreateStateBlock(iface
, type
, stateblock
);
5994 set_fpu_control_word(old_fpucw
);
5999 static BOOL
is_mip_level_subset(struct ddraw_surface
*dest
, struct ddraw_surface
*src
)
6001 struct ddraw_surface
*src_level
, *dest_level
;
6002 IDirectDrawSurface7
*temp
;
6003 DDSURFACEDESC2 ddsd
;
6004 BOOL levelFound
; /* at least one suitable sublevel in dest found */
6006 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
6007 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
6008 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
6015 for (;src_level
&& dest_level
;)
6017 if (src_level
->surface_desc
.dwWidth
== dest_level
->surface_desc
.dwWidth
&&
6018 src_level
->surface_desc
.dwHeight
== dest_level
->surface_desc
.dwHeight
)
6022 ddsd
.ddsCaps
.dwCaps
= DDSCAPS_TEXTURE
;
6023 ddsd
.ddsCaps
.dwCaps2
= DDSCAPS2_MIPMAPSUBLEVEL
;
6024 IDirectDrawSurface7_GetAttachedSurface(&dest_level
->IDirectDrawSurface7_iface
, &ddsd
.ddsCaps
, &temp
);
6026 if (dest_level
!= dest
) IDirectDrawSurface7_Release(&dest_level
->IDirectDrawSurface7_iface
);
6028 dest_level
= unsafe_impl_from_IDirectDrawSurface7(temp
);
6031 ddsd
.ddsCaps
.dwCaps
= DDSCAPS_TEXTURE
;
6032 ddsd
.ddsCaps
.dwCaps2
= DDSCAPS2_MIPMAPSUBLEVEL
;
6033 IDirectDrawSurface7_GetAttachedSurface(&src_level
->IDirectDrawSurface7_iface
, &ddsd
.ddsCaps
, &temp
);
6035 if (src_level
!= src
) IDirectDrawSurface7_Release(&src_level
->IDirectDrawSurface7_iface
);
6037 src_level
= unsafe_impl_from_IDirectDrawSurface7(temp
);
6040 if (src_level
&& src_level
!= src
) IDirectDrawSurface7_Release(&src_level
->IDirectDrawSurface7_iface
);
6041 if (dest_level
&& dest_level
!= dest
) IDirectDrawSurface7_Release(&dest_level
->IDirectDrawSurface7_iface
);
6043 return !dest_level
&& levelFound
;
6046 static void copy_mipmap_chain(struct d3d_device
*device
, struct ddraw_surface
*dst
,
6047 struct ddraw_surface
*src
, const POINT
*DestPoint
, const RECT
*SrcRect
)
6049 struct ddraw_surface
*dst_level
, *src_level
;
6050 IDirectDrawSurface7
*temp
;
6051 DDSURFACEDESC2 ddsd
;
6055 IDirectDrawPalette
*pal
= NULL
, *pal_src
= NULL
;
6059 /* Copy palette, if possible. */
6060 IDirectDrawSurface7_GetPalette(&src
->IDirectDrawSurface7_iface
, &pal_src
);
6061 IDirectDrawSurface7_GetPalette(&dst
->IDirectDrawSurface7_iface
, &pal
);
6063 if (pal_src
!= NULL
&& pal
!= NULL
)
6065 PALETTEENTRY palent
[256];
6067 IDirectDrawPalette_GetEntries(pal_src
, 0, 0, 256, palent
);
6068 IDirectDrawPalette_SetEntries(pal
, 0, 0, 256, palent
);
6071 if (pal
) IDirectDrawPalette_Release(pal
);
6072 if (pal_src
) IDirectDrawPalette_Release(pal_src
);
6074 /* Copy colorkeys, if present. */
6075 for (ckeyflag
= DDCKEY_DESTBLT
; ckeyflag
<= DDCKEY_SRCOVERLAY
; ckeyflag
<<= 1)
6077 hr
= IDirectDrawSurface7_GetColorKey(&src
->IDirectDrawSurface7_iface
, ckeyflag
, &ddckey
);
6081 IDirectDrawSurface7_SetColorKey(&dst
->IDirectDrawSurface7_iface
, ckeyflag
, &ddckey
);
6089 src_rect
= *SrcRect
;
6091 for (;src_level
&& dst_level
;)
6093 if (src_level
->surface_desc
.dwWidth
== dst_level
->surface_desc
.dwWidth
6094 && src_level
->surface_desc
.dwHeight
== dst_level
->surface_desc
.dwHeight
)
6096 UINT src_w
= src_rect
.right
- src_rect
.left
;
6097 UINT src_h
= src_rect
.bottom
- src_rect
.top
;
6098 RECT dst_rect
= {point
.x
, point
.y
, point
.x
+ src_w
, point
.y
+ src_h
};
6100 if (FAILED(hr
= wined3d_texture_blt(dst_level
->wined3d_texture
, dst_level
->sub_resource_idx
, &dst_rect
,
6101 src_level
->wined3d_texture
, src_level
->sub_resource_idx
, &src_rect
, 0, NULL
, WINED3D_TEXF_POINT
)))
6102 ERR("Blit failed, hr %#x.\n", hr
);
6104 ddsd
.ddsCaps
.dwCaps
= DDSCAPS_TEXTURE
;
6105 ddsd
.ddsCaps
.dwCaps2
= DDSCAPS2_MIPMAPSUBLEVEL
;
6106 IDirectDrawSurface7_GetAttachedSurface(&dst_level
->IDirectDrawSurface7_iface
, &ddsd
.ddsCaps
, &temp
);
6108 if (dst_level
!= dst
)
6109 IDirectDrawSurface7_Release(&dst_level
->IDirectDrawSurface7_iface
);
6111 dst_level
= unsafe_impl_from_IDirectDrawSurface7(temp
);
6114 ddsd
.ddsCaps
.dwCaps
= DDSCAPS_TEXTURE
;
6115 ddsd
.ddsCaps
.dwCaps2
= DDSCAPS2_MIPMAPSUBLEVEL
;
6116 IDirectDrawSurface7_GetAttachedSurface(&src_level
->IDirectDrawSurface7_iface
, &ddsd
.ddsCaps
, &temp
);
6118 if (src_level
!= src
) IDirectDrawSurface7_Release(&src_level
->IDirectDrawSurface7_iface
);
6120 src_level
= unsafe_impl_from_IDirectDrawSurface7(temp
);
6127 src_rect
.right
= (src_rect
.right
+ 1) / 2;
6128 src_rect
.bottom
= (src_rect
.bottom
+ 1) / 2;
6131 if (src_level
&& src_level
!= src
)
6132 IDirectDrawSurface7_Release(&src_level
->IDirectDrawSurface7_iface
);
6133 if (dst_level
&& dst_level
!= dst
)
6134 IDirectDrawSurface7_Release(&dst_level
->IDirectDrawSurface7_iface
);
6137 /*****************************************************************************
6138 * IDirect3DDevice7::Load
6140 * Loads a rectangular area from the source into the destination texture.
6141 * It can also copy the source to the faces of a cubic environment map
6146 * DestTex: Destination texture
6147 * DestPoint: Point in the destination where the source image should be
6149 * SrcTex: Source texture
6150 * SrcRect: Source rectangle
6151 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6152 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6153 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6157 * DDERR_INVALIDPARAMS if dst_texture or src_texture is NULL, broken coordinates or anything unexpected.
6160 *****************************************************************************/
6161 static HRESULT
d3d_device7_Load(IDirect3DDevice7
*iface
, IDirectDrawSurface7
*dst_texture
, POINT
*dst_pos
,
6162 IDirectDrawSurface7
*src_texture
, RECT
*src_rect
, DWORD flags
)
6164 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
6165 struct ddraw_surface
*dest
= unsafe_impl_from_IDirectDrawSurface7(dst_texture
);
6166 struct ddraw_surface
*src
= unsafe_impl_from_IDirectDrawSurface7(src_texture
);
6170 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6171 iface
, dst_texture
, wine_dbgstr_point(dst_pos
), src_texture
, wine_dbgstr_rect(src_rect
), flags
);
6173 if( (!src
) || (!dest
) )
6174 return DDERR_INVALIDPARAMS
;
6176 wined3d_mutex_lock();
6179 SetRect(&srcrect
, 0, 0, src
->surface_desc
.dwWidth
, src
->surface_desc
.dwHeight
);
6181 srcrect
= *src_rect
;
6184 destpoint
.x
= destpoint
.y
= 0;
6186 destpoint
= *dst_pos
;
6188 /* Check bad dimensions. dst_pos is validated against src, not dest, because
6189 * destination can be a subset of mip levels, in which case actual coordinates used
6190 * for it may be divided. If any dimension of dest is larger than source, it can't be
6191 * mip level subset, so an error can be returned early.
6193 if (IsRectEmpty(&srcrect
) || srcrect
.right
> src
->surface_desc
.dwWidth
||
6194 srcrect
.bottom
> src
->surface_desc
.dwHeight
||
6195 destpoint
.x
+ srcrect
.right
- srcrect
.left
> src
->surface_desc
.dwWidth
||
6196 destpoint
.y
+ srcrect
.bottom
- srcrect
.top
> src
->surface_desc
.dwHeight
||
6197 dest
->surface_desc
.dwWidth
> src
->surface_desc
.dwWidth
||
6198 dest
->surface_desc
.dwHeight
> src
->surface_desc
.dwHeight
)
6200 wined3d_mutex_unlock();
6201 return DDERR_INVALIDPARAMS
;
6204 /* Must be top level surfaces. */
6205 if (src
->surface_desc
.ddsCaps
.dwCaps2
& DDSCAPS2_MIPMAPSUBLEVEL
||
6206 dest
->surface_desc
.ddsCaps
.dwCaps2
& DDSCAPS2_MIPMAPSUBLEVEL
)
6208 wined3d_mutex_unlock();
6209 return DDERR_INVALIDPARAMS
;
6212 if (src
->surface_desc
.ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP
)
6214 struct ddraw_surface
*src_face
, *dest_face
;
6215 DWORD src_face_flag
, dest_face_flag
;
6216 IDirectDrawSurface7
*temp
;
6217 DDSURFACEDESC2 ddsd
;
6220 if (!(dest
->surface_desc
.ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP
))
6222 wined3d_mutex_unlock();
6223 return DDERR_INVALIDPARAMS
;
6226 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6227 * time it's actual surface loading. */
6228 for (i
= 0; i
< 2; i
++)
6233 for (;dest_face
&& src_face
;)
6235 src_face_flag
= src_face
->surface_desc
.ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP_ALLFACES
;
6236 dest_face_flag
= dest_face
->surface_desc
.ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP_ALLFACES
;
6238 if (src_face_flag
== dest_face_flag
)
6242 /* Destination mip levels must be subset of source mip levels. */
6243 if (!is_mip_level_subset(dest_face
, src_face
))
6245 wined3d_mutex_unlock();
6246 return DDERR_INVALIDPARAMS
;
6249 else if (flags
& dest_face_flag
)
6251 copy_mipmap_chain(device
, dest_face
, src_face
, &destpoint
, &srcrect
);
6254 if (src_face_flag
< DDSCAPS2_CUBEMAP_NEGATIVEZ
)
6256 ddsd
.ddsCaps
.dwCaps
= DDSCAPS_TEXTURE
;
6257 ddsd
.ddsCaps
.dwCaps2
= DDSCAPS2_CUBEMAP
| (src_face_flag
<< 1);
6258 IDirectDrawSurface7_GetAttachedSurface(&src
->IDirectDrawSurface7_iface
, &ddsd
.ddsCaps
, &temp
);
6260 if (src_face
!= src
) IDirectDrawSurface7_Release(&src_face
->IDirectDrawSurface7_iface
);
6262 src_face
= unsafe_impl_from_IDirectDrawSurface7(temp
);
6266 if (src_face
!= src
) IDirectDrawSurface7_Release(&src_face
->IDirectDrawSurface7_iface
);
6272 if (dest_face_flag
< DDSCAPS2_CUBEMAP_NEGATIVEZ
)
6274 ddsd
.ddsCaps
.dwCaps
= DDSCAPS_TEXTURE
;
6275 ddsd
.ddsCaps
.dwCaps2
= DDSCAPS2_CUBEMAP
| (dest_face_flag
<< 1);
6276 IDirectDrawSurface7_GetAttachedSurface(&dest
->IDirectDrawSurface7_iface
, &ddsd
.ddsCaps
, &temp
);
6278 if (dest_face
!= dest
) IDirectDrawSurface7_Release(&dest_face
->IDirectDrawSurface7_iface
);
6280 dest_face
= unsafe_impl_from_IDirectDrawSurface7(temp
);
6284 if (dest_face
!= dest
) IDirectDrawSurface7_Release(&dest_face
->IDirectDrawSurface7_iface
);
6292 /* Native returns error if src faces are not subset of dest faces. */
6295 wined3d_mutex_unlock();
6296 return DDERR_INVALIDPARAMS
;
6301 wined3d_mutex_unlock();
6304 else if (dest
->surface_desc
.ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP
)
6306 wined3d_mutex_unlock();
6307 return DDERR_INVALIDPARAMS
;
6310 /* Handle non cube map textures. */
6312 /* Destination mip levels must be subset of source mip levels. */
6313 if (!is_mip_level_subset(dest
, src
))
6315 wined3d_mutex_unlock();
6316 return DDERR_INVALIDPARAMS
;
6319 copy_mipmap_chain(device
, dest
, src
, &destpoint
, &srcrect
);
6321 wined3d_mutex_unlock();
6326 static HRESULT WINAPI
d3d_device7_Load_FPUSetup(IDirect3DDevice7
*iface
, IDirectDrawSurface7
*dst_texture
,
6327 POINT
*dst_pos
, IDirectDrawSurface7
*src_texture
, RECT
*src_rect
, DWORD flags
)
6329 return d3d_device7_Load(iface
, dst_texture
, dst_pos
, src_texture
, src_rect
, flags
);
6332 static HRESULT WINAPI
d3d_device7_Load_FPUPreserve(IDirect3DDevice7
*iface
, IDirectDrawSurface7
*dst_texture
,
6333 POINT
*dst_pos
, IDirectDrawSurface7
*src_texture
, RECT
*src_rect
, DWORD flags
)
6338 old_fpucw
= d3d_fpu_setup();
6339 hr
= d3d_device7_Load(iface
, dst_texture
, dst_pos
, src_texture
, src_rect
, flags
);
6340 set_fpu_control_word(old_fpucw
);
6345 /*****************************************************************************
6346 * IDirect3DDevice7::LightEnable
6348 * Enables or disables a light
6350 * Version 7, IDirect3DLight uses this method too.
6353 * LightIndex: The index of the light to enable / disable
6354 * Enable: Enable or disable the light
6359 *****************************************************************************/
6360 static HRESULT
d3d_device7_LightEnable(IDirect3DDevice7
*iface
, DWORD light_idx
, BOOL enabled
)
6362 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
6365 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface
, light_idx
, enabled
);
6367 wined3d_mutex_lock();
6368 hr
= wined3d_device_set_light_enable(device
->wined3d_device
, light_idx
, enabled
);
6369 wined3d_mutex_unlock();
6371 return hr_ddraw_from_wined3d(hr
);
6374 static HRESULT WINAPI
d3d_device7_LightEnable_FPUSetup(IDirect3DDevice7
*iface
, DWORD light_idx
, BOOL enabled
)
6376 return d3d_device7_LightEnable(iface
, light_idx
, enabled
);
6379 static HRESULT WINAPI
d3d_device7_LightEnable_FPUPreserve(IDirect3DDevice7
*iface
, DWORD light_idx
, BOOL enabled
)
6384 old_fpucw
= d3d_fpu_setup();
6385 hr
= d3d_device7_LightEnable(iface
, light_idx
, enabled
);
6386 set_fpu_control_word(old_fpucw
);
6391 /*****************************************************************************
6392 * IDirect3DDevice7::GetLightEnable
6394 * Retrieves if the light with the given index is enabled or not
6399 * LightIndex: Index of desired light
6400 * Enable: Pointer to a BOOL which contains the result
6404 * DDERR_INVALIDPARAMS if Enable is NULL
6406 *****************************************************************************/
6407 static HRESULT
d3d_device7_GetLightEnable(IDirect3DDevice7
*iface
, DWORD light_idx
, BOOL
*enabled
)
6409 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
6412 TRACE("iface %p, light_idx %u, enabled %p.\n", iface
, light_idx
, enabled
);
6415 return DDERR_INVALIDPARAMS
;
6417 wined3d_mutex_lock();
6418 hr
= wined3d_device_get_light_enable(device
->wined3d_device
, light_idx
, enabled
);
6419 wined3d_mutex_unlock();
6421 return hr_ddraw_from_wined3d(hr
);
6424 static HRESULT WINAPI
d3d_device7_GetLightEnable_FPUSetup(IDirect3DDevice7
*iface
, DWORD light_idx
, BOOL
*enabled
)
6426 return d3d_device7_GetLightEnable(iface
, light_idx
, enabled
);
6429 static HRESULT WINAPI
d3d_device7_GetLightEnable_FPUPreserve(IDirect3DDevice7
*iface
, DWORD light_idx
, BOOL
*enabled
)
6434 old_fpucw
= d3d_fpu_setup();
6435 hr
= d3d_device7_GetLightEnable(iface
, light_idx
, enabled
);
6436 set_fpu_control_word(old_fpucw
);
6441 /*****************************************************************************
6442 * IDirect3DDevice7::SetClipPlane
6444 * Sets custom clipping plane
6449 * Index: The index of the clipping plane
6450 * PlaneEquation: An equation defining the clipping plane
6454 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6456 *****************************************************************************/
6457 static HRESULT
d3d_device7_SetClipPlane(IDirect3DDevice7
*iface
, DWORD idx
, D3DVALUE
*plane
)
6459 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
6462 TRACE("iface %p, idx %u, plane %p.\n", iface
, idx
, plane
);
6465 return DDERR_INVALIDPARAMS
;
6467 wined3d_mutex_lock();
6468 hr
= wined3d_device_set_clip_plane(device
->wined3d_device
, idx
, (struct wined3d_vec4
*)plane
);
6469 wined3d_mutex_unlock();
6474 static HRESULT WINAPI
d3d_device7_SetClipPlane_FPUSetup(IDirect3DDevice7
*iface
, DWORD idx
, D3DVALUE
*plane
)
6476 return d3d_device7_SetClipPlane(iface
, idx
, plane
);
6479 static HRESULT WINAPI
d3d_device7_SetClipPlane_FPUPreserve(IDirect3DDevice7
*iface
, DWORD idx
, D3DVALUE
*plane
)
6484 old_fpucw
= d3d_fpu_setup();
6485 hr
= d3d_device7_SetClipPlane(iface
, idx
, plane
);
6486 set_fpu_control_word(old_fpucw
);
6491 /*****************************************************************************
6492 * IDirect3DDevice7::GetClipPlane
6494 * Returns the clipping plane with a specific index
6497 * Index: The index of the desired plane
6498 * PlaneEquation: Address to store the plane equation to
6502 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6504 *****************************************************************************/
6505 static HRESULT
d3d_device7_GetClipPlane(IDirect3DDevice7
*iface
, DWORD idx
, D3DVALUE
*plane
)
6507 struct d3d_device
*device
= impl_from_IDirect3DDevice7(iface
);
6510 TRACE("iface %p, idx %u, plane %p.\n", iface
, idx
, plane
);
6513 return DDERR_INVALIDPARAMS
;
6515 wined3d_mutex_lock();
6516 hr
= wined3d_device_get_clip_plane(device
->wined3d_device
, idx
, (struct wined3d_vec4
*)plane
);
6517 wined3d_mutex_unlock();
6522 static HRESULT WINAPI
d3d_device7_GetClipPlane_FPUSetup(IDirect3DDevice7
*iface
, DWORD idx
, D3DVALUE
*plane
)
6524 return d3d_device7_GetClipPlane(iface
, idx
, plane
);
6527 static HRESULT WINAPI
d3d_device7_GetClipPlane_FPUPreserve(IDirect3DDevice7
*iface
, DWORD idx
, D3DVALUE
*plane
)
6532 old_fpucw
= d3d_fpu_setup();
6533 hr
= d3d_device7_GetClipPlane(iface
, idx
, plane
);
6534 set_fpu_control_word(old_fpucw
);
6539 /*****************************************************************************
6540 * IDirect3DDevice7::GetInfo
6542 * Retrieves some information about the device. The DirectX sdk says that
6543 * this version returns S_FALSE for all retail builds of DirectX, that's what
6544 * this implementation does.
6547 * DevInfoID: Information type requested
6548 * DevInfoStruct: Pointer to a structure to store the info to
6549 * Size: Size of the structure
6552 * S_FALSE, because it's a non-debug driver
6554 *****************************************************************************/
6555 static HRESULT WINAPI
d3d_device7_GetInfo(IDirect3DDevice7
*iface
, DWORD info_id
, void *info
, DWORD info_size
)
6557 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6558 iface
, info_id
, info
, info_size
);
6560 if (TRACE_ON(ddraw
))
6562 TRACE(" info requested : ");
6565 case D3DDEVINFOID_TEXTUREMANAGER
: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6566 case D3DDEVINFOID_D3DTEXTUREMANAGER
: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6567 case D3DDEVINFOID_TEXTURING
: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6568 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS
;
6572 return S_FALSE
; /* According to MSDN, this is valid for a non-debug driver */
6575 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6576 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6577 * are not duplicated.
6579 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6580 * has already been setup for optimal d3d operation.
6582 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6583 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6584 * by Sacrifice (game). */
6585 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl
=
6587 /*** IUnknown Methods ***/
6588 d3d_device7_QueryInterface
,
6590 d3d_device7_Release
,
6591 /*** IDirect3DDevice7 ***/
6592 d3d_device7_GetCaps_FPUSetup
,
6593 d3d_device7_EnumTextureFormats_FPUSetup
,
6594 d3d_device7_BeginScene_FPUSetup
,
6595 d3d_device7_EndScene_FPUSetup
,
6596 d3d_device7_GetDirect3D
,
6597 d3d_device7_SetRenderTarget_FPUSetup
,
6598 d3d_device7_GetRenderTarget
,
6599 d3d_device7_Clear_FPUSetup
,
6600 d3d_device7_SetTransform_FPUSetup
,
6601 d3d_device7_GetTransform_FPUSetup
,
6602 d3d_device7_SetViewport_FPUSetup
,
6603 d3d_device7_MultiplyTransform_FPUSetup
,
6604 d3d_device7_GetViewport_FPUSetup
,
6605 d3d_device7_SetMaterial_FPUSetup
,
6606 d3d_device7_GetMaterial_FPUSetup
,
6607 d3d_device7_SetLight_FPUSetup
,
6608 d3d_device7_GetLight_FPUSetup
,
6609 d3d_device7_SetRenderState_FPUSetup
,
6610 d3d_device7_GetRenderState_FPUSetup
,
6611 d3d_device7_BeginStateBlock_FPUSetup
,
6612 d3d_device7_EndStateBlock_FPUSetup
,
6613 d3d_device7_PreLoad_FPUSetup
,
6614 d3d_device7_DrawPrimitive_FPUSetup
,
6615 d3d_device7_DrawIndexedPrimitive_FPUSetup
,
6616 d3d_device7_SetClipStatus
,
6617 d3d_device7_GetClipStatus
,
6618 d3d_device7_DrawPrimitiveStrided_FPUSetup
,
6619 d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup
,
6620 d3d_device7_DrawPrimitiveVB_FPUSetup
,
6621 d3d_device7_DrawIndexedPrimitiveVB_FPUSetup
,
6622 d3d_device7_ComputeSphereVisibility
,
6623 d3d_device7_GetTexture_FPUSetup
,
6624 d3d_device7_SetTexture_FPUSetup
,
6625 d3d_device7_GetTextureStageState_FPUSetup
,
6626 d3d_device7_SetTextureStageState_FPUSetup
,
6627 d3d_device7_ValidateDevice_FPUSetup
,
6628 d3d_device7_ApplyStateBlock_FPUSetup
,
6629 d3d_device7_CaptureStateBlock_FPUSetup
,
6630 d3d_device7_DeleteStateBlock_FPUSetup
,
6631 d3d_device7_CreateStateBlock_FPUSetup
,
6632 d3d_device7_Load_FPUSetup
,
6633 d3d_device7_LightEnable_FPUSetup
,
6634 d3d_device7_GetLightEnable_FPUSetup
,
6635 d3d_device7_SetClipPlane_FPUSetup
,
6636 d3d_device7_GetClipPlane_FPUSetup
,
6640 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl
=
6642 /*** IUnknown Methods ***/
6643 d3d_device7_QueryInterface
,
6645 d3d_device7_Release
,
6646 /*** IDirect3DDevice7 ***/
6647 d3d_device7_GetCaps_FPUPreserve
,
6648 d3d_device7_EnumTextureFormats_FPUPreserve
,
6649 d3d_device7_BeginScene_FPUPreserve
,
6650 d3d_device7_EndScene_FPUPreserve
,
6651 d3d_device7_GetDirect3D
,
6652 d3d_device7_SetRenderTarget_FPUPreserve
,
6653 d3d_device7_GetRenderTarget
,
6654 d3d_device7_Clear_FPUPreserve
,
6655 d3d_device7_SetTransform_FPUPreserve
,
6656 d3d_device7_GetTransform_FPUPreserve
,
6657 d3d_device7_SetViewport_FPUPreserve
,
6658 d3d_device7_MultiplyTransform_FPUPreserve
,
6659 d3d_device7_GetViewport_FPUPreserve
,
6660 d3d_device7_SetMaterial_FPUPreserve
,
6661 d3d_device7_GetMaterial_FPUPreserve
,
6662 d3d_device7_SetLight_FPUPreserve
,
6663 d3d_device7_GetLight_FPUPreserve
,
6664 d3d_device7_SetRenderState_FPUPreserve
,
6665 d3d_device7_GetRenderState_FPUPreserve
,
6666 d3d_device7_BeginStateBlock_FPUPreserve
,
6667 d3d_device7_EndStateBlock_FPUPreserve
,
6668 d3d_device7_PreLoad_FPUPreserve
,
6669 d3d_device7_DrawPrimitive_FPUPreserve
,
6670 d3d_device7_DrawIndexedPrimitive_FPUPreserve
,
6671 d3d_device7_SetClipStatus
,
6672 d3d_device7_GetClipStatus
,
6673 d3d_device7_DrawPrimitiveStrided_FPUPreserve
,
6674 d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve
,
6675 d3d_device7_DrawPrimitiveVB_FPUPreserve
,
6676 d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve
,
6677 d3d_device7_ComputeSphereVisibility
,
6678 d3d_device7_GetTexture_FPUPreserve
,
6679 d3d_device7_SetTexture_FPUPreserve
,
6680 d3d_device7_GetTextureStageState_FPUPreserve
,
6681 d3d_device7_SetTextureStageState_FPUPreserve
,
6682 d3d_device7_ValidateDevice_FPUPreserve
,
6683 d3d_device7_ApplyStateBlock_FPUPreserve
,
6684 d3d_device7_CaptureStateBlock_FPUPreserve
,
6685 d3d_device7_DeleteStateBlock_FPUPreserve
,
6686 d3d_device7_CreateStateBlock_FPUPreserve
,
6687 d3d_device7_Load_FPUPreserve
,
6688 d3d_device7_LightEnable_FPUPreserve
,
6689 d3d_device7_GetLightEnable_FPUPreserve
,
6690 d3d_device7_SetClipPlane_FPUPreserve
,
6691 d3d_device7_GetClipPlane_FPUPreserve
,
6695 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl
=
6697 /*** IUnknown Methods ***/
6698 d3d_device3_QueryInterface
,
6700 d3d_device3_Release
,
6701 /*** IDirect3DDevice3 ***/
6702 d3d_device3_GetCaps
,
6703 d3d_device3_GetStats
,
6704 d3d_device3_AddViewport
,
6705 d3d_device3_DeleteViewport
,
6706 d3d_device3_NextViewport
,
6707 d3d_device3_EnumTextureFormats
,
6708 d3d_device3_BeginScene
,
6709 d3d_device3_EndScene
,
6710 d3d_device3_GetDirect3D
,
6711 d3d_device3_SetCurrentViewport
,
6712 d3d_device3_GetCurrentViewport
,
6713 d3d_device3_SetRenderTarget
,
6714 d3d_device3_GetRenderTarget
,
6716 d3d_device3_BeginIndexed
,
6720 d3d_device3_GetRenderState
,
6721 d3d_device3_SetRenderState
,
6722 d3d_device3_GetLightState
,
6723 d3d_device3_SetLightState
,
6724 d3d_device3_SetTransform
,
6725 d3d_device3_GetTransform
,
6726 d3d_device3_MultiplyTransform
,
6727 d3d_device3_DrawPrimitive
,
6728 d3d_device3_DrawIndexedPrimitive
,
6729 d3d_device3_SetClipStatus
,
6730 d3d_device3_GetClipStatus
,
6731 d3d_device3_DrawPrimitiveStrided
,
6732 d3d_device3_DrawIndexedPrimitiveStrided
,
6733 d3d_device3_DrawPrimitiveVB
,
6734 d3d_device3_DrawIndexedPrimitiveVB
,
6735 d3d_device3_ComputeSphereVisibility
,
6736 d3d_device3_GetTexture
,
6737 d3d_device3_SetTexture
,
6738 d3d_device3_GetTextureStageState
,
6739 d3d_device3_SetTextureStageState
,
6740 d3d_device3_ValidateDevice
6743 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl
=
6745 /*** IUnknown Methods ***/
6746 d3d_device2_QueryInterface
,
6748 d3d_device2_Release
,
6749 /*** IDirect3DDevice2 ***/
6750 d3d_device2_GetCaps
,
6751 d3d_device2_SwapTextureHandles
,
6752 d3d_device2_GetStats
,
6753 d3d_device2_AddViewport
,
6754 d3d_device2_DeleteViewport
,
6755 d3d_device2_NextViewport
,
6756 d3d_device2_EnumTextureFormats
,
6757 d3d_device2_BeginScene
,
6758 d3d_device2_EndScene
,
6759 d3d_device2_GetDirect3D
,
6760 d3d_device2_SetCurrentViewport
,
6761 d3d_device2_GetCurrentViewport
,
6762 d3d_device2_SetRenderTarget
,
6763 d3d_device2_GetRenderTarget
,
6765 d3d_device2_BeginIndexed
,
6769 d3d_device2_GetRenderState
,
6770 d3d_device2_SetRenderState
,
6771 d3d_device2_GetLightState
,
6772 d3d_device2_SetLightState
,
6773 d3d_device2_SetTransform
,
6774 d3d_device2_GetTransform
,
6775 d3d_device2_MultiplyTransform
,
6776 d3d_device2_DrawPrimitive
,
6777 d3d_device2_DrawIndexedPrimitive
,
6778 d3d_device2_SetClipStatus
,
6779 d3d_device2_GetClipStatus
6782 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl
=
6784 /*** IUnknown Methods ***/
6785 d3d_device1_QueryInterface
,
6787 d3d_device1_Release
,
6788 /*** IDirect3DDevice1 ***/
6789 d3d_device1_Initialize
,
6790 d3d_device1_GetCaps
,
6791 d3d_device1_SwapTextureHandles
,
6792 d3d_device1_CreateExecuteBuffer
,
6793 d3d_device1_GetStats
,
6794 d3d_device1_Execute
,
6795 d3d_device1_AddViewport
,
6796 d3d_device1_DeleteViewport
,
6797 d3d_device1_NextViewport
,
6799 d3d_device1_GetPickRecords
,
6800 d3d_device1_EnumTextureFormats
,
6801 d3d_device1_CreateMatrix
,
6802 d3d_device1_SetMatrix
,
6803 d3d_device1_GetMatrix
,
6804 d3d_device1_DeleteMatrix
,
6805 d3d_device1_BeginScene
,
6806 d3d_device1_EndScene
,
6807 d3d_device1_GetDirect3D
6810 static const struct IUnknownVtbl d3d_device_inner_vtbl
=
6812 d3d_device_inner_QueryInterface
,
6813 d3d_device_inner_AddRef
,
6814 d3d_device_inner_Release
,
6817 struct d3d_device
*unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7
*iface
)
6819 if (!iface
) return NULL
;
6820 assert((iface
->lpVtbl
== &d3d_device7_fpu_preserve_vtbl
) || (iface
->lpVtbl
== &d3d_device7_fpu_setup_vtbl
));
6821 return CONTAINING_RECORD(iface
, struct d3d_device
, IDirect3DDevice7_iface
);
6824 struct d3d_device
*unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3
*iface
)
6826 if (!iface
) return NULL
;
6827 assert(iface
->lpVtbl
== &d3d_device3_vtbl
);
6828 return CONTAINING_RECORD(iface
, struct d3d_device
, IDirect3DDevice3_iface
);
6831 struct d3d_device
*unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2
*iface
)
6833 if (!iface
) return NULL
;
6834 assert(iface
->lpVtbl
== &d3d_device2_vtbl
);
6835 return CONTAINING_RECORD(iface
, struct d3d_device
, IDirect3DDevice2_iface
);
6838 struct d3d_device
*unsafe_impl_from_IDirect3DDevice(IDirect3DDevice
*iface
)
6840 if (!iface
) return NULL
;
6841 assert(iface
->lpVtbl
== &d3d_device1_vtbl
);
6842 return CONTAINING_RECORD(iface
, struct d3d_device
, IDirect3DDevice_iface
);
6845 enum wined3d_depth_buffer_type
d3d_device_update_depth_stencil(struct d3d_device
*device
)
6847 IDirectDrawSurface7
*depthStencil
= NULL
;
6848 IDirectDrawSurface7
*render_target
;
6849 static DDSCAPS2 depthcaps
= { DDSCAPS_ZBUFFER
, 0, 0, {0} };
6850 struct ddraw_surface
*dsi
;
6852 if (device
->rt_iface
&& SUCCEEDED(IUnknown_QueryInterface(device
->rt_iface
,
6853 &IID_IDirectDrawSurface7
, (void **)&render_target
)))
6855 IDirectDrawSurface7_GetAttachedSurface(render_target
, &depthcaps
, &depthStencil
);
6856 IDirectDrawSurface7_Release(render_target
);
6860 TRACE("Setting wined3d depth stencil to NULL\n");
6861 wined3d_device_set_depth_stencil_view(device
->wined3d_device
, NULL
);
6862 return WINED3D_ZB_FALSE
;
6865 dsi
= impl_from_IDirectDrawSurface7(depthStencil
);
6866 wined3d_device_set_depth_stencil_view(device
->wined3d_device
,
6867 ddraw_surface_get_rendertarget_view(dsi
));
6869 IDirectDrawSurface7_Release(depthStencil
);
6870 return WINED3D_ZB_TRUE
;
6873 static HRESULT
d3d_device_init(struct d3d_device
*device
, struct ddraw
*ddraw
,
6874 struct ddraw_surface
*target
, IUnknown
*rt_iface
, UINT version
, IUnknown
*outer_unknown
)
6876 static const D3DMATRIX ident
=
6878 1.0f
, 0.0f
, 0.0f
, 0.0f
,
6879 0.0f
, 1.0f
, 0.0f
, 0.0f
,
6880 0.0f
, 0.0f
, 1.0f
, 0.0f
,
6881 0.0f
, 0.0f
, 0.0f
, 1.0f
,
6885 if (ddraw
->cooperative_level
& DDSCL_FPUPRESERVE
)
6886 device
->IDirect3DDevice7_iface
.lpVtbl
= &d3d_device7_fpu_preserve_vtbl
;
6888 device
->IDirect3DDevice7_iface
.lpVtbl
= &d3d_device7_fpu_setup_vtbl
;
6890 device
->IDirect3DDevice3_iface
.lpVtbl
= &d3d_device3_vtbl
;
6891 device
->IDirect3DDevice2_iface
.lpVtbl
= &d3d_device2_vtbl
;
6892 device
->IDirect3DDevice_iface
.lpVtbl
= &d3d_device1_vtbl
;
6893 device
->IUnknown_inner
.lpVtbl
= &d3d_device_inner_vtbl
;
6895 device
->version
= version
;
6898 device
->outer_unknown
= outer_unknown
;
6900 device
->outer_unknown
= &device
->IUnknown_inner
;
6902 device
->ddraw
= ddraw
;
6903 list_init(&device
->viewport_list
);
6905 if (!ddraw_handle_table_init(&device
->handle_table
, 64))
6907 ERR("Failed to initialize handle table.\n");
6908 return DDERR_OUTOFMEMORY
;
6911 device
->legacyTextureBlending
= FALSE
;
6912 device
->legacy_projection
= ident
;
6913 device
->legacy_clipspace
= ident
;
6915 /* This is for convenience. */
6916 device
->wined3d_device
= ddraw
->wined3d_device
;
6917 wined3d_device_incref(ddraw
->wined3d_device
);
6919 /* Render to the back buffer */
6920 if (FAILED(hr
= wined3d_device_set_rendertarget_view(ddraw
->wined3d_device
,
6921 0, ddraw_surface_get_rendertarget_view(target
), TRUE
)))
6923 ERR("Failed to set render target, hr %#x.\n", hr
);
6924 ddraw_handle_table_destroy(&device
->handle_table
);
6928 device
->rt_iface
= rt_iface
;
6930 IUnknown_AddRef(device
->rt_iface
);
6932 ddraw
->d3ddevice
= device
;
6934 wined3d_device_set_render_state(ddraw
->wined3d_device
, WINED3D_RS_ZENABLE
,
6935 d3d_device_update_depth_stencil(device
));
6936 if (version
== 1) /* Color keying is initially enabled for version 1 devices. */
6937 wined3d_device_set_render_state(ddraw
->wined3d_device
, WINED3D_RS_COLORKEYENABLE
, TRUE
);
6938 else if (version
== 2)
6939 wined3d_device_set_render_state(ddraw
->wined3d_device
, WINED3D_RS_SPECULARENABLE
, TRUE
);
6941 wined3d_device_set_render_state(ddraw
->wined3d_device
, WINED3D_RS_NORMALIZENORMALS
, TRUE
);
6946 HRESULT
d3d_device_create(struct ddraw
*ddraw
, struct ddraw_surface
*target
, IUnknown
*rt_iface
,
6947 UINT version
, struct d3d_device
**device
, IUnknown
*outer_unknown
)
6949 struct d3d_device
*object
;
6952 TRACE("ddraw %p, target %p, version %u, device %p, outer_unknown %p.\n",
6953 ddraw
, target
, version
, device
, outer_unknown
);
6955 if (!(target
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_3DDEVICE
)
6956 || (target
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_ZBUFFER
))
6958 WARN("Surface %p is not a render target.\n", target
);
6959 return DDERR_INVALIDCAPS
;
6962 if (!validate_surface_palette(target
))
6964 WARN("Surface %p has an indexed pixel format, but no palette.\n", target
);
6965 return DDERR_NOPALETTEATTACHED
;
6968 if (!(target
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_VIDEOMEMORY
))
6970 WARN("Surface %p is not in video memory.\n", target
);
6971 return D3DERR_SURFACENOTINVIDMEM
;
6974 if (ddraw
->flags
& DDRAW_NO3D
)
6976 ERR_(winediag
)("The application wants to create a Direct3D device, "
6977 "but the current DirectDrawRenderer does not support this.\n");
6982 if (ddraw
->d3ddevice
)
6984 FIXME("Only one Direct3D device per DirectDraw object supported.\n");
6985 return DDERR_INVALIDPARAMS
;
6988 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
6991 ERR("Failed to allocate device memory.\n");
6992 return DDERR_OUTOFMEMORY
;
6995 if (FAILED(hr
= d3d_device_init(object
, ddraw
, target
, rt_iface
, version
, outer_unknown
)))
6997 WARN("Failed to initialize device, hr %#x.\n", hr
);
6998 HeapFree(GetProcessHeap(), 0, object
);
7002 TRACE("Created device %p.\n", object
);